diff options
-rw-r--r-- | gcc/match.pd | 30 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/fold-negate-1.c | 58 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 35 |
3 files changed, 107 insertions, 16 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index a063a15..a9791ce 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1481,6 +1481,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (if (!FIXED_POINT_TYPE_P (type)) (plus @0 (negate @1)))) +/* Other simplifications of negation (c.f. fold_negate_expr_1). */ +(simplify + (negate (mult:c@0 @1 negate_expr_p@2)) + (if (! TYPE_UNSIGNED (type) + && ! HONOR_SIGN_DEPENDENT_ROUNDING (type) + && single_use (@0)) + (mult @1 (negate @2)))) + +(simplify + (negate (rdiv@0 @1 negate_expr_p@2)) + (if (! HONOR_SIGN_DEPENDENT_ROUNDING (type) + && single_use (@0)) + (rdiv @1 (negate @2)))) + +(simplify + (negate (rdiv@0 negate_expr_p@1 @2)) + (if (! HONOR_SIGN_DEPENDENT_ROUNDING (type) + && single_use (@0)) + (rdiv (negate @1) @2))) + +/* Fold -((int)x >> (prec - 1)) into (unsigned)x >> (prec - 1). */ +(simplify + (negate (convert? (rshift @0 INTEGER_CST@1))) + (if (tree_nop_conversion_p (type, TREE_TYPE (@0)) + && wi::to_wide (@1) == element_precision (type) - 1) + (with { tree stype = TREE_TYPE (@0); + tree ntype = TYPE_UNSIGNED (stype) ? signed_type_for (stype) + : unsigned_type_for (stype); } + (convert (rshift:ntype (convert:ntype @0) @1))))) + /* Try to fold (type) X op CST -> (type) (X op ((type-x) CST)) when profitable. For bitwise binary operations apply operand conversions to the diff --git a/gcc/testsuite/gcc.dg/fold-negate-1.c b/gcc/testsuite/gcc.dg/fold-negate-1.c new file mode 100644 index 0000000..00ec8b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/fold-negate-1.c @@ -0,0 +1,58 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#define SHIFT ((8*__SIZEOF_INT__)-1) + +int test_rshift_1(int x) +{ + int t = x >> SHIFT; + return -t; +} + +int test_rshift_2(int x) +{ + unsigned int t = (unsigned int)x >> SHIFT; + return -t; +} + +int test_rshift_3(int x) +{ + int t = (unsigned int)x >> SHIFT; + return -t; +} + +int test_rshift_4(int x) +{ + unsigned int t = x >> SHIFT; + return -t; +} + +double test_mul_1(double x) +{ + double t = -5.0 * x; + return -t; +} + +double test_mul_2(double x, double y) +{ + double t1 = -x; + double t2 = t1 * y; + return -t2; +} + +double test_rdiv_1(double x, double y) +{ + double t1 = -x; + double t2 = t1 / y; + return -t2; +} + +double test_rdiv_2(double x, double y) +{ + double t1 = -y; + double t2 = x / t1; + return -t2; +} + +/* { dg-final { scan-tree-dump-not " -" "optimized" } } */ + diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index bfa516b..a901f51 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2321,11 +2321,13 @@ vn_reference_lookup_or_insert_for_pieces (tree vuse, } /* Return a value-number for RCODE OPS... either by looking up an existing - value-number for the simplified result or by inserting the operation if - INSERT is true. */ + value-number for the possibly simplified result or by inserting the + operation if INSERT is true. If SIMPLIFY is false, return a value + number for the unsimplified expression. */ static tree -vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert) +vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert, + bool simplify) { tree result = NULL_TREE; /* We will be creating a value number for @@ -2333,15 +2335,16 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert) So first simplify and lookup this expression to see if it is already available. */ /* For simplification valueize. */ - unsigned i; - for (i = 0; i < res_op->num_ops; ++i) - if (TREE_CODE (res_op->ops[i]) == SSA_NAME) - { - tree tem = vn_valueize (res_op->ops[i]); - if (!tem) - break; - res_op->ops[i] = tem; - } + unsigned i = 0; + if (simplify) + for (i = 0; i < res_op->num_ops; ++i) + if (TREE_CODE (res_op->ops[i]) == SSA_NAME) + { + tree tem = vn_valueize (res_op->ops[i]); + if (!tem) + break; + res_op->ops[i] = tem; + } /* If valueization of an operand fails (it is not available), skip simplification. */ bool res = false; @@ -2440,7 +2443,7 @@ vn_nary_build_or_lookup_1 (gimple_match_op *res_op, bool insert) static tree vn_nary_build_or_lookup (gimple_match_op *res_op) { - return vn_nary_build_or_lookup_1 (res_op, true); + return vn_nary_build_or_lookup_1 (res_op, true, true); } /* Try to simplify the expression RCODE OPS... of type TYPE and return @@ -2454,7 +2457,7 @@ vn_nary_simplify (vn_nary_op_t nary) gimple_match_op op (gimple_match_cond::UNCOND, nary->opcode, nary->type, nary->length); memcpy (op.ops, nary->op, sizeof (tree) * nary->length); - return vn_nary_build_or_lookup_1 (&op, false); + return vn_nary_build_or_lookup_1 (&op, false, true); } /* Elimination engine. */ @@ -5006,7 +5009,7 @@ visit_nary_op (tree lhs, gassign *stmt) tree ops[2]; gimple_match_op match_op (gimple_match_cond::UNCOND, NEGATE_EXPR, type, rhs[i]); - ops[i] = vn_nary_build_or_lookup_1 (&match_op, false); + ops[i] = vn_nary_build_or_lookup_1 (&match_op, false, true); ops[j] = rhs[j]; if (ops[i] && (ops[0] = vn_nary_op_lookup_pieces (2, code, @@ -5014,7 +5017,7 @@ visit_nary_op (tree lhs, gassign *stmt) { gimple_match_op match_op (gimple_match_cond::UNCOND, NEGATE_EXPR, type, ops[0]); - result = vn_nary_build_or_lookup (&match_op); + result = vn_nary_build_or_lookup_1 (&match_op, true, false); if (result) { bool changed = set_ssa_val_to (lhs, result); |