tree-ssa-threadedge.c (thread_across_edge): After threading through a joiner...
authorJeff Law <law@redhat.com>
Wed, 20 Nov 2013 01:55:17 +0000 (18:55 -0700)
committerJeff Law <law@gcc.gnu.org>
Wed, 20 Nov 2013 01:55:17 +0000 (18:55 -0700)
* tree-ssa-threadedge.c (thread_across_edge): After threading
through a joiner, allow threading a normal block requiring
duplication.

* tree-ssa-threadupdate.c (thread_block_1): Improve code to detect
jump threading requests that would muck up the loop structures.

From-SVN: r205074

gcc/ChangeLog
gcc/tree-ssa-threadedge.c
gcc/tree-ssa-threadupdate.c

index 01bef34..7688983 100644 (file)
@@ -1,5 +1,12 @@
 2013-11-19  Jeff Law  <law@redhat.com>
-       
+
+       * tree-ssa-threadedge.c (thread_across_edge): After threading
+       through a joiner, allow threading a normal block requiring
+       duplication.
+
+       * tree-ssa-threadupdate.c (thread_block_1): Improve code to detect
+       jump threading requests that would muck up the loop structures.
+
        * tree-ssa-threadupdate.c: Fix trailing whitespace.
        * tree-ssa-threadupdate.h: Likewise.
 
index b90ff23..7bb8829 100644 (file)
@@ -1098,6 +1098,14 @@ thread_across_edge (gimple dummy_cond,
                                              path,
                                              &backedge_seen);
 
+       if (!found
+           && (!backedge_seen
+               || ! cond_arg_set_in_bb (path->last ()->e, e->dest)))
+         found = thread_through_normal_block (path->last ()->e, dummy_cond,
+                                              handle_dominating_asserts,
+                                              stack, simplify, path, visited,
+                                              &backedge_seen);
+
        /* If we were able to thread through a successor of E->dest, then
           record the jump threading opportunity.  */
        if (found)
