Hi all, In this PR we end up hitting a signed overflow in noce_get_alt_condition when we try to increment or decrement a HOST_WIDE_INT that might be HOST_WIDE_INT_MAX or HOST_WIDE_INT_MIN.
I've confirmed the overflow by adding an assert before the operation: gcc_assert (desired_val != HOST_WIDE_INT_MAX); This patch fixes those cases by catching the cases when desired_val has the extreme value and avoids the transformation that function is trying to make. Bootstrapped and tested on arm, aarch64, x86_64. I've added the testcase that I used to trigger the assert mentioned above as a compile test, though I'm not sure how much value it has... Ok for trunk? Thanks, Kyrill 2016-05-23 Kyrylo Tkachov <kyrylo.tkac...@arm.com> PR rtl-optimization/66940 * ifcvt.c (noce_get_alt_condition): Check that incrementing or decrementing desired_val will not overflow before performing these operations. 2016-05-23 Kyrylo Tkachov <kyrylo.tkac...@arm.com> PR rtl-optimization/66940 * gcc.c-torture/compile/pr66940.c: New test.
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 80af4a84363192879cc49ea45f777fc987fda555..05fac71409d401a08d01b7dc7cf164613f8477c4 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -2396,28 +2396,32 @@ noce_get_alt_condition (struct noce_if_info *if_info, rtx target, switch (code) { case LT: - if (actual_val == desired_val + 1) + if (desired_val != HOST_WIDE_INT_MAX + && actual_val == desired_val + 1) { code = LE; op_b = GEN_INT (desired_val); } break; case LE: - if (actual_val == desired_val - 1) + if (desired_val != HOST_WIDE_INT_MIN + && actual_val == desired_val - 1) { code = LT; op_b = GEN_INT (desired_val); } break; case GT: - if (actual_val == desired_val - 1) + if (desired_val != HOST_WIDE_INT_MIN + && actual_val == desired_val - 1) { code = GE; op_b = GEN_INT (desired_val); } break; case GE: - if (actual_val == desired_val + 1) + if (desired_val != HOST_WIDE_INT_MAX + && actual_val == desired_val + 1) { code = GT; op_b = GEN_INT (desired_val); diff --git a/gcc/testsuite/gcc.c-torture/compile/pr66940.c b/gcc/testsuite/gcc.c-torture/compile/pr66940.c new file mode 100644 index 0000000000000000000000000000000000000000..1f3586b49f4389b4a506774cf550a984073f03e6 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr66940.c @@ -0,0 +1,8 @@ +long +foo (int cp, long ival) +{ + if (ival <= 0) + return -0x7fffffffffffffffL - 1; + + return 0x7fffffffffffffffL; +}