aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernd Schmidt <bernd.schmidt@analog.com>2009-03-31 15:16:41 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2009-03-31 15:16:41 +0000
commit1569e19062140aa281bc0d08d1be4cf8d4a0e7bf (patch)
treef70a92f822f9ed585d42284f367304878fc9253d
parented853664c52914caf6b9841bf6abfdb168b1b96e (diff)
downloadgcc-1569e19062140aa281bc0d08d1be4cf8d4a0e7bf.zip
gcc-1569e19062140aa281bc0d08d1be4cf8d4a0e7bf.tar.gz
gcc-1569e19062140aa281bc0d08d1be4cf8d4a0e7bf.tar.bz2
loop-iv.c (simplify_using_condition): A condition of the form (EQ REG CONST) can be used to simply make a substitution.
* loop-iv.c (simplify_using_condition): A condition of the form (EQ REG CONST) can be used to simply make a substitution. (simplify_using_initial_values): Keep track of conditions we have seen and keep using them to simplify new expressions, while applying the same substitutions to them as to the expression. From-SVN: r145352
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/loop-iv.c65
2 files changed, 63 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 007b00e..d4686fd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -9,6 +9,12 @@
(simplify_using_initial_values): Deal with altered regs here and track
more precisely the effect they have on the validity of our expression.
+ * loop-iv.c (simplify_using_condition): A condition of the form
+ (EQ REG CONST) can be used to simply make a substitution.
+ (simplify_using_initial_values): Keep track of conditions we have seen
+ and keep using them to simplify new expressions, while applying the
+ same substitutions to them as to the 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 483a868..123e37c 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -1636,15 +1636,22 @@ simplify_using_condition (rtx cond, rtx *expr, regset altered)
{
rtx rev, reve, exp = *expr;
- if (!COMPARISON_P (exp))
- return;
-
/* If some register gets altered later, we do not really speak about its
value at the time of comparison. */
if (altered
&& for_each_rtx (&cond, altered_reg_used, altered))
return;
+ if (GET_CODE (cond) == EQ
+ && REG_P (XEXP (cond, 0)) && CONSTANT_P (XEXP (cond, 1)))
+ {
+ *expr = simplify_replace_rtx (*expr, XEXP (cond, 0), XEXP (cond, 1));
+ return;
+ }
+
+ if (!COMPARISON_P (exp))
+ return;
+
rev = reversed_condition (cond);
reve = reversed_condition (exp);
@@ -1661,7 +1668,6 @@ simplify_using_condition (rtx cond, rtx *expr, regset altered)
return;
}
-
if (rev && rtx_equal_p (exp, rev))
{
*expr = const0_rtx;
@@ -1746,7 +1752,7 @@ static void
simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
{
bool expression_valid;
- rtx head, tail, insn, last_valid_expr;
+ rtx head, tail, insn, cond_list, last_valid_expr;
rtx neutral, aggr;
regset altered, this_altered;
edge e;
@@ -1817,26 +1823,40 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
expression_valid = true;
last_valid_expr = *expr;
+ cond_list = NULL_RTX;
while (1)
{
insn = BB_END (e->src);
if (any_condjump_p (insn))
{
rtx cond = get_condition (BB_END (e->src), NULL, false, true);
-
+
if (cond && (e->flags & EDGE_FALLTHRU))
cond = reversed_condition (cond);
if (cond)
{
+ rtx old = *expr;
simplify_using_condition (cond, expr, altered);
- if (CONSTANT_P (*expr))
- goto out;
+ if (old != *expr)
+ {
+ rtx note;
+ if (CONSTANT_P (*expr))
+ goto out;
+ for (note = cond_list; note; note = XEXP (note, 1))
+ {
+ simplify_using_condition (XEXP (note, 0), expr, altered);
+ if (CONSTANT_P (*expr))
+ goto out;
+ }
+ }
+ cond_list = alloc_EXPR_LIST (0, cond, cond_list);
}
}
FOR_BB_INSNS_REVERSE (e->src, insn)
{
rtx src, dest;
+ rtx old = *expr;
if (!INSN_P (insn))
continue;
@@ -1855,9 +1875,34 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
if (suitable_set_for_replacement (insn, &dest, &src))
{
+ rtx *pnote, *pnote_next;
+
*expr = simplify_replace_rtx (*expr, dest, src);
if (CONSTANT_P (*expr))
goto out;
+
+ for (pnote = &cond_list; *pnote; pnote = pnote_next)
+ {
+ rtx note = *pnote;
+ rtx old_cond = XEXP (note, 0);
+
+ pnote_next = &XEXP (note, 1);
+ XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), dest,
+ src);
+ /* We can no longer use a condition that has been simplified
+ to a constant, and simplify_using_condition will abort if
+ we try. */
+ if (CONSTANT_P (XEXP (note, 0)))
+ {
+ *pnote = *pnote_next;
+ pnote_next = pnote;
+ free_EXPR_LIST_node (note);
+ }
+ /* Retry simplifications with this condition if either the
+ expression or the condition changed. */
+ else if (old_cond != XEXP (note, 0) || old != *expr)
+ simplify_using_condition (XEXP (note, 0), expr, altered);
+ }
}
else
/* If we did not use this insn to make a replacement, any overlap
@@ -1866,6 +1911,9 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
if (for_each_rtx (expr, altered_reg_used, this_altered))
goto out;
+ if (CONSTANT_P (*expr))
+ goto out;
+
IOR_REG_SET (altered, this_altered);
/* If the expression now contains regs that have been altered, we
@@ -1885,6 +1933,7 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr)
}
out:
+ free_EXPR_LIST_list (&cond_list);
if (!CONSTANT_P (*expr))
*expr = last_valid_expr;
FREE_REG_SET (altered);