When we have

x = (T) y;
if (x > CONST)
  true arm
else
  false arm

Assume CONST is larger than what can be represented in T. If we use fold_convert, any bits not not in T will be dropped. So if CONST is say 0x100000000 and T is a 32 bit type, the returned constant will be 0x0. So we change the code to

x = (T) y;
if (y > 0)
  true arm
else
  false arm

If y happens to have a value such as "1" we end up taking the true arm when we should have taken the false arm.

The astute reader will note that VRP should have simply eliminated the condition because it can never be true, at least not in the testcase which is derived from real code in mpfr. Probably we're too conservative when propagating a [0..INF(OV)] through a widening conversion.

Bootstrapped and regression tested on x86_64-unknown-linux-gnu, OK for trunk?

Note this fixes the mpfr-2.x testsuite failures on x86_64. While I believe this fix will address 57144 (ia64), I haven't directly confirmed that's true.





commit baf070f82c7c6f19fd0a9e72514cc0ce03920c29
Author: Jeff Law <l...@redhat.com>
Date:   Thu May 2 22:19:37 2013 -0600

        PR tree-optimization/57411
        * tree-vrp.c (simplify_cond_using_ranges): Verify the constant
        operand of the condition will bit into the new type when eliminating
        a cast feeding a condition.
    
        PR tree-optimization/57411
        * gcc.c-torture/execute/pr57144.c: New test.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9e3d783..f245097 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2013-05-02  Jeff Law  <l...@redhat.com>
+
+       PR tree-optimization/57411
+       * tree-vrp.c (simplify_cond_using_ranges): Verify the constant
+       operand of the condition will bit into the new type when eliminating
+       a cast feeding a condition.
+
 2013-05-02  Richard Biener  <rguent...@suse.de>
 
        * tree-eh.c (cleanup_empty_eh_merge_phis): Remove rename_virts
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c8dc189..be30c51 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2013-05-02  Jeff Law  <l...@redhat.com>
+
+       PR tree-optimization/57411
+       * gcc.c-torture/execute/pr57144.c: New test.
+
 2013-05-02  Tobias Burnus  <bur...@net-b.de>
 
        PR fortran/57142
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57144.c 
b/gcc/testsuite/gcc.c-torture/execute/pr57144.c
new file mode 100644
index 0000000..e96c749
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr57144.c
@@ -0,0 +1,15 @@
+__attribute__ ((noinline))
+foo(int a)
+{
+  int z = a > 0 ? a : -a;
+  long x = z;
+  if (x > 0x100000000)
+    abort ();
+  else
+    exit (0);
+}
+
+main()
+{
+  foo (1);
+}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 6ed353f..b5de683 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -8668,7 +8668,8 @@ simplify_cond_using_ranges (gimple stmt)
          if (range_int_cst_p (vr)
              && range_fits_type_p (vr,
                                    TYPE_PRECISION (TREE_TYPE (op0)),
-                                   TYPE_UNSIGNED (TREE_TYPE (op0))))
+                                   TYPE_UNSIGNED (TREE_TYPE (op0)))
+             && int_fits_type_p (op1, TREE_TYPE (innerop)))
            {
              tree newconst = fold_convert (TREE_TYPE (innerop), op1);
              gimple_cond_set_lhs (stmt, innerop);

Reply via email to