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