------- Comment #5 from jakub at gcc dot gnu dot org 2010-01-13 15:05 ------- The bug is in add_double_with_sign it seems. 319int 320add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1, 321 unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2, 322 unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, 323 bool unsigned_p) 324{ 325 unsigned HOST_WIDE_INT l; 326 HOST_WIDE_INT h; 327 328 l = l1 + l2; 329 h = h1 + h2 + (l < l1); 330 331 *lv = l; 332 *hv = h; 333 334 if (unsigned_p) 335 return (unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1; 336 else 337 return OVERFLOW_SUM_SIGN (h1, h2, h); 338} When called with say -1U, -1, -2U, -1, &x, &y, true it pretends no overflow happened. That is because we don't add just 2 numbers together, but 3 (also (l < l1)), and so -1U + -1U + 1 gives -1U, so h == h1. I believe it is wrong not just for unsigned_p, but also for !unsigned_p. The question is how to fix this as efficiently as possible.
-- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42721