diff options
author | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-01-04 16:34:52 +0000 |
---|---|---|
committer | dberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-01-04 16:34:52 +0000 |
commit | 878c6b557cacf714221f9c550425779e155e2b0d (patch) | |
tree | ebc033b9b67710f150a7a565c73db6c4da44a365 /gcc/lambda-code.c | |
parent | b75b98aa8366f8c69c546a6e0a8f0e7559540363 (diff) | |
download | ppe42-gcc-878c6b557cacf714221f9c550425779e155e2b0d.tar.gz ppe42-gcc-878c6b557cacf714221f9c550425779e155e2b0d.zip |
2006-01-04 Daniel Berlin <dberlin@dberlin.org>
* lambda-code.c (can_put_in_inner_loop): Relax
restrictions.
(can_put_after_inner_loop): New function.
(can_convert_to_perfect_nest): Use can_put_after_inner_loop as well.
(perfect_nestify): Change to make copies and modify uses.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109337 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/lambda-code.c')
-rw-r--r-- | gcc/lambda-code.c | 87 |
1 files changed, 59 insertions, 28 deletions
diff --git a/gcc/lambda-code.c b/gcc/lambda-code.c index 43889f78595..c19ea6cfa54 100644 --- a/gcc/lambda-code.c +++ b/gcc/lambda-code.c @@ -2201,23 +2201,20 @@ exit_phi_for_loop_p (struct loop *loop, tree stmt) return true; } -/* Return true if STMT can be put back into INNER, a loop by moving it to the - beginning of that loop. */ +/* Return true if STMT can be put back into the loop INNER, by + copying it to the beginning of that loop and changing the uses. */ static bool can_put_in_inner_loop (struct loop *inner, tree stmt) { imm_use_iterator imm_iter; use_operand_p use_p; - basic_block use_bb = NULL; gcc_assert (TREE_CODE (stmt) == MODIFY_EXPR); if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS) || !expr_invariant_in_loop_p (inner, TREE_OPERAND (stmt, 1))) return false; - /* We require that the basic block of all uses be the same, or the use be an - exit phi. */ FOR_EACH_IMM_USE_FAST (use_p, imm_iter, TREE_OPERAND (stmt, 0)) { if (!exit_phi_for_loop_p (inner, USE_STMT (use_p))) @@ -2226,17 +2223,39 @@ can_put_in_inner_loop (struct loop *inner, tree stmt) if (!flow_bb_inside_loop_p (inner, immbb)) return false; - if (use_bb == NULL) - use_bb = immbb; - else if (immbb != use_bb) + } + } + return true; +} + +/* Return true if STMT can be put *after* the inner loop of LOOP. */ +static bool +can_put_after_inner_loop (struct loop *loop, tree stmt) +{ + imm_use_iterator imm_iter; + use_operand_p use_p; + + if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)) + return false; + + FOR_EACH_IMM_USE_FAST (use_p, imm_iter, TREE_OPERAND (stmt, 0)) + { + if (!exit_phi_for_loop_p (loop, USE_STMT (use_p))) + { + basic_block immbb = bb_for_stmt (USE_STMT (use_p)); + + if (!dominated_by_p (CDI_DOMINATORS, + immbb, + loop->inner->header) + && !can_put_in_inner_loop (loop->inner, stmt)) return false; } } return true; - } + /* Return TRUE if LOOP is an imperfect nest that we can convert to a perfect one. LOOPIVS is a vector of induction variables, one per loop. ATM, we only handle imperfect nests of depth 2, where all of the statements @@ -2277,18 +2296,20 @@ can_convert_to_perfect_nest (struct loop *loop, if (stmt_uses_op (stmt, iv)) goto fail; - /* If this is a simple operation like a cast that is invariant - in the inner loop, only used there, and we can place it - there, then it's not going to hurt us. - This means that we will propagate casts and other cheap - invariant operations *back* - into the inner loop if we can interchange the loop, on the - theory that we are going to gain a lot more by interchanging - the loop than we are by leaving some invariant code there for - some other pass to clean up. */ + /* If this is a simple operation like a cast that is + invariant in the inner loop, or after the inner loop, + then see if we can place it back where it came from. + This means that we will propagate casts and other + cheap invariant operations *back* into or after + the inner loop if we can interchange the loop, on the + theory that we are going to gain a lot more by + interchanging the loop than we are by leaving some + invariant code there for some other pass to clean + up. */ if (TREE_CODE (stmt) == MODIFY_EXPR && is_gimple_cast (TREE_OPERAND (stmt, 1)) - && can_put_in_inner_loop (loop->inner, stmt)) + && (can_put_in_inner_loop (loop->inner, stmt) + || can_put_after_inner_loop (loop, stmt))) continue; /* Otherwise, if the bb of a statement we care about isn't @@ -2515,23 +2536,33 @@ perfect_nestify (struct loops *loops, bsi_prev (&bsi); continue; } - /* Move this statement back into the inner loop. - This looks a bit confusing, but we are really just - finding the first non-exit phi use and moving the - statement to the beginning of that use's basic - block. */ + + /* Make copies of this statement to put it back next + to its uses. */ FOR_EACH_IMM_USE_SAFE (use_p, imm_iter, TREE_OPERAND (stmt, 0)) { tree imm_stmt = USE_STMT (use_p); if (!exit_phi_for_loop_p (loop->inner, imm_stmt)) { - block_stmt_iterator tobsi = bsi_after_labels (bb_for_stmt (imm_stmt)); - bsi_move_after (&bsi, &tobsi); - update_stmt (stmt); - BREAK_FROM_SAFE_IMM_USE (imm_iter); + block_stmt_iterator tobsi; + tree newname; + tree newstmt; + + newstmt = unshare_expr (stmt); + tobsi = bsi_after_labels (bb_for_stmt (imm_stmt)); + newname = TREE_OPERAND (newstmt, 0); + newname = SSA_NAME_VAR (newname); + newname = make_ssa_name (newname, newstmt); + TREE_OPERAND (newstmt, 0) = newname; + SET_USE (use_p, TREE_OPERAND (newstmt, 0)); + bsi_insert_after (&tobsi, newstmt, BSI_SAME_STMT); + update_stmt (newstmt); + update_stmt (imm_stmt); } } + if (!bsi_end_p (bsi)) + bsi_prev (&bsi); } } else |