diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2021-09-22 19:17:49 +0100 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2021-09-22 19:17:49 +0100 |
commit | 8f571e64713cc72561f84241863496e473eae4c6 (patch) | |
tree | 4e844b47051f80796967e0a819e774833b79e1b6 | |
parent | 2f2dcbe4717ce7a117671234940f8b74809f3973 (diff) | |
download | gcc-8f571e64713cc72561f84241863496e473eae4c6.zip gcc-8f571e64713cc72561f84241863496e473eae4c6.tar.gz gcc-8f571e64713cc72561f84241863496e473eae4c6.tar.bz2 |
More NEGATE_EXPR folding in match.pd
As observed by Jakub in comment #2 of PR 98865, the expression -(a>>63)
is optimized in GENERIC but not in GIMPLE. Investigating further it
turns out that this is one of a few transformations performed by
fold_negate_expr in fold-const.c that aren't yet performed by match.pd.
This patch moves/duplicates them there, and should be relatively safe
as these transformations are already performed by the compiler, but
just in different passes.
This revised patch adds a Boolean simplify argument to tree-ssa-sccvn.c's
vn_nary_build_or_lookup_1 to control whether simplification should be
performed before value numbering, updating the callers, but then
avoiding simplification when constructing/value-numbering NEGATE_EXPR.
This avoids the regression of gcc.dg/tree-ssa/ssa-free-88.c, and enables
the new test case(s) to pass.
2021-09-22 Roger Sayle <roger@nextmovesoftware.com>
Richard Biener <rguenther@suse.de>
gcc/ChangeLog
* match.pd (negation simplifications): Implement some negation
folding transformations from fold-const.c's fold_negate_expr.
* tree-ssa-sccvn.c (vn_nary_build_or_lookup_1): Add a SIMPLIFY
argument, to control whether the op should be simplified prior
to looking up/assigning a value number.
(vn_nary_build_or_lookup): Update call to vn_nary_build_or_lookup_1.
(vn_nary_simplify): Likewise.
(visit_nary_op): Likewise, but when constructing a NEGATE_EXPR
now call vn_nary_build_or_lookup_1 disabling simplification.
gcc/testsuite/ChangeLog
* gcc.dg/fold-negate-1.c: New test case.
-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); |