------- Comment #6 from rguenther at suse dot de 2010-01-13 15:08 ------- Subject: Re: possible integer wrong code bug
On Wed, 13 Jan 2010, jakub at gcc dot gnu dot org wrote: > > > ------- 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. No-undefined-overflow branch has { unsigned HOST_WIDE_INT l; HOST_WIDE_INT h; l = l1 + l2; h = (HOST_WIDE_INT)((unsigned HOST_WIDE_INT)h1 + (unsigned HOST_WIDE_INT)h2 + (l < l1)); *lv = l; *hv = h; if (unsigned_p) return ((unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1 || (h == h1 && l < l1)); else return OVERFLOW_SUM_SIGN (h1, h2, h); } but I think that caused fallout somewhere else... (extra TREE_OVERFLOW stuff, etc) Richard. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42721