In this PR we hit the issue that when CCP faces a conditional which
is (still) undefined it will consider all outgoing edges executable.
Eventually we'll reverse that decision (but without reflecting that
in the lattice), but it's too late then if a PHI node merging
the edges has been evaluated to a copy defined in the not executable
path.

Thus the following patch makes sure we never even start with such
a case (SSA propagator iteration order hopefully makes sure
this doesn't pessimize things in non-loop regions - I have a patch
to fix some iteration order oddities of it).

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2015-07-06  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/66772
        * tree-ssa-ccp.c (ccp_visit_phi_node): Make sure that copy
        values are available in the PHI node BB when there are
        still unexecutable edges.

        * gcc.dg/torture/pr66772-1.c: New testcase.
        * gcc.dg/torture/pr66772-2.c: Likewise.

Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c  (revision 225449)
--- gcc/tree-ssa-ccp.c  (working copy)
*************** ccp_visit_phi_node (gphi *phi)
*** 1081,1086 ****
--- 1094,1100 ----
    new_val.mask = 0;
  
    bool first = true;
+   bool non_exec_edge = false;
    for (i = 0; i < gimple_phi_num_args (phi); i++)
      {
        /* Compute the meet operator over all the PHI arguments flowing
*************** ccp_visit_phi_node (gphi *phi)
*** 1121,1126 ****
--- 1135,1156 ----
          if (new_val.lattice_val == VARYING)
            break;
        }
+       else
+       non_exec_edge = true;
+     }
+ 
+   /* In case there were non-executable edges and the value is a copy
+      make sure its definition dominates the PHI node.  */
+   if (non_exec_edge
+       && new_val.lattice_val == CONSTANT
+       && TREE_CODE (new_val.value) == SSA_NAME
+       && ! SSA_NAME_IS_DEFAULT_DEF (new_val.value)
+       && ! dominated_by_p (CDI_DOMINATORS, gimple_bb (phi),
+                          gimple_bb (SSA_NAME_DEF_STMT (new_val.value))))
+     {
+       new_val.lattice_val = VARYING;
+       new_val.value = NULL_TREE;
+       new_val.mask = -1;
      }
  
    if (dump_file && (dump_flags & TDF_DETAILS))
Index: gcc/testsuite/gcc.dg/torture/pr66733-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr66733-1.c    (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr66733-1.c    (working copy)
***************
*** 0 ****
--- 1,28 ----
+ /* { dg-do compile } */
+ 
+ int a;
+ 
+ int
+ fn1 ()
+ {
+   return 1;
+ }
+ 
+ void
+ fn2 ()
+ {
+   int b, j;
+   for (;;)
+     {
+       int c = 1;
+       if (j)
+       {
+         if (c)
+           break;
+       }
+       else
+       b = a;
+       fn1 () && b;
+       j = fn1 ();
+     }
+ }
Index: gcc/testsuite/gcc.dg/torture/pr66733-2.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr66733-2.c    (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr66733-2.c    (working copy)
***************
*** 0 ****
--- 1,46 ----
+ /* { dg-do compile } */
+ 
+ int a, b, c, e, f;
+ 
+ void fn1 (int p) { }
+ 
+ int
+ fn2 (int p)
+ {
+   return a ? p % a : 0; 
+ }
+ 
+ short
+ fn3 (int p)
+ {
+   return (1 >> p) < 1 ? 1 : p;
+ }
+ 
+ int
+ fn4 ()
+ {
+   int g = 0, h = 1;
+   if (b)
+     goto lbl;
+   fn2 (0);
+   if (fn3 (1))
+     fn1 (e && c);
+   if (h)
+     {
+       int i = 1;
+ lbl:
+       if (i)
+       return 0;
+       for (; g < 1; g++)
+       ;
+     }
+   for (;;)
+     f || g > 0;
+ }
+ 
+ int
+ main ()
+ {
+   fn4 (); 
+   return 0;
+ }

Reply via email to