From cc7b5acf3761c358bf9705f58b4fcf9625c49b0e Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 11 Nov 2014 13:23:26 +0000 Subject: [PATCH] match.pd: Implement patterns from associate_plusminus and factor in differences from the... 2014-11-11 Richard Biener * match.pd: Implement patterns from associate_plusminus and factor in differences from the fold-const.c implementation. * fold-const.c (fold_binary_loc): Remove patterns here. * tree-ssa-forwprop.c (associate_plusminus): Remove. (pass_forwprop::execute): Don't call it. * tree.c (tree_nop_conversion_p): New function, factored from tree_nop_conversion. * tree.h (tree_nop_conversion_p): Declare. From-SVN: r217349 --- gcc/ChangeLog | 11 ++ gcc/fold-const.c | 56 -------- gcc/match.pd | 119 +++++++++++++++- gcc/tree-ssa-forwprop.c | 361 ------------------------------------------------ gcc/tree.c | 35 +++-- gcc/tree.h | 1 + 6 files changed, 147 insertions(+), 436 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2f6582d..2d57bd3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2014-11-11 Richard Biener + + * match.pd: Implement patterns from associate_plusminus + and factor in differences from the fold-const.c implementation. + * fold-const.c (fold_binary_loc): Remove patterns here. + * tree-ssa-forwprop.c (associate_plusminus): Remove. + (pass_forwprop::execute): Don't call it. + * tree.c (tree_nop_conversion_p): New function, factored + from tree_nop_conversion. + * tree.h (tree_nop_conversion_p): Declare. + 2014-11-11 Uros Bizjak * system.h: Include algorithm and utility. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 13faf0c..f3562ff 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -9939,59 +9939,8 @@ fold_binary_loc (location_t loc, return NULL_TREE; case PLUS_EXPR: - /* A + (-B) -> A - B */ - if (TREE_CODE (arg1) == NEGATE_EXPR - && (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0) - return fold_build2_loc (loc, MINUS_EXPR, type, - fold_convert_loc (loc, type, arg0), - fold_convert_loc (loc, type, - TREE_OPERAND (arg1, 0))); - /* (-A) + B -> B - A */ - if (TREE_CODE (arg0) == NEGATE_EXPR - && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1) - && (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0) - return fold_build2_loc (loc, MINUS_EXPR, type, - fold_convert_loc (loc, type, arg1), - fold_convert_loc (loc, type, - TREE_OPERAND (arg0, 0))); - if (INTEGRAL_TYPE_P (type) || VECTOR_INTEGER_TYPE_P (type)) { - /* Convert ~A + 1 to -A. */ - if (TREE_CODE (arg0) == BIT_NOT_EXPR - && integer_each_onep (arg1)) - return fold_build1_loc (loc, NEGATE_EXPR, type, - fold_convert_loc (loc, type, - TREE_OPERAND (arg0, 0))); - - /* ~X + X is -1. */ - if (TREE_CODE (arg0) == BIT_NOT_EXPR - && !TYPE_OVERFLOW_TRAPS (type)) - { - tree tem = TREE_OPERAND (arg0, 0); - - STRIP_NOPS (tem); - if (operand_equal_p (tem, arg1, 0)) - { - t1 = build_all_ones_cst (type); - return omit_one_operand_loc (loc, type, t1, arg1); - } - } - - /* X + ~X is -1. */ - if (TREE_CODE (arg1) == BIT_NOT_EXPR - && !TYPE_OVERFLOW_TRAPS (type)) - { - tree tem = TREE_OPERAND (arg1, 0); - - STRIP_NOPS (tem); - if (operand_equal_p (arg0, tem, 0)) - { - t1 = build_all_ones_cst (type); - return omit_one_operand_loc (loc, type, t1, arg0); - } - } - /* X + (X / CST) * -CST is X % CST. */ if (TREE_CODE (arg1) == MULT_EXPR && TREE_CODE (TREE_OPERAND (arg1, 0)) == TRUNC_DIV_EXPR @@ -10469,11 +10418,6 @@ fold_binary_loc (location_t loc, return fold_build2_loc (loc, MINUS_EXPR, type, tmp, arg11); } } - /* A - (-B) -> A + B */ - if (TREE_CODE (arg1) == NEGATE_EXPR) - return fold_build2_loc (loc, PLUS_EXPR, type, op0, - fold_convert_loc (loc, type, - TREE_OPERAND (arg1, 0))); /* (-A) - B -> (-B) - A where B is easily negated and we can swap. */ if (TREE_CODE (arg0) == NEGATE_EXPR && negate_expr_p (arg1) diff --git a/gcc/match.pd b/gcc/match.pd index f4f9b8d..29b5ab2 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -25,8 +25,9 @@ along with GCC; see the file COPYING3. If not see /* Generic tree predicates we inherit. */ (define_predicates - integer_onep integer_zerop integer_all_onesp - real_zerop real_onep + integer_onep integer_zerop integer_all_onesp integer_minus_onep + integer_each_onep + real_zerop real_onep real_minus_onep CONSTANT_CLASS_P tree_expr_nonnegative_p) @@ -239,10 +240,6 @@ along with GCC; see the file COPYING3. If not see (bit_not (bit_not @0)) @0) -(simplify - (negate (negate @0)) - @0) - /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */ (simplify @@ -278,6 +275,116 @@ along with GCC; see the file COPYING3. If not see (bit_and @0 { algn; }))) +/* We can't reassociate at all for saturating types. */ +(if (!TYPE_SATURATING (type)) + + /* Contract negates. */ + /* A + (-B) -> A - B */ + (simplify + (plus:c (convert1? @0) (convert2? (negate @1))) + /* Apply STRIP_NOPS on @0 and the negate. */ + (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) + && tree_nop_conversion_p (type, TREE_TYPE (@1)) + && (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0) + (minus (convert @0) (convert @1)))) + /* A - (-B) -> A + B */ + (simplify + (minus (convert1? @0) (convert2? (negate @1))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) + && tree_nop_conversion_p (type, TREE_TYPE (@1))) + (plus (convert @0) (convert @1)))) + /* -(-A) -> A */ + (simplify + (negate (convert? (negate @1))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@1)) + && (TYPE_OVERFLOW_WRAPS (type) + || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)) + @1)) + + /* We can't reassociate floating-point or fixed-point plus or minus + because of saturation to +-Inf. */ + (if (!FLOAT_TYPE_P (type) && !FIXED_POINT_TYPE_P (type)) + + /* Match patterns that allow contracting a plus-minus pair + irrespective of overflow issues. */ + /* (A +- B) - A -> +- B */ + /* (A +- B) -+ B -> A */ + /* A - (A +- B) -> -+ B */ + /* A +- (B -+ A) -> +- B */ + (simplify + (minus (plus:c @0 @1) @0) + @1) + (simplify + (minus (minus @0 @1) @0) + (negate @1)) + (simplify + (plus:c (minus @0 @1) @1) + @0) + (simplify + (minus @0 (plus:c @0 @1)) + (negate @1)) + (simplify + (minus @0 (minus @0 @1)) + @1) + + /* (A +- CST) +- CST -> A + CST */ + (for outer_op (plus minus) + (for inner_op (plus minus) + (simplify + (outer_op (inner_op @0 CONSTANT_CLASS_P@1) CONSTANT_CLASS_P@2) + /* If the constant operation overflows we cannot do the transform + as we would introduce undefined overflow, for example + with (a - 1) + INT_MIN. */ + (with { tree cst = fold_binary (outer_op == inner_op + ? PLUS_EXPR : MINUS_EXPR, type, @1, @2); } + (if (cst && !TREE_OVERFLOW (cst)) + (inner_op @0 { cst; } )))))) + + /* (CST - A) +- CST -> CST - A */ + (for outer_op (plus minus) + (simplify + (outer_op (minus CONSTANT_CLASS_P@1 @0) CONSTANT_CLASS_P@2) + (with { tree cst = fold_binary (outer_op, type, @1, @2); } + (if (cst && !TREE_OVERFLOW (cst)) + (minus { cst; } @0))))) + + /* ~A + A -> -1 */ + (simplify + (plus:c (bit_not @0) @0) + (if (!TYPE_OVERFLOW_TRAPS (type)) + { build_all_ones_cst (type); })) + + /* ~A + 1 -> -A */ + (simplify + (plus (bit_not @0) integer_each_onep) + (negate @0)) + + /* (T)(P + A) - (T)P -> (T) A */ + (for add (plus pointer_plus) + (simplify + (minus (convert (add @0 @1)) + (convert @0)) + (if (TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1)) + /* For integer types, if A has a smaller type + than T the result depends on the possible + overflow in P + A. + E.g. T=size_t, A=(unsigned)429497295, P>0. + However, if an overflow in P + A would cause + undefined behavior, we can assume that there + is no overflow. */ + || (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0))) + /* For pointer types, if the conversion of A to the + final type requires a sign- or zero-extension, + then we have to punt - it is not defined which + one is correct. */ + || (POINTER_TYPE_P (TREE_TYPE (@0)) + && TREE_CODE (@1) == INTEGER_CST + && tree_int_cst_sign_bit (@1) == 0)) + (convert @1)))))) + + + /* Simplifications of conversions. */ /* Basic strip-useless-type-conversions / strip_nops. */ diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 2d6a9fb..b47f7e2 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -1920,359 +1920,6 @@ simplify_rotate (gimple_stmt_iterator *gsi) return true; } -/* Perform re-associations of the plus or minus statement STMT that are - always permitted. Returns true if the CFG was changed. */ - -static bool -associate_plusminus (gimple_stmt_iterator *gsi) -{ - gimple stmt = gsi_stmt (*gsi); - tree rhs1 = gimple_assign_rhs1 (stmt); - tree rhs2 = gimple_assign_rhs2 (stmt); - enum tree_code code = gimple_assign_rhs_code (stmt); - bool changed; - - /* We can't reassociate at all for saturating types. */ - if (TYPE_SATURATING (TREE_TYPE (rhs1))) - return false; - - /* First contract negates. */ - do - { - changed = false; - - /* A +- (-B) -> A -+ B. */ - if (TREE_CODE (rhs2) == SSA_NAME) - { - gimple def_stmt = SSA_NAME_DEF_STMT (rhs2); - if (is_gimple_assign (def_stmt) - && gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR - && can_propagate_from (def_stmt)) - { - code = (code == MINUS_EXPR) ? PLUS_EXPR : MINUS_EXPR; - gimple_assign_set_rhs_code (stmt, code); - rhs2 = gimple_assign_rhs1 (def_stmt); - gimple_assign_set_rhs2 (stmt, rhs2); - gimple_set_modified (stmt, true); - changed = true; - } - } - - /* (-A) + B -> B - A. */ - if (TREE_CODE (rhs1) == SSA_NAME - && code == PLUS_EXPR) - { - gimple def_stmt = SSA_NAME_DEF_STMT (rhs1); - if (is_gimple_assign (def_stmt) - && gimple_assign_rhs_code (def_stmt) == NEGATE_EXPR - && can_propagate_from (def_stmt)) - { - code = MINUS_EXPR; - gimple_assign_set_rhs_code (stmt, code); - rhs1 = rhs2; - gimple_assign_set_rhs1 (stmt, rhs1); - rhs2 = gimple_assign_rhs1 (def_stmt); - gimple_assign_set_rhs2 (stmt, rhs2); - gimple_set_modified (stmt, true); - changed = true; - } - } - } - while (changed); - - /* We can't reassociate floating-point or fixed-point plus or minus - because of saturation to +-Inf. */ - if (FLOAT_TYPE_P (TREE_TYPE (rhs1)) - || FIXED_POINT_TYPE_P (TREE_TYPE (rhs1))) - goto out; - - /* Second match patterns that allow contracting a plus-minus pair - irrespective of overflow issues. - - (A +- B) - A -> +- B - (A +- B) -+ B -> A - (CST +- A) +- CST -> CST +- A - (A +- CST) +- CST -> A +- CST - ~A + A -> -1 - ~A + 1 -> -A - A - (A +- B) -> -+ B - A +- (B +- A) -> +- B - CST +- (CST +- A) -> CST +- A - CST +- (A +- CST) -> CST +- A - A + ~A -> -1 - (T)(P + A) - (T)P -> (T)A - - via commutating the addition and contracting operations to zero - by reassociation. */ - - if (TREE_CODE (rhs1) == SSA_NAME) - { - gimple def_stmt = SSA_NAME_DEF_STMT (rhs1); - if (is_gimple_assign (def_stmt) && can_propagate_from (def_stmt)) - { - enum tree_code def_code = gimple_assign_rhs_code (def_stmt); - if (def_code == PLUS_EXPR - || def_code == MINUS_EXPR) - { - tree def_rhs1 = gimple_assign_rhs1 (def_stmt); - tree def_rhs2 = gimple_assign_rhs2 (def_stmt); - if (operand_equal_p (def_rhs1, rhs2, 0) - && code == MINUS_EXPR) - { - /* (A +- B) - A -> +- B. */ - code = ((def_code == PLUS_EXPR) - ? TREE_CODE (def_rhs2) : NEGATE_EXPR); - rhs1 = def_rhs2; - rhs2 = NULL_TREE; - gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); - gcc_assert (gsi_stmt (*gsi) == stmt); - gimple_set_modified (stmt, true); - } - else if (operand_equal_p (def_rhs2, rhs2, 0) - && code != def_code) - { - /* (A +- B) -+ B -> A. */ - code = TREE_CODE (def_rhs1); - rhs1 = def_rhs1; - rhs2 = NULL_TREE; - gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); - gcc_assert (gsi_stmt (*gsi) == stmt); - gimple_set_modified (stmt, true); - } - else if (CONSTANT_CLASS_P (rhs2) - && CONSTANT_CLASS_P (def_rhs1)) - { - /* (CST +- A) +- CST -> CST +- A. */ - tree cst = fold_binary (code, TREE_TYPE (rhs1), - def_rhs1, rhs2); - if (cst && !TREE_OVERFLOW (cst)) - { - code = def_code; - gimple_assign_set_rhs_code (stmt, code); - rhs1 = cst; - gimple_assign_set_rhs1 (stmt, rhs1); - rhs2 = def_rhs2; - gimple_assign_set_rhs2 (stmt, rhs2); - gimple_set_modified (stmt, true); - } - } - else if (CONSTANT_CLASS_P (rhs2) - && CONSTANT_CLASS_P (def_rhs2)) - { - /* (A +- CST) +- CST -> A +- CST. */ - enum tree_code mix = (code == def_code) - ? PLUS_EXPR : MINUS_EXPR; - tree cst = fold_binary (mix, TREE_TYPE (rhs1), - def_rhs2, rhs2); - if (cst && !TREE_OVERFLOW (cst)) - { - code = def_code; - gimple_assign_set_rhs_code (stmt, code); - rhs1 = def_rhs1; - gimple_assign_set_rhs1 (stmt, rhs1); - rhs2 = cst; - gimple_assign_set_rhs2 (stmt, rhs2); - gimple_set_modified (stmt, true); - } - } - } - else if (def_code == BIT_NOT_EXPR && code == PLUS_EXPR) - { - tree def_rhs1 = gimple_assign_rhs1 (def_stmt); - if (operand_equal_p (def_rhs1, rhs2, 0)) - { - /* ~A + A -> -1. */ - rhs1 = build_all_ones_cst (TREE_TYPE (rhs2)); - rhs2 = NULL_TREE; - code = TREE_CODE (rhs1); - gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); - gcc_assert (gsi_stmt (*gsi) == stmt); - gimple_set_modified (stmt, true); - } - else if ((TREE_CODE (TREE_TYPE (rhs2)) != COMPLEX_TYPE - && integer_onep (rhs2)) - || (TREE_CODE (rhs2) == COMPLEX_CST - && integer_onep (TREE_REALPART (rhs2)) - && integer_onep (TREE_IMAGPART (rhs2)))) - { - /* ~A + 1 -> -A. */ - code = NEGATE_EXPR; - rhs1 = def_rhs1; - rhs2 = NULL_TREE; - gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); - gcc_assert (gsi_stmt (*gsi) == stmt); - gimple_set_modified (stmt, true); - } - } - else if (code == MINUS_EXPR - && CONVERT_EXPR_CODE_P (def_code) - && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME - && TREE_CODE (rhs2) == SSA_NAME) - { - /* (T)(P + A) - (T)P -> (T)A. */ - gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs2); - if (is_gimple_assign (def_stmt2) - && can_propagate_from (def_stmt2) - && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2)) - && TREE_CODE (gimple_assign_rhs1 (def_stmt2)) == SSA_NAME) - { - /* Now we have (T)X - (T)P. */ - tree p = gimple_assign_rhs1 (def_stmt2); - def_stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt)); - if (is_gimple_assign (def_stmt2) - && can_propagate_from (def_stmt2) - && (gimple_assign_rhs_code (def_stmt2) == POINTER_PLUS_EXPR - || gimple_assign_rhs_code (def_stmt2) == PLUS_EXPR) - && gimple_assign_rhs1 (def_stmt2) == p) - { - /* And finally (T)(P + A) - (T)P. */ - tree a = gimple_assign_rhs2 (def_stmt2); - if (TYPE_PRECISION (TREE_TYPE (rhs1)) - <= TYPE_PRECISION (TREE_TYPE (a)) - /* For integer types, if A has a smaller type - than T the result depends on the possible - overflow in P + A. - E.g. T=size_t, A=(unsigned)429497295, P>0. - However, if an overflow in P + A would cause - undefined behavior, we can assume that there - is no overflow. */ - || (INTEGRAL_TYPE_P (TREE_TYPE (p)) - && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (p))) - /* For pointer types, if the conversion of A to the - final type requires a sign- or zero-extension, - then we have to punt - it is not defined which - one is correct. */ - || (POINTER_TYPE_P (TREE_TYPE (p)) - && TREE_CODE (a) == INTEGER_CST - && tree_int_cst_sign_bit (a) == 0)) - { - if (issue_strict_overflow_warning - (WARN_STRICT_OVERFLOW_MISC) - && TYPE_PRECISION (TREE_TYPE (rhs1)) - > TYPE_PRECISION (TREE_TYPE (a)) - && INTEGRAL_TYPE_P (TREE_TYPE (p))) - warning_at (gimple_location (stmt), - OPT_Wstrict_overflow, - "assuming signed overflow does not " - "occur when assuming that " - "(T)(P + A) - (T)P is always (T)A"); - if (useless_type_conversion_p (TREE_TYPE (rhs1), - TREE_TYPE (a))) - code = TREE_CODE (a); - else - code = NOP_EXPR; - rhs1 = a; - rhs2 = NULL_TREE; - gimple_assign_set_rhs_with_ops (gsi, code, rhs1, - rhs2); - gcc_assert (gsi_stmt (*gsi) == stmt); - gimple_set_modified (stmt, true); - } - } - } - } - } - } - - if (rhs2 && TREE_CODE (rhs2) == SSA_NAME) - { - gimple def_stmt = SSA_NAME_DEF_STMT (rhs2); - if (is_gimple_assign (def_stmt) && can_propagate_from (def_stmt)) - { - enum tree_code def_code = gimple_assign_rhs_code (def_stmt); - if (def_code == PLUS_EXPR - || def_code == MINUS_EXPR) - { - tree def_rhs1 = gimple_assign_rhs1 (def_stmt); - tree def_rhs2 = gimple_assign_rhs2 (def_stmt); - if (operand_equal_p (def_rhs1, rhs1, 0) - && code == MINUS_EXPR) - { - /* A - (A +- B) -> -+ B. */ - code = ((def_code == PLUS_EXPR) - ? NEGATE_EXPR : TREE_CODE (def_rhs2)); - rhs1 = def_rhs2; - rhs2 = NULL_TREE; - gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); - gcc_assert (gsi_stmt (*gsi) == stmt); - gimple_set_modified (stmt, true); - } - else if (operand_equal_p (def_rhs2, rhs1, 0) - && code != def_code) - { - /* A +- (B +- A) -> +- B. */ - code = ((code == PLUS_EXPR) - ? TREE_CODE (def_rhs1) : NEGATE_EXPR); - rhs1 = def_rhs1; - rhs2 = NULL_TREE; - gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); - gcc_assert (gsi_stmt (*gsi) == stmt); - gimple_set_modified (stmt, true); - } - else if (CONSTANT_CLASS_P (rhs1) - && CONSTANT_CLASS_P (def_rhs1)) - { - /* CST +- (CST +- A) -> CST +- A. */ - tree cst = fold_binary (code, TREE_TYPE (rhs2), - rhs1, def_rhs1); - if (cst && !TREE_OVERFLOW (cst)) - { - code = (code == def_code ? PLUS_EXPR : MINUS_EXPR); - gimple_assign_set_rhs_code (stmt, code); - rhs1 = cst; - gimple_assign_set_rhs1 (stmt, rhs1); - rhs2 = def_rhs2; - gimple_assign_set_rhs2 (stmt, rhs2); - gimple_set_modified (stmt, true); - } - } - else if (CONSTANT_CLASS_P (rhs1) - && CONSTANT_CLASS_P (def_rhs2)) - { - /* CST +- (A +- CST) -> CST +- A. */ - tree cst = fold_binary (def_code == code - ? PLUS_EXPR : MINUS_EXPR, - TREE_TYPE (rhs2), - rhs1, def_rhs2); - if (cst && !TREE_OVERFLOW (cst)) - { - rhs1 = cst; - gimple_assign_set_rhs1 (stmt, rhs1); - rhs2 = def_rhs1; - gimple_assign_set_rhs2 (stmt, rhs2); - gimple_set_modified (stmt, true); - } - } - } - else if (def_code == BIT_NOT_EXPR) - { - tree def_rhs1 = gimple_assign_rhs1 (def_stmt); - if (code == PLUS_EXPR - && operand_equal_p (def_rhs1, rhs1, 0)) - { - /* A + ~A -> -1. */ - rhs1 = build_all_ones_cst (TREE_TYPE (rhs1)); - rhs2 = NULL_TREE; - code = TREE_CODE (rhs1); - gimple_assign_set_rhs_with_ops (gsi, code, rhs1, NULL_TREE); - gcc_assert (gsi_stmt (*gsi) == stmt); - gimple_set_modified (stmt, true); - } - } - } - } - -out: - if (gimple_modified_p (stmt)) - { - fold_stmt_inplace (gsi); - update_stmt (stmt); - return true; - } - - return false; -} - /* Combine an element access with a shuffle. Returns true if there were any changes made, else it returns false. */ @@ -2805,14 +2452,6 @@ pass_forwprop::execute (function *fun) || code == BIT_XOR_EXPR) && simplify_rotate (&gsi)) changed = true; - else if (code == PLUS_EXPR - || code == MINUS_EXPR) - { - changed = associate_plusminus (&gsi); - if (changed - && maybe_clean_or_replace_eh_stmt (stmt, stmt)) - bitmap_set_bit (to_purge, bb->index); - } else if (code == VEC_PERM_EXPR) { int did_something = simplify_permutation (&gsi); diff --git a/gcc/tree.c b/gcc/tree.c index c7c4c41..221f0dd 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -11659,6 +11659,27 @@ block_ultimate_origin (const_tree block) } } +/* Return true iff conversion from INNER_TYPE to OUTER_TYPE generates + no instruction. */ + +bool +tree_nop_conversion_p (const_tree outer_type, const_tree inner_type) +{ + /* Use precision rather then machine mode when we can, which gives + the correct answer even for submode (bit-field) types. */ + if ((INTEGRAL_TYPE_P (outer_type) + || POINTER_TYPE_P (outer_type) + || TREE_CODE (outer_type) == OFFSET_TYPE) + && (INTEGRAL_TYPE_P (inner_type) + || POINTER_TYPE_P (inner_type) + || TREE_CODE (inner_type) == OFFSET_TYPE)) + return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type); + + /* Otherwise fall back on comparing machine modes (e.g. for + aggregate types, floats). */ + return TYPE_MODE (outer_type) == TYPE_MODE (inner_type); +} + /* Return true iff conversion in EXP generates no instruction. Mark it inline so that we fully inline into the stripping functions even though we have two uses of this function. */ @@ -11680,19 +11701,7 @@ tree_nop_conversion (const_tree exp) if (!inner_type) return false; - /* Use precision rather then machine mode when we can, which gives - the correct answer even for submode (bit-field) types. */ - if ((INTEGRAL_TYPE_P (outer_type) - || POINTER_TYPE_P (outer_type) - || TREE_CODE (outer_type) == OFFSET_TYPE) - && (INTEGRAL_TYPE_P (inner_type) - || POINTER_TYPE_P (inner_type) - || TREE_CODE (inner_type) == OFFSET_TYPE)) - return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type); - - /* Otherwise fall back on comparing machine modes (e.g. for - aggregate types, floats). */ - return TYPE_MODE (outer_type) == TYPE_MODE (inner_type); + return tree_nop_conversion_p (outer_type, inner_type); } /* Return true iff conversion in EXP generates no instruction. Don't diff --git a/gcc/tree.h b/gcc/tree.h index d9fe0c2..0577d51 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4226,6 +4226,7 @@ extern bool is_typedef_decl (tree x); extern bool typedef_variant_p (tree); extern bool auto_var_in_fn_p (const_tree, const_tree); extern tree build_low_bits_mask (tree, unsigned); +extern bool tree_nop_conversion_p (const_tree, const_tree); extern tree tree_strip_nop_conversions (tree); extern tree tree_strip_sign_nop_conversions (tree); extern const_tree strip_invariant_refs (const_tree); -- 2.7.4