modernc.org/ccgo/v3@v3.16.14/lib/testdata/gcc-9.1.0/gcc/testsuite/gcc.c-torture/execute/20040703-1.c (about)

     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  }