re PR tree-optimization/34114 (Missed optimization: cannot determine loop termination)

PR tree-optimization/34114
	* fold-const.c (multiple_of_p): Improve MULT_EXPR, PLUS_EXPR,
	PLUS_EXPR case.  Handle SSA_NAME case.

From-SVN: r238982
This commit is contained in:
Bin Cheng 2016-08-02 10:09:33 +00:00 committed by Bin Cheng
parent e877144da9
commit 4e2f2da341
2 changed files with 66 additions and 7 deletions

View file

@ -1,3 +1,9 @@
2016-08-02 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/34114
* fold-const.c (multiple_of_p): Improve MULT_EXPR, PLUS_EXPR,
PLUS_EXPR case. Handle SSA_NAME case.
2016-08-02 Tamar Christina <tamar.christina@arm.com>
* config/aarch64/aarch64-simd-builtins.def

View file

@ -12538,6 +12538,9 @@ fold_build_call_array_initializer_loc (location_t loc, tree type, tree fn,
int
multiple_of_p (tree type, const_tree top, const_tree bottom)
{
gimple *stmt;
tree t1, op1, op2;
if (operand_equal_p (top, bottom, 0))
return 1;
@ -12554,19 +12557,31 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
/* FALLTHRU */
case MULT_EXPR:
return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
|| multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
|| multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
case MINUS_EXPR:
/* It is impossible to prove if op0 - op1 is multiple of bottom
precisely, so be conservative here checking if both op0 and op1
are multiple of bottom. Note we check the second operand first
since it's usually simpler. */
return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
&& multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
case PLUS_EXPR:
case MINUS_EXPR:
return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
&& multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
/* The same as MINUS_EXPR, but handle cases like op0 + 0xfffffffd
as op0 - 3 if the expression has unsigned type. For example,
(X / 3) + 0xfffffffd is multiple of 3, but 0xfffffffd is not. */
op1 = TREE_OPERAND (top, 1);
if (TYPE_UNSIGNED (type)
&& TREE_CODE (op1) == INTEGER_CST && tree_int_cst_sign_bit (op1))
op1 = fold_build1 (NEGATE_EXPR, type, op1);
return (multiple_of_p (type, op1, bottom)
&& multiple_of_p (type, TREE_OPERAND (top, 0), bottom));
case LSHIFT_EXPR:
if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
{
tree op1, t1;
op1 = TREE_OPERAND (top, 1);
/* const_binop may not detect overflow correctly,
so check for it explicitly here. */
@ -12606,6 +12621,44 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
SIGNED);
case SSA_NAME:
if (TREE_CODE (bottom) == INTEGER_CST
&& (stmt = SSA_NAME_DEF_STMT (top)) != NULL
&& gimple_code (stmt) == GIMPLE_ASSIGN)
{
enum tree_code code = gimple_assign_rhs_code (stmt);
/* Check for special cases to see if top is defined as multiple
of bottom:
top = (X & ~(bottom - 1) ; bottom is power of 2
or
Y = X % bottom
top = X - Y. */
if (code == BIT_AND_EXPR
&& (op2 = gimple_assign_rhs2 (stmt)) != NULL_TREE
&& TREE_CODE (op2) == INTEGER_CST
&& integer_pow2p (bottom)
&& wi::multiple_of_p (wi::to_widest (op2),
wi::to_widest (bottom), UNSIGNED))
return 1;
op1 = gimple_assign_rhs1 (stmt);
if (code == MINUS_EXPR
&& (op2 = gimple_assign_rhs2 (stmt)) != NULL_TREE
&& TREE_CODE (op2) == SSA_NAME
&& (stmt = SSA_NAME_DEF_STMT (op2)) != NULL
&& gimple_code (stmt) == GIMPLE_ASSIGN
&& (code = gimple_assign_rhs_code (stmt)) == TRUNC_MOD_EXPR
&& operand_equal_p (op1, gimple_assign_rhs1 (stmt), 0)
&& operand_equal_p (bottom, gimple_assign_rhs2 (stmt), 0))
return 1;
}
/* .. fall through ... */
default:
return 0;
}