1.6.1.1.1.1.4. Addition and minus
Then for other operation, back in int_const_binop.
int_const_binop (continue)
1239 case PLUS_EXPR:
1240 overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
1241 break;
1242
1243 case MINUS_EXPR:
1244 neg_double (int2l, int2h, &low, &hi);
1245 add_double (int1l, int1h, low, hi, &low, &hi);
1246 overflow = OVERFLOW_SUM_SIGN (hi, int2h, int1h);
1247 break;
1248
1249 case MULT_EXPR:
1250 overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);
1251 break;
1252
1253 case TRUNC_DIV_EXPR:
1254 case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
1255 case EXACT_DIV_EXPR:
1256 /* This is a shortcut for a common special case. */
1257 if (int2h == 0 && (HOST_WIDE_INT) int2l > 0
1258 && ! TREE_CONSTANT_OVERFLOW (arg1)
1259 && ! TREE_CONSTANT_OVERFLOW (arg2)
1260 && int1h == 0 && (HOST_WIDE_INT) int1l >= 0)
1261 {
1262 if (code == CEIL_DIV_EXPR)
1263 int1l += int2l - 1;
1264
1265 low = int1l / int2l, hi = 0;
1266 break;
1267 }
1268
1269 /* ... fall through ... */
add_double accepts two operands, in its parameters, l1 a006Ed h1 are the low and high part of the first operand, so are l2 and h2 for second operand.
261 int
262 add_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, in fold-const.c
263 unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
264 unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
265 {
266 unsigned HOST_WIDE_INT l;
267 HOST_WIDE_INT h;
268
269 l = l1 + l2;
270 h = h1 + h2 + (l < l1);
271
272 *lv = l;
273 *hv = h;
274 return OVERFLOW_SUM_SIGN (h1, h2, h);
275 }
Above, if the sum of the low parts is smaller, it means carrier is produced for the sum, takes it into the high part at line 270. For high part, such case means overflow. Overflow occurs if A and B have the same sign, but A and SUM differ in sign. Below macro detects overflow by this way.
136 #define OVERFLOW_SUM_SIGN(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
neg_double is alittle tricky, it is because of the 2 complement reprensentation.
282 int
283 neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, in fold-const.c
284 unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
285 {
286 if (l1 == 0)
287 {
288 *lv = 0;
289 *hv = - h1;
290 return (*hv & h1) < 0;
291 }
292 else
293 {
294 *lv = -l1;
295 *hv = ~h1;
296 return 0;
297 }
298 }
1.6.1.1.1.1.5. Multiplication
While to implement effective and correct multiplication, it must carefully to deal with the problem of overflow as multiplication may double the size of operands.
307 int
308 mul_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, in fold-const.c
309 unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
310 unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
311 {
312 HOST_WIDE_INT arg1[4];
313 HOST_WIDE_INT arg2[4];
314 HOST_WIDE_INT prod[4 * 2];
315 unsigned HOST_WIDE_INT carry;
316 int i, j, k;
317 unsigned HOST_WIDE_INT toplow, neglow;
318 HOST_WIDE_INT tophigh, neghigh;
319
320 encode (arg1, l1, h1);
321 encode (arg2, l2, h2);
322
323 memset (prod, 0, sizeof prod);
324
325 for (i = 0; i < 4; i++)
326 {
327 carry = 0;
328 for (j = 0; j < 4; j++)
329 {
330 k = i + j;
331 /* This product is <= 0xFFFE0001, the sum <= 0xFFFF0000. */
332 carry += arg1[i] * arg2[j];
333 /* Since prod[p] < 0xFFFF, this sum <= 0xFFFFFFFF. */
334 carry += prod[k];
335 prod[k] = LOWPART (carry);
336 carry = HIGHPART (carry);
337 }
338 prod[i + 4] = carry;
339 }
340
341 decode (prod, lv, hv); /* This ignores prod[4] through prod[4*2-1] */
342
343 /* Check for overflow by calculating the top half of the answer in full;
344 it should agree with the low half's sign bit. */
345 decode (prod + 4, &toplow, &tophigh);
346 if (h1 < 0)
347 {
348 neg_double (l2, h2, &neglow, &neghigh);
349 add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
350 }
351 if (h2 < 0)
352 {
353 neg_double (l1, h1, &neglow, &neghigh);
354 add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
355 }
356 return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;
357 }
To handle the problem of overflow, encode at line 320 and 321 will put the operands into the buffer of double size.
153 static void in fold-const.c
154 encode (HOST_WIDE_INT *words, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
155 {
156 words[0] = LOWPART (low);
157 words[1] = HIGHPART (low);
158 words[2] = LOWPART (hi);
159 words[3] = HIGHPART (hi);
160 }
To see the operation in FOR loop at line 325 clearly, using following example to demonstrate the procedure. Assuming multiplication (decimal integer of size 2, and the result will be temperarily saved in buffer of size 4):
65 (then h1 = 6, l1 = 5)
X 23 (then h2 = 2, l2 = 3)
l1 * l2 (15)
+ carry (0)
+ prod[0+0] (0)
carry (1) ß 15 à prod[0+0] (5) (end of l1 * l2)
h1 * l2 (18)
+ carry (1)
+ prod[1+0] (0)
carry (1) ß19 à prod[1+0] (9) (end of h1 * l2, prod[0+2] = carry = 1)
l1 * h2 (10)
+ carry (0)
+ prod[0+1] (9)
carry (1) ß 19 à prod[0+1] (8) (end of l1 * h2)
h1 * h2 (12)
+ carry (1)<