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 }