diff options
author | Bernd Schmidt <bernd.schmidt@analog.com> | 2009-03-31 15:15:04 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2009-03-31 15:15:04 +0000 |
commit | ed853664c52914caf6b9841bf6abfdb168b1b96e (patch) | |
tree | bf6fa20b19a417e860e35f143a681c1cc93575fb /gcc | |
parent | bebc6e07b129cd3e159a6a82fb283e8d13c7a1ff (diff) | |
download | gcc-ed853664c52914caf6b9841bf6abfdb168b1b96e.zip gcc-ed853664c52914caf6b9841bf6abfdb168b1b96e.tar.gz gcc-ed853664c52914caf6b9841bf6abfdb168b1b96e.tar.bz2 |
loop-iv.c (suitable_set_for_replacement): Renamed from simplify_using_assignment...
* loop-iv.c (suitable_set_for_replacement): Renamed from
simplify_using_assignment; changed to return bool and to accept new
args DEST and SRC. Return true iff we find a source/destination pair
that can be used to make a replacement, and fill SRC and DEST if so.
Remove arg ALTERED. Don't deal with altered regs here. All callers
changed.
(simplify_using_initial_values): Deal with altered regs here and track
more precisely the effect they have on the validity of our expression.
From-SVN: r145351
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/loop-iv.c | 106 |
2 files changed, 71 insertions, 46 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3ccdb4c..007b00e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2009-03-31 Bernd Schmidt <bernd.schmidt@analog.com> + + * loop-iv.c (suitable_set_for_replacement): Renamed from + simplify_using_assignment; changed to return bool and to accept new + args DEST and SRC. Return true iff we find a source/destination pair + that can be used to make a replacement, and fill SRC and DEST if so. + Remove arg ALTERED. Don't deal with altered regs here. All callers + changed. + (simplify_using_initial_values): Deal with altered regs here and track + more precisely the effect they have on the validity of our expression. + 2009-03-31 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> PR target/27237 diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c index e02f164..483a868 100644 --- a/gcc/loop-iv.c +++ b/gcc/loop-iv.c @@ -1364,39 +1364,23 @@ simple_rhs_p (rtx rhs) } } -/* Simplifies *EXPR using assignment in INSN. ALTERED is the set of registers - altered so far. */ +/* A subroutine of simplify_using_initial_values, this function examines INSN + to see if it contains a suitable set that we can use to make a replacement. + If it is suitable, return true and set DEST and SRC to the lhs and rhs of + the set; return false otherwise. */ -static void -simplify_using_assignment (rtx insn, rtx *expr, regset altered) +static bool +suitable_set_for_replacement (rtx insn, rtx *dest, rtx *src) { rtx set = single_set (insn); rtx lhs = NULL_RTX, rhs; - bool ret = false; - if (set) - { - lhs = SET_DEST (set); - if (!REG_P (lhs) - || altered_reg_used (&lhs, altered)) - ret = true; - } - else - ret = true; - - note_stores (PATTERN (insn), mark_altered, altered); - if (CALL_P (insn)) - { - int i; - - /* Kill all call clobbered registers. */ - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) - SET_REGNO_REG_SET (altered, i); - } + if (!set) + return false; - if (ret) - return; + lhs = SET_DEST (set); + if (!REG_P (lhs)) + return false; rhs = find_reg_equal_equiv_note (insn); if (rhs) @@ -1405,12 +1389,11 @@ simplify_using_assignment (rtx insn, rtx *expr, regset altered) rhs = SET_SRC (set); if (!simple_rhs_p (rhs)) - return; - - if (for_each_rtx (&rhs, altered_reg_used, altered)) - return; + return false; - *expr = simplify_replace_rtx (*expr, lhs, rhs); + *dest = lhs; + *src = rhs; + return true; } /* Checks whether A implies B. */ @@ -1762,9 +1745,10 @@ eliminate_implied_conditions (enum rtx_code op, rtx *head, rtx tail) static void simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr) { - rtx head, tail, insn; + bool expression_valid; + rtx head, tail, insn, last_valid_expr; rtx neutral, aggr; - regset altered; + regset altered, this_altered; edge e; if (!*expr) @@ -1829,7 +1813,10 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr) return; altered = ALLOC_REG_SET (®_obstack); + this_altered = ALLOC_REG_SET (®_obstack); + expression_valid = true; + last_valid_expr = *expr; while (1) { insn = BB_END (e->src); @@ -1843,29 +1830,52 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr) { simplify_using_condition (cond, expr, altered); if (CONSTANT_P (*expr)) - { - FREE_REG_SET (altered); - return; - } + goto out; } } FOR_BB_INSNS_REVERSE (e->src, insn) { + rtx src, dest; + if (!INSN_P (insn)) continue; - - simplify_using_assignment (insn, expr, altered); - if (CONSTANT_P (*expr)) + + CLEAR_REG_SET (this_altered); + note_stores (PATTERN (insn), mark_altered, this_altered); + if (CALL_P (insn)) { - FREE_REG_SET (altered); - return; + int i; + + /* Kill all call clobbered registers. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)) + SET_REGNO_REG_SET (this_altered, i); } - if (for_each_rtx (expr, altered_reg_used, altered)) + + if (suitable_set_for_replacement (insn, &dest, &src)) { - FREE_REG_SET (altered); - return; + *expr = simplify_replace_rtx (*expr, dest, src); + if (CONSTANT_P (*expr)) + goto out; } + else + /* If we did not use this insn to make a replacement, any overlap + between stores in this insn and our expression will cause the + expression to become invalid. */ + if (for_each_rtx (expr, altered_reg_used, this_altered)) + goto out; + + IOR_REG_SET (altered, this_altered); + + /* If the expression now contains regs that have been altered, we + can't return it to the caller. However, it is still valid for + further simplification, so keep searching to see if we can + eventually turn it into a constant. */ + if (for_each_rtx (expr, altered_reg_used, altered)) + expression_valid = false; + if (expression_valid) + last_valid_expr = *expr; } if (!single_pred_p (e->src) @@ -1874,7 +1884,11 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr) e = single_pred_edge (e->src); } + out: + if (!CONSTANT_P (*expr)) + *expr = last_valid_expr; FREE_REG_SET (altered); + FREE_REG_SET (this_altered); } /* Transforms invariant IV into MODE. Adds assumptions based on the fact |