On Tue, Nov 11, 2014 at 8:48 AM, Richard Biener
<richard.guent...@gmail.com> wrote:
> On Tue, Nov 11, 2014 at 1:10 PM, Patrick Palka <patr...@parcs.ath.cx> wrote:
>> This patch is a replacement for the 2nd VRP refactoring patch.  It
>> simply teaches VRP to look through widening type conversions when
>> finding suitable edge assertions, e.g.
>>
>> bool p = x != y;
>> int q = (int) p;
>> if (q == 0) // new edge assert: p == 0 and therefore x == y
>
> I think the proper fix is to forward x != y to q == 0 instead of this one.
> That said - the tree-ssa-forwprop.c restriction on only forwarding
> single-uses into conditions is clearly bogus here.  I suggest to
> relax it for conversions and compares.  Like with
>
> Index: tree-ssa-forwprop.c
> ===================================================================
> --- tree-ssa-forwprop.c (revision 217349)
> +++ tree-ssa-forwprop.c (working copy)
> @@ -476,7 +476,7 @@ forward_propagate_into_comparison_1 (gim
>         {
>           rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt);
>           tmp = combine_cond_expr_cond (stmt, code, type,
> -                                       rhs0, op1, !single_use0_p);
> +                                       rhs0, op1, false);
>           if (tmp)
>             return tmp;
>         }
>
>
> Thanks,
> Richard.

That makes sense.  Attached is what I have so far.  I relaxed the
forwprop restriction in the case of comparing an integer constant with
a comparison or with a conversion from a boolean value.  (If I allow
all conversions, not just those from a boolean value, then a couple of
-Wstrict-overflow faillures trigger..)  Does the change look sensible?
 Should the logic be duplicated for the case when TREE_CODE (op1) ==
SSA_NAME? Thanks for your help so far!
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-29.c 
b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-29.c
new file mode 100644
index 0000000..df5334e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-29.c
@@ -0,0 +1,31 @@
+/* { dg-options "-O2" } */
+
+void runtime_error (void) __attribute__ ((noreturn));
+void compiletime_error (void) __attribute__ ((noreturn, error ("")));
+
+static void
+compiletime_check_equals_1 (int *x, int y)
+{
+  int __p = *x != y;
+  if (__builtin_constant_p (__p) && __p)
+    compiletime_error ();
+  if (__p)
+    runtime_error ();
+}
+
+static void
+compiletime_check_equals_2 (int *x, int y)
+{
+  int __p = *x != y;
+  if (__builtin_constant_p (__p) && __p)
+    compiletime_error (); /* { dg-error "call to" } */
+  if (__p)
+    runtime_error ();
+}
+
+void
+foo (int *x)
+{
+  compiletime_check_equals_1 (x, 5);
+  compiletime_check_equals_2 (x, 10);
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c 
b/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c
index 251b84e..1ff1820 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c
@@ -16,5 +16,5 @@ foo (int a)
     return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "Replaced" 2 "forwprop1" { xfail *-*-* } 
} } */
+/* { dg-final { scan-tree-dump-times "Replaced" 2 "forwprop1" } } */
 /* { dg-final { cleanup-tree-dump "forwprop1" } } */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index b47f7e2..95f09d1 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -472,11 +472,26 @@ forward_propagate_into_comparison_1 (gimple stmt,
   if (TREE_CODE (op0) == SSA_NAME)
     {
       gimple def_stmt = get_prop_source_stmt (op0, false, &single_use0_p);
+
       if (def_stmt && can_propagate_from (def_stmt))
        {
+         enum tree_code def_code = gimple_assign_rhs_code (def_stmt);
+         bool invariant_only_p = !single_use0_p;
+
          rhs0 = rhs_to_tree (TREE_TYPE (op1), def_stmt);
+
+         /* Always keep the new comparison tree if we are comparing an
+            integer constant with another comparison or with a conversion
+            from a boolean value.  */
+         if (TREE_CODE (op1) == INTEGER_CST
+             && ((CONVERT_EXPR_CODE_P (def_code)
+                  && TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs0, 0)))
+                     == BOOLEAN_TYPE)
+                 || TREE_CODE_CLASS (def_code) == tcc_comparison))
+           invariant_only_p = false;
+
          tmp = combine_cond_expr_cond (stmt, code, type,
-                                       rhs0, op1, !single_use0_p);
+                                       rhs0, op1, invariant_only_p);
          if (tmp)
            return tmp;
        }

Reply via email to