pr58387.c: New test.
authorJeff Law <law@redhat.com>
Tue, 17 Sep 2013 17:27:41 +0000 (11:27 -0600)
committerJeff Law <law@gcc.gnu.org>
Tue, 17 Sep 2013 17:27:41 +0000 (11:27 -0600)
* gcc.c-torture/execute/pr58387.c: New test.

* tree-ssa-dom.c (cprop_into_successor_phis): Also propagate
edge implied equivalences into successor phis.
* tree-ssa-threadupdate.c (phi_args_equal_on_edges): Moved into
here from tree-ssa-threadedge.c.
(mark_threaded_blocks): When threading through a joiner, if both
successors of the joiner's clone reach the same block, verify the
PHI arguments are equal.  If not, cancel the jump threading request.
* tree-ssa-threadedge.c (phi_args_equal_on_edges): Moved into
tree-ssa-threadupdate.c
(thread_across_edge): Don't check PHI argument equality when
threading through joiner block here.

From-SVN: r202660

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr58387.c [new file with mode: 0644]
gcc/tree-ssa-dom.c
gcc/tree-ssa-threadedge.c
gcc/tree-ssa-threadupdate.c

index eb162f4a2b2125e86da17e9c04a232681fea1306..78f4cbc6ce7d05e06fa6c5fc0f61b4ba99e93b3e 100644 (file)
@@ -1,3 +1,17 @@
+2013-09-17  Jeff Law  <law@redhat.com>
+
+       * tree-ssa-dom.c (cprop_into_successor_phis): Also propagate
+       edge implied equivalences into successor phis.
+       * tree-ssa-threadupdate.c (phi_args_equal_on_edges): Moved into
+       here from tree-ssa-threadedge.c.
+       (mark_threaded_blocks): When threading through a joiner, if both
+       successors of the joiner's clone reach the same block, verify the
+       PHI arguments are equal.  If not, cancel the jump threading request.
+       * tree-ssa-threadedge.c (phi_args_equal_on_edges): Moved into
+       tree-ssa-threadupdate.c
+       (thread_across_edge): Don't check PHI argument equality when
+       threading through joiner block here.
+       
 2013-09-17  Andrew MacLeod <amacleod@redhat.com>
 
        * tree-flow.h (ssa_undefined_value_p): Remove prototype.
index a7b90f0a9579dddf8bb33c7c5bf4e161cb61f903..d51c300bd1031a2cc49d820b452246af52ec9c6f 100644 (file)
@@ -1,3 +1,7 @@
+2013-09-17  Jeff Law  <law@redhat.com>
+
+       * gcc.c-torture/execute/pr58387.c: New test.
+
 2013-09-17  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        PR tree-optimization/58088
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58387.c b/gcc/testsuite/gcc.c-torture/execute/pr58387.c
new file mode 100644 (file)
index 0000000..74c32df
--- /dev/null
@@ -0,0 +1,11 @@
+extern void abort(void);
+
+int a = -1; 
+
+int main ()
+{
+  int b = a == 0 ? 0 : -a;
+  if (b < 1)
+    abort ();
+  return 0;
+}
index e02a56662b95713e9b55723110d28eb7265f5d5b..4a2b48bd93d74576e5aab06bdb769412739dfc6e 100644 (file)
@@ -1235,7 +1235,7 @@ record_equivalences_from_incoming_edge (basic_block bb)
 
                  /* If the conversion widens the original value and
                     the constant is in the range of the type of OLD_RHS,
-                    then convert the constant and record the equivalence. 
+                    then convert the constant and record the equivalence.
 
                     Note that int_fits_type_p does not check the precision
                     if the upper and lower bounds are OK.  */
@@ -1642,6 +1642,28 @@ cprop_into_successor_phis (basic_block bb)
       if (gsi_end_p (gsi))
        continue;
 
+      /* We may have an equivalence associated with this edge.  While
+        we can not propagate it into non-dominated blocks, we can
+        propagate them into PHIs in non-dominated blocks.  */
+
+      /* Push the unwind marker so we can reset the const and copies
+        table back to its original state after processing this edge.  */
+      const_and_copies_stack.safe_push (NULL_TREE);
+
+      /* Extract and record any simple NAME = VALUE equivalences.
+
+        Don't bother with [01] = COND equivalences, they're not useful
+        here.  */
+      struct edge_info *edge_info = (struct edge_info *) e->aux;
+      if (edge_info)
+       {
+         tree lhs = edge_info->lhs;
+         tree rhs = edge_info->rhs;
+
+         if (lhs && TREE_CODE (lhs) == SSA_NAME)
+           record_const_or_copy (lhs, rhs);
+       }
+
       indx = e->dest_idx;
       for ( ; !gsi_end_p (gsi); gsi_next (&gsi))
        {
@@ -1667,6 +1689,8 @@ cprop_into_successor_phis (basic_block bb)
              && may_propagate_copy (orig_val, new_val))
            propagate_value (orig_p, new_val);
        }
