This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][RTL ifcvt] PR rtl-optimization/66940: Avoid signed overflow in noce_get_alt_condition


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.tkachov@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.tkachov@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;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]