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:
parent
e877144da9
commit
4e2f2da341
2 changed files with 66 additions and 7 deletions
|
@ -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>
|
2016-08-02 Tamar Christina <tamar.christina@arm.com>
|
||||||
|
|
||||||
* config/aarch64/aarch64-simd-builtins.def
|
* config/aarch64/aarch64-simd-builtins.def
|
||||||
|
|
|
@ -12538,6 +12538,9 @@ fold_build_call_array_initializer_loc (location_t loc, tree type, tree fn,
|
||||||
int
|
int
|
||||||
multiple_of_p (tree type, const_tree top, const_tree bottom)
|
multiple_of_p (tree type, const_tree top, const_tree bottom)
|
||||||
{
|
{
|
||||||
|
gimple *stmt;
|
||||||
|
tree t1, op1, op2;
|
||||||
|
|
||||||
if (operand_equal_p (top, bottom, 0))
|
if (operand_equal_p (top, bottom, 0))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -12554,19 +12557,31 @@ multiple_of_p (tree type, const_tree top, const_tree bottom)
|
||||||
/* FALLTHRU */
|
/* FALLTHRU */
|
||||||
|
|
||||||
case MULT_EXPR:
|
case MULT_EXPR:
|
||||||
return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
|
return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
|
||||||
|| 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 PLUS_EXPR:
|
||||||
case MINUS_EXPR:
|
/* The same as MINUS_EXPR, but handle cases like op0 + 0xfffffffd
|
||||||
return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
|
as op0 - 3 if the expression has unsigned type. For example,
|
||||||
&& multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
|
(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:
|
case LSHIFT_EXPR:
|
||||||
if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
|
if (TREE_CODE (TREE_OPERAND (top, 1)) == INTEGER_CST)
|
||||||
{
|
{
|
||||||
tree op1, t1;
|
|
||||||
|
|
||||||
op1 = TREE_OPERAND (top, 1);
|
op1 = TREE_OPERAND (top, 1);
|
||||||
/* const_binop may not detect overflow correctly,
|
/* const_binop may not detect overflow correctly,
|
||||||
so check for it explicitly here. */
|
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),
|
return wi::multiple_of_p (wi::to_widest (top), wi::to_widest (bottom),
|
||||||
SIGNED);
|
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:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue