re PR rtl-optimization/32283 (Missed induction variable optimization)

PR rtl-optimization/32283
	* tree-ssa-loop-niter.c (scev_probably_wraps_p): Use type of the base
	of the induction variable to decide whether it may wrap.
	* tree-ssa-loop-ivopts.c (rewrite_use_compare): Emit the initialization
	of the bound before the loop.
	* simplify-rtx.c (simplify_binary_operation_1): Add two simplifications
	regarding AND.
	(simplify_plus_minus): Only fail if no simplification is possible.
	* loop-iv.c (simple_rhs_p): Consider reg + reg and reg << cst simple.

From-SVN: r142035
This commit is contained in:
Zdenek Dvorak 2008-11-20 09:05:12 +01:00 committed by Zdenek Dvorak
parent f9487002a4
commit dc5b3407f2
5 changed files with 62 additions and 19 deletions

View File

@ -1,3 +1,15 @@
2008-11-19 Zdenek Dvorak <ook@ucw.cz>
PR rtl-optimization/32283
* tree-ssa-loop-niter.c (scev_probably_wraps_p): Use type of the base
of the induction variable to decide whether it may wrap.
* tree-ssa-loop-ivopts.c (rewrite_use_compare): Emit the initialization
of the bound before the loop.
* simplify-rtx.c (simplify_binary_operation_1): Add two simplifications
regarding AND.
(simplify_plus_minus): Only fail if no simplification is possible.
* loop-iv.c (simple_rhs_p): Consider reg + reg and reg << cst simple.
2008-11-20 Jakub Jelinek <jakub@redhat.com>
PR c++/36631

View File

@ -1337,13 +1337,26 @@ simple_rhs_p (rtx rhs)
case MINUS:
op0 = XEXP (rhs, 0);
op1 = XEXP (rhs, 1);
/* Allow reg + const sets only. */
if (REG_P (op0) && !HARD_REGISTER_P (op0) && CONSTANT_P (op1))
return true;
if (REG_P (op1) && !HARD_REGISTER_P (op1) && CONSTANT_P (op0))
return true;
/* Allow reg + const and reg + reg. */
if (!(REG_P (op0) && !HARD_REGISTER_P (op0))
&& !CONSTANT_P (op0))
return false;
if (!(REG_P (op1) && !HARD_REGISTER_P (op1))
&& !CONSTANT_P (op1))
return false;
return false;
return true;
case ASHIFT:
op0 = XEXP (rhs, 0);
op1 = XEXP (rhs, 1);
/* Allow reg << const. */
if (!(REG_P (op0) && !HARD_REGISTER_P (op0)))
return false;
if (!CONSTANT_P (op1))
return false;
return true;
default:
return false;

View File

@ -2304,12 +2304,19 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
case AND:
if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0))
return trueop1;
/* If we are turning off bits already known off in OP0, we need
not do an AND. */
if (GET_CODE (trueop1) == CONST_INT
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& (nonzero_bits (trueop0, mode) & ~INTVAL (trueop1)) == 0)
return op0;
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
{
HOST_WIDE_INT nzop0 = nonzero_bits (trueop0, mode);
HOST_WIDE_INT val1 = INTVAL (trueop1);
/* If we are turning off bits already known off in OP0, we need
not do an AND. */
if ((nzop0 & ~val1) == 0)
return op0;
/* If we are clearing all the nonzero bits, the result is zero. */
if ((val1 & nzop0) == 0 && !side_effects_p (op0))
return CONST0_RTX (mode);
}
if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)
&& GET_MODE_CLASS (mode) != MODE_CC)
return op0;
@ -2391,7 +2398,9 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
((A & N) + B) & M -> (A + B) & M
Similarly if (N & M) == 0,
((A | N) + B) & M -> (A + B) & M
and for - instead of + and/or ^ instead of |. */
and for - instead of + and/or ^ instead of |.
Also, if (N & M) == 0, then
(A +- N) & M -> A & M. */
if (GET_CODE (trueop1) == CONST_INT
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
&& ~INTVAL (trueop1)
@ -2404,6 +2413,10 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
pmop[0] = XEXP (op0, 0);
pmop[1] = XEXP (op0, 1);
if (GET_CODE (pmop[1]) == CONST_INT
&& (INTVAL (pmop[1]) & INTVAL (trueop1)) == 0)
return simplify_gen_binary (AND, mode, pmop[0], op1);
for (which = 0; which < 2; which++)
{
tem = pmop[which];
@ -3591,10 +3604,6 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
ops[j + 1] = save;
}
/* This is only useful the first time through. */
if (!canonicalized)
return NULL_RTX;
changed = 0;
for (i = n_ops - 1; i > 0; i--)
for (j = i - 1; j >= 0; j--)
@ -3650,10 +3659,15 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
ops[i].neg = lneg;
ops[j].op = NULL_RTX;
changed = 1;
canonicalized = 1;
}
}
}
/* If nothing changed, fail. */
if (!canonicalized)
return NULL_RTX;
/* Pack all the operands to the lower-numbered entries. */
for (i = 0, j = 0; j < n_ops; j++)
if (ops[j].op)

View File

@ -5323,11 +5323,15 @@ rewrite_use_compare (struct ivopts_data *data,
{
tree var = var_at_stmt (data->current_loop, cand, use->stmt);
tree var_type = TREE_TYPE (var);
gimple_seq stmts;
compare = iv_elimination_compare (data, use);
bound = unshare_expr (fold_convert (var_type, bound));
op = force_gimple_operand_gsi (&bsi, bound, true, NULL_TREE,
true, GSI_SAME_STMT);
op = force_gimple_operand (bound, &stmts, true, NULL_TREE);
if (stmts)
gsi_insert_seq_on_edge_immediate (
loop_preheader_edge (data->current_loop),
stmts);
gimple_cond_set_lhs (use->stmt, var);
gimple_cond_set_code (use->stmt, compare);

View File

@ -3053,7 +3053,7 @@ scev_probably_wraps_p (tree base, tree step,
/* If we can use the fact that signed and pointer arithmetics does not
wrap, we are done. */
if (use_overflow_semantics && nowrap_type_p (type))
if (use_overflow_semantics && nowrap_type_p (TREE_TYPE (base)))
return false;
/* To be able to use estimates on number of iterations of the loop,