------- 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

Reply via email to