index 1b7c73d..777fe41 100644 (file)
@@ -328,7 +328,7 @@ lookup_redirection_data (edge e, enum insert_option insert)
         to the list of incoming edges associated with E.  */
       if (insert)
        {
-          struct el *el = XNEW (struct el);
+         struct el *el = XNEW (struct el);
          el->next = elt->incoming_edges;
          el->e = e;
          elt->incoming_edges = el;
@@ -496,11 +496,11 @@ ssa_fix_duplicate_block_edges (struct redirection_data *rd,
              e2 = redirect_edge_and_branch (victim, path->last ()->e->dest);
              e2->count = path->last ()->e->count;
              /* If we redirected the edge, then we need to copy PHI arguments
-                at the target.  If the edge already existed (e2 != victim
+                at the target.  If the edge already existed (e2 != victim
                 case), then the PHIs in the target already have the correct
                 arguments.  */
              if (e2 == victim)
-               copy_phi_args (e2->dest, path->last ()->e, e2);
+               copy_phi_args (e2->dest, path->last ()->e, e2);
            }
          else
            {
@@ -550,7 +550,7 @@ ssa_create_duplicates (struct redirection_data **slot,
 
   /* The second duplicated block in a jump threading path is specific
      to the path.  So it gets stored in RD rather than in LOCAL_DATA.
-       
+
      Each time we're called, we have to look through the path and see
      if a second block needs to be duplicated.
 
@@ -672,7 +672,7 @@ ssa_redirect_edges (struct redirection_data **slot,
        }
 
       /* Go ahead and clear E->aux.  It's not needed anymore and failure
-         to clear it will cause all kinds of unpleasant problems later.  */
+        to clear it will cause all kinds of unpleasant problems later.  */
       delete_jump_thread_path (path);
       e->aux = NULL;
 
@@ -697,9 +697,9 @@ redirection_block_p (basic_block bb)
   /* Advance to the first executable statement.  */
   gsi = gsi_start_bb (bb);
   while (!gsi_end_p (gsi)
-         && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
+        && (gimple_code (gsi_stmt (gsi)) == GIMPLE_LABEL
             || is_gimple_debug (gsi_stmt (gsi))
-             || gimple_nop_p (gsi_stmt (gsi))))
+            || gimple_nop_p (gsi_stmt (gsi))))
     gsi_next (&gsi);
 
   /* Check if this is an empty block.  */
@@ -708,9 +708,9 @@ redirection_block_p (basic_block bb)
 
   /* Test that we've reached the terminating control statement.  */
   return gsi_stmt (gsi)
-         && (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND
-             || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
-             || gimple_code (gsi_stmt (gsi)) == GIMPLE_SWITCH);
+        && (gimple_code (gsi_stmt (gsi)) == GIMPLE_COND
+            || gimple_code (gsi_stmt (gsi)) == GIMPLE_GOTO
+            || gimple_code (gsi_stmt (gsi)) == GIMPLE_SWITCH);
 }
 
 /* BB is a block which ends with a COND_EXPR or SWITCH_EXPR and when BB
@@ -795,22 +795,12 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
       if (!e2 || noloop_only)
        {
          /* If NOLOOP_ONLY is true, we only allow threading through the
-            header of a loop to exit edges.
-
-            There are two cases to consider.  The first when BB is the
-            loop header.  We will attempt to thread this elsewhere, so
-            we can just continue here.  */
-
-         if (bb == bb->loop_father->header
-             && (!loop_exit_edge_p (bb->loop_father, e2)
-                 || (*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK))
-           continue;
-
+            header of a loop to exit edges.  */
 
-         /* The second occurs when there was loop header buried in a jump
-            threading path.  We do not try and thread this elsewhere, so
-            just cancel the jump threading request by clearing the AUX
-            field now.  */
+         /* One case occurs when there was loop header buried in a jump
+            threading path that crosses loop boundaries.  We do not try
+            and thread this elsewhere, so just cancel the jump threading
+            request by clearing the AUX field now.  */
          if ((bb->loop_father != e2->src->loop_father
               && !loop_exit_edge_p (e2->src->loop_father, e2))
              || (e2->src->loop_father != e2->dest->loop_father
@@ -823,11 +813,40 @@ thread_block_1 (basic_block bb, bool noloop_only, bool joiners)
              e->aux = NULL;
              continue;
            }
+
+         /* Another case occurs when trying to thread through our
+            own loop header, possibly from inside the loop.
+
+            If our loop header is buried in the path, then go ahead
+            and cancel the jump threading request here.  This likely
+            will need updating for the FSA/FSM coremark case.
+
+            Other cases (BB is the loop header) are handled elsewhere.  */
+         unsigned int i;
+         for (i = 1; i < path->length (); i++)
+           {
+             if ((*path)[i]->e->src == bb->loop_father->header
+                 && (!loop_exit_edge_p (bb->loop_father, e2)
+                     || (*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK))
+               {
+                 /* If i != 1, then it's a buried header that will not
+                    be handled elsehwere.  */
+                 if (i != 1)
+                   {
+                     delete_jump_thread_path (path);
+                     e->aux = NULL;
+                   }
+                 break;
+               }
+           }
+
+         if (i != path->length ())
+           continue;
        }
 
       if (e->dest == e2->src)
        update_bb_profile_for_threading (e->dest, EDGE_FREQUENCY (e),
-                                        e->count, (*THREAD_PATH (e))[1]->e);
+                                        e->count, (*THREAD_PATH (e))[1]->e);
 
       /* Insert the outgoing edge into the hash table if it is not
         already in the hash table.  */
@@ -1242,7 +1261,7 @@ thread_through_loop_header (struct loop *loop, bool may_peel_loop_headers)
       unsigned nblocks, i;
 
       /* First handle the case latch edge is redirected.  We are copying
-         the loop header but not creating a multiple entry loop.  Make the
+        the loop header but not creating a multiple entry loop.  Make the
         cfg manipulation code aware of that fact.  */
       set_loop_copy (loop, loop);
       loop->latch = thread_single_edge (latch);