[Bug rtl-optimization/28651] signed compare incorrectly false for (int)(U+4)<(int)U where U is unsigned INT_MAX (for optimized x86)

rguenth at gcc dot gnu dot org gcc-bugzilla@gcc.gnu.org
Tue Aug 8 17:17:00 GMT 2006

------- Comment #4 from rguenth at gcc dot gnu dot org  2006-08-08 17:17 -------
Breakpoint 4, simplify_const_relational_operation (code=LT, mode=SImode, 
    op0=0xb7cc9f60, op1=0xb7d3ef60)
    at /space/rguenther/src/svn/gcc-4_1-branch/gcc/simplify-rtx.c:3040
3040      gcc_assert (mode != VOIDmode
(gdb) call debug_rtx (op0)
(plus:SI (reg/v:SI 59 [ u ])
    (const_int 4 [0x4]))
(gdb) call debug_rtx (op1)
(reg/v:SI 59 [ u ])


Breakpoint 4, simplify_const_relational_operation (code=LT, mode=SImode, 
    op0=0xb7cc6230, op1=0xb7cc6210)
3040      gcc_assert (mode != VOIDmode
(gdb) call debug_rtx (op0)
(const_int 4 [0x4])
(gdb) call debug_rtx (op1)
(const_int 0 [0x0])

returns 0.  So, here's the bug:

  /* For integer comparisons of A and B maybe we can simplify A - B and can
     then simplify a comparison of that with zero.  If A and B are both either
     a register or a CONST_INT, this can't help; testing for these cases will
     prevent infinite recursion here and speed things up.

     If CODE is an unsigned comparison, then we can never do this optimization,
     because it gives an incorrect result if the subtraction wraps around zero.
     ANSI C defines unsigned operations such that they never overflow, and
     thus such cases can not be ignored; but we cannot do it even for
     signed comparisons for languages such as Java, so test flag_wrapv.  */

  if (!flag_wrapv && INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx
      && ! ((REG_P (op0) || GET_CODE (trueop0) == CONST_INT)
            && (REG_P (op1) || GET_CODE (trueop1) == CONST_INT)) 
      && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1))
      /* We cannot do this for == or != if tem is a nonzero address.  */
      && ((code != EQ && code != NE) || ! nonzero_address_p (tem))
      && code != GTU && code != GEU && code != LTU && code != LEU)
    return simplify_const_relational_operation (signed_condition (code),
                                                mode, tem, const0_rtx);

actually, simplify_binary_operation (MINUS, mode, op0, op1) should not have
returned 4 (it's a signed MINUS which changes overflow because of the
unsigned PLUS, which is not ok as we are relying on undefined overflow).

For mainline, simplify_plus_minus (code=MINUS, mode=SImode, op0=0xb7e0a93c,
op1=0xb7e15f10) returns NULL_RTX while on the branch it simplifies.



More information about the Gcc-bugs mailing list