diff options
Diffstat (limited to 'gcc/tree-ssa-threadupdate.c')
-rw-r--r-- | gcc/tree-ssa-threadupdate.c | 73 |
1 files changed, 46 insertions, 27 deletions
diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index 1b7c73d..777fe41 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -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); |