aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/match.pd30
-rw-r--r--gcc/testsuite/gcc.dg/fold-negate-1.c58
-rw-r--r--gcc/tree-ssa-sccvn.c35
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);