Commit 4e2f2da3 by Bin Cheng Committed by Bin Cheng

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
parent e877144d
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, ...@@ -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) ...@@ -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 PLUS_EXPR:
case MINUS_EXPR: case MINUS_EXPR:
return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom) /* It is impossible to prove if op0 - op1 is multiple of bottom
&& multiple_of_p (type, TREE_OPERAND (top, 1), 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:
/* 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: 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) ...@@ -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;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment