From: Bin Cheng Date: Tue, 2 Aug 2016 10:09:33 +0000 (+0000) Subject: re PR tree-optimization/34114 (Missed optimization: cannot determine loop termination) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4e2f2da341683a28aa56fae94bc38c2b6341a9ad;p=gcc.git 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 --- 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 + + 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 * 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; }