diff options
author | amker <amker@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-08-02 10:09:33 +0000 |
---|---|---|
committer | amker <amker@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-08-02 10:09:33 +0000 |
commit | 03eed863e98172e590a96b19095c0d44f8d336df (patch) | |
tree | fd8b692140e067fa720442480eb581a6512dc153 | |
parent | 8020abd0dfe3b93bb45207e4ea74a3129ec54a5c (diff) | |
download | gcc-03eed863e98172e590a96b19095c0d44f8d336df.tar.gz |
PR tree-optimization/34114
* fold-const.c (multiple_of_p): Improve MULT_EXPR, PLUS_EXPR,
PLUS_EXPR case. Handle SSA_NAME case.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@238982 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/fold-const.c | 67 |
2 files changed, 66 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f2c81b077fb..5687ad51224 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c5d9a79ed28..c6c2bff5011 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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 PLUS_EXPR: case MINUS_EXPR: - return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom) - && multiple_of_p (type, TREE_OPERAND (top, 1), bottom)); + /* 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: + /* 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; } |