(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.c-torture/
execute/
20040703-1.c
       1  /* PR 16341 */
       2  /* { dg-require-effective-target int32plus } */
       3  
       4  #define PART_PRECISION (sizeof (cpp_num_part) * 8)
       5  
       6  typedef unsigned int cpp_num_part;
       7  typedef struct cpp_num cpp_num;
       8  struct cpp_num
       9  {
      10     cpp_num_part high;
      11     cpp_num_part low;
      12     int unsignedp;  /* True if value should be treated as unsigned.  */
      13     int overflow;   /* True if the most recent calculation overflowed.  */
      14  };
      15  
      16  static  int
      17  num_positive (cpp_num num, unsigned int precision)
      18  {
      19     if (precision > PART_PRECISION)
      20       {
      21         precision -= PART_PRECISION;
      22         return (num.high & (cpp_num_part) 1 << (precision - 1)) == 0;
      23       }
      24  
      25     return (num.low & (cpp_num_part) 1 << (precision - 1)) == 0;
      26  }
      27  
      28  static cpp_num
      29  num_trim (cpp_num num, unsigned int precision)
      30  {
      31     if (precision > PART_PRECISION)
      32       {
      33         precision -= PART_PRECISION;
      34         if (precision < PART_PRECISION)
      35           num.high &= ((cpp_num_part) 1 << precision) - 1;
      36       }
      37     else
      38       {
      39         if (precision < PART_PRECISION)
      40           num.low &= ((cpp_num_part) 1 << precision) - 1;
      41         num.high = 0;
      42       }
      43  
      44     return num;
      45  }
      46  
      47  /* Shift NUM, of width PRECISION, right by N bits.  */
      48  static cpp_num
      49  num_rshift (cpp_num num, unsigned int precision, unsigned int n)
      50  {
      51     cpp_num_part sign_mask;
      52     int x = num_positive (num, precision);
      53  
      54     if (num.unsignedp || x)
      55       sign_mask = 0;
      56     else
      57       sign_mask = ~(cpp_num_part) 0;
      58  
      59     if (n >= precision)
      60       num.high = num.low = sign_mask;
      61     else
      62       {
      63         /* Sign-extend.  */
      64         if (precision < PART_PRECISION)
      65           num.high = sign_mask, num.low |= sign_mask << precision;
      66         else if (precision < 2 * PART_PRECISION)
      67           num.high |= sign_mask << (precision - PART_PRECISION);
      68  
      69         if (n >= PART_PRECISION)
      70           {
      71             n -= PART_PRECISION;
      72             num.low = num.high;
      73             num.high = sign_mask;
      74           }
      75  
      76         if (n)
      77           {
      78             num.low = (num.low >> n) | (num.high << (PART_PRECISION - n));
      79             num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n));
      80           }
      81       }
      82  
      83     num = num_trim (num, precision);
      84     num.overflow = 0;
      85     return num;
      86  }
      87                                #define num_zerop(num) ((num.low | num.high) == 0)
      88  #define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
      89  
      90  cpp_num
      91  num_lshift (cpp_num num, unsigned int precision, unsigned int n)
      92  {
      93     if (n >= precision)
      94       {
      95         num.overflow = !num.unsignedp && !num_zerop (num);
      96         num.high = num.low = 0;
      97       }
      98     else
      99       {
     100         cpp_num orig;
     101         unsigned int m = n;
     102  
     103         orig = num;
     104         if (m >= PART_PRECISION)
     105           {
     106             m -= PART_PRECISION;
     107             num.high = num.low;
     108             num.low = 0;
     109           }
     110         if (m)
     111           {
     112             num.high = (num.high << m) | (num.low >> (PART_PRECISION - m));
     113             num.low <<= m;
     114           }
     115         num = num_trim (num, precision);
     116  
     117         if (num.unsignedp)
     118           num.overflow = 0;
     119         else
     120           {
     121             cpp_num maybe_orig = num_rshift (num, precision, n);
     122             num.overflow = !num_eq (orig, maybe_orig);
     123           }
     124       }
     125  
     126     return num;
     127  }
     128  
     129  unsigned int precision = 64;
     130  unsigned int n = 16;
     131  
     132  cpp_num num = { 0, 3, 0, 0 };
     133  
     134  int main()
     135  {
     136     cpp_num res = num_lshift (num, 64, n);
     137  
     138     if (res.low != 0x30000)
     139       abort ();
     140  
     141     if (res.high != 0)
     142       abort ();
     143  
     144     if (res.overflow != 0)
     145       abort ();
     146  
     147     exit (0);
     148  }