+
+      restore_vars_to_original_value ();
     }
 }
 
index 42474f16bb82c34511a7d2e716e7e10ac63c1938..47db280411713d5814c670eaad31c4802a3d429d 100644 (file)
@@ -841,28 +841,6 @@ thread_around_empty_blocks (edge taken_edge,
   return false;
 }
       
-/* E1 and E2 are edges into the same basic block.  Return TRUE if the
-   PHI arguments associated with those edges are equal or there are no
-   PHI arguments, otherwise return FALSE.  */
-
-static bool
-phi_args_equal_on_edges (edge e1, edge e2)
-{
-  gimple_stmt_iterator gsi;
-  int indx1 = e1->dest_idx;
-  int indx2 = e2->dest_idx;
-
-  for (gsi = gsi_start_phis (e1->dest); !gsi_end_p (gsi); gsi_next (&gsi))
-    {
-      gimple phi = gsi_stmt (gsi);
-
-      if (!operand_equal_p (gimple_phi_arg_def (phi, indx1),
-                           gimple_phi_arg_def (phi, indx2), 0))
-       return false;
-    }
-  return true;
-}
-
 /* We are exiting E->src, see if E->dest ends with a conditional
    jump which has a known value when reached via E.
 
@@ -1021,18 +999,9 @@ thread_across_edge (gimple dummy_cond,
           record the jump threading opportunity.  */
        if (found)
          {
-           edge tmp;
-           /* If there is already an edge from the block to be duplicated
-              (E2->src) to the final target (E3->dest), then make sure that
-              the PHI args associated with the edges E2 and E3 are the
-              same.  */
-           tmp = find_edge (taken_edge->src, path[path.length () - 1]->dest);
-           if (!tmp || phi_args_equal_on_edges (tmp, path[path.length () - 1]))
-             {
-               propagate_threaded_block_debug_into (path[path.length () - 1]->dest,
-                                                    taken_edge->dest);
-               register_jump_thread (path, true);
-             }
+           propagate_threaded_block_debug_into (path[path.length () - 1]->dest,
+                                                taken_edge->dest);
+           register_jump_thread (path, true);
          }
 
         path.release();
index d75526643b0801915d5322c74eceede303740abc..413112814d6df5ac30abce13934164caa827fc5c 100644 (file)
@@ -1147,6 +1147,28 @@ fail:
   return false;
 }
 
+/* E1 and E2 are edges into the same basic block.  Return TRUE if the
+   PHI arguments associated with those edges are equal or there are no
+   PHI arguments, otherwise return FALSE.  */
+
+static bool
+phi_args_equal_on_edges (edge e1, edge e2)
+{
+  gimple_stmt_iterator gsi;
+  int indx1 = e1->dest_idx;
+  int indx2 = e2->dest_idx;
+
+  for (gsi = gsi_start_phis (e1->dest); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple phi = gsi_stmt (gsi);
+
+      if (!operand_equal_p (gimple_phi_arg_def (phi, indx1),
+                           gimple_phi_arg_def (phi, indx2), 0))
+       return false;
+    }
+  return true;
+}
+
 /* Walk through the registered jump threads and convert them into a
    form convenient for this pass.
 
@@ -1219,6 +1241,46 @@ mark_threaded_blocks (bitmap threaded_blocks)
        }
     }
 
+  /* If we have a joiner block (J) which has two successors S1 and S2 and
+     we are threading though S1 and the final destination of the thread
+     is S2, then we must verify that any PHI nodes in S2 have the same
+     PHI arguments for the edge J->S2 and J->S1->...->S2.
+
+     We used to detect this prior to registering the jump thread, but
+     that prohibits propagation of edge equivalences into non-dominated
+     PHI nodes as the equivalency test might occur before propagation. 
+
+     This works for now, but will need improvement as part of the FSA
+     optimization. 
+
+     Note since we've moved the thread request data to the edges,
+     we have to iterate on those rather than the threaded_edges vector.  */
+  EXECUTE_IF_SET_IN_BITMAP (tmp, 0, i, bi)
+    {
+      bb = BASIC_BLOCK (i);
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       {
+         if (e->aux)
+           {
+             bool have_joiner = THREAD_TARGET2 (e) != NULL;
+
+             if (have_joiner)
+               {
+                 basic_block joiner = e->dest;
+                 edge final_edge = THREAD_TARGET2 (e);
+                 basic_block final_dest = final_edge->dest;
+                 edge e2 = find_edge (joiner, final_dest);
+
+                 if (e2 && !phi_args_equal_on_edges (e2, final_edge))
+                   {
+                     free (e->aux);
+                     e->aux = NULL;
+                   }
+               }
+           }
+       }
+    }
+
 
   /* If optimizing for size, only thread through block if we don't have
      to duplicate it or it's an otherwise empty redirection block.  */