]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
More NEGATE_EXPR folding in match.pd
authorRoger Sayle <roger@nextmovesoftware.com>
Wed, 22 Sep 2021 18:17:49 +0000 (19:17 +0100)
committerRoger Sayle <roger@nextmovesoftware.com>
Wed, 22 Sep 2021 18:17:49 +0000 (19:17 +0100)
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.

gcc/match.pd
gcc/testsuite/gcc.dg/fold-negate-1.c [new file with mode: 0644]
gcc/tree-ssa-sccvn.c

index a063a1577b5a2b422e660f1f7a2e51f782fdea1b..a9791ceb74ae7cfeae959719e09a8d49cbd4e1b1 100644 (file)
@@ -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 (file)
index 0000000..00ec8b4
--- /dev/null
@@ -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" } } */
+
index bfa516b6cf90343353b298b982744d91707e6c78..a901f51a025f97fed30621ebc07d627a1e7b5cae 100644 (file)
@@ -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);