public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-2041] Port most of the A CMP 0 ? A : -A to match
@ 2021-07-05 20:42 Andrew Pinski
  0 siblings, 0 replies; only message in thread
From: Andrew Pinski @ 2021-07-05 20:42 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:7d6979197274a662da7bdc564314afe8415865c1

commit r12-2041-g7d6979197274a662da7bdc564314afe8415865c1
Author: Andrew Pinski <apinski@marvell.com>
Date:   Sat Jun 12 19:45:20 2021 -0700

    Port most of the A CMP 0 ? A : -A to match
    
    To improve phiopt and be able to remove abs_replacement, this ports
    most of "A CMP 0 ? A : -A" from fold_cond_expr_with_comparison to
    match.pd.  There is a few extra changes that are needed to remove
    the "A CMP 0 ? A : -A" part from fold_cond_expr_with_comparison:
       * Need to handle (A - B) case
       * Need to handle UN* comparisons.
    
    I will handle those in a different patch.
    
    Note phi-opt-15.c test needed to be updated as we get ABSU now
    instead of not getting ABS.  When ABSU was added phiopt was not
    updated even to use ABSU instead of not creating ABS.
    
    OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.
    
    gcc/ChangeLog:
    
            PR tree-optimization/101039
            * match.pd (A CMP 0 ? A : -A): New patterns.
            * tree-ssa-phiopt.c (abs_replacement): Delete function.
            (tree_ssa_phiopt_worker): Don't call abs_replacement.
            Update comment about abs_replacement.
    
    gcc/testsuite/ChangeLog:
    
            PR tree-optimization/101039
            * gcc.dg/tree-ssa/phi-opt-15.c: Update test to expect
            ABSU and still not expect ABS_EXPR.
            * gcc.dg/tree-ssa/phi-opt-23.c: New test.
            * gcc.dg/tree-ssa/phi-opt-24.c: New test.

Diff:
---
 gcc/match.pd                               |  60 +++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c |   4 +-
 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-23.c |  44 ++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/phi-opt-24.c |  44 ++++++++++
 gcc/tree-ssa-phiopt.c                      | 134 +----------------------------
 5 files changed, 152 insertions(+), 134 deletions(-)

diff --git a/gcc/match.pd b/gcc/match.pd
index 4e10d54383c..72860fbd448 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3976,6 +3976,66 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (cnd (logical_inverted_value truth_valued_p@0) @1 @2)
   (cnd @0 @2 @1)))
 
+/* abs/negative simplifications moved from fold_cond_expr_with_comparison,
+   Need to handle (A - B) case as fold_cond_expr_with_comparison does.
+   Need to handle UN* comparisons.
+
+   None of these transformations work for modes with signed
+   zeros.  If A is +/-0, the first two transformations will
+   change the sign of the result (from +0 to -0, or vice
+   versa).  The last four will fix the sign of the result,
+   even though the original expressions could be positive or
+   negative, depending on the sign of A.
+
+   Note that all these transformations are correct if A is
+   NaN, since the two alternatives (A and -A) are also NaNs.  */
+
+(for cnd (cond vec_cond)
+ /* A == 0 ? A : -A    same as -A */
+ (for cmp (eq uneq)
+  (simplify
+   (cnd (cmp @0 zerop) @0 (negate@1 @0))
+    (if (!HONOR_SIGNED_ZEROS (type))
+     @1))
+  (simplify
+   (cnd (cmp @0 zerop) integer_zerop (negate@1 @0))
+    (if (!HONOR_SIGNED_ZEROS (type))
+     @1))
+ )
+ /* A != 0 ? A : -A    same as A */
+ (for cmp (ne ltgt)
+  (simplify
+   (cnd (cmp @0 zerop) @0 (negate @0))
+    (if (!HONOR_SIGNED_ZEROS (type))
+     @0))
+  (simplify
+   (cnd (cmp @0 zerop) @0 integer_zerop)
+    (if (!HONOR_SIGNED_ZEROS (type))
+     @0))
+ )
+ /* A >=/> 0 ? A : -A    same as abs (A) */
+ (for cmp (ge gt)
+  (simplify
+   (cnd (cmp @0 zerop) @0 (negate @0))
+    (if (!HONOR_SIGNED_ZEROS (type)
+	 && !TYPE_UNSIGNED (type))
+     (abs @0))))
+ /* A <=/< 0 ? A : -A    same as -abs (A) */
+ (for cmp (le lt)
+  (simplify
+   (cnd (cmp @0 zerop) @0 (negate @0))
+    (if (!HONOR_SIGNED_ZEROS (type)
+	 && !TYPE_UNSIGNED (type))
+     (if (ANY_INTEGRAL_TYPE_P (type)
+	  && !TYPE_OVERFLOW_WRAPS (type))
+      (with {
+	tree utype = unsigned_type_for (type);
+       }
+       (convert (negate (absu:utype @0))))
+       (negate (abs @0)))))
+ )
+)
+
 /* -(type)!A -> (type)A - 1.  */
 (simplify
  (negate (convert?:s (logical_inverted_value:s @0)))
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c
index ac3018ef533..6aec68961cf 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c
@@ -9,4 +9,6 @@ foo (int i)
   return i;
 }
 
-/* { dg-final { scan-tree-dump-not "ABS" "optimized" } } */
+/* We should not have ABS_EXPR but ABSU_EXPR instead. */
+/* { dg-final { scan-tree-dump-not "ABS_EXPR" "optimized" } } */
+/* { dg-final { scan-tree-dump "ABSU" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-23.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-23.c
new file mode 100644
index 00000000000..ff658cd16a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-23.c
@@ -0,0 +1,44 @@
+/* { dg-options "-O2 -fdump-tree-phiopt" } */
+
+int f0(int A)
+{
+//     A == 0? A : -A    same as -A
+  if (A == 0)  return A;
+  return -A;
+}
+
+int f1(int A)
+{
+//     A != 0? A : -A    same as A
+  if (A != 0)  return A;
+  return -A;
+}
+int f2(int A)
+{
+//     A >= 0? A : -A    same as abs (A)
+  if (A >= 0)  return A;
+  return -A;
+}
+int f3(int A)
+{
+//     A > 0?  A : -A    same as abs (A)
+  if (A > 0)  return A;
+  return -A;
+}
+int f4(int A)
+{
+//     A <= 0? A : -A    same as -abs (A)
+  if (A <= 0)  return A;
+  return -A;
+}
+int f5(int A)
+{
+//     A < 0?  A : -A    same as -abs (A)
+  if (A < 0)  return A;
+  return -A;
+}
+
+/* These should be optimized in phiopt1 but is confused by predicts. */
+/* { dg-final { scan-tree-dump-not "if" "phiopt1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-not "if" "phiopt2" } } */
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-24.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-24.c
new file mode 100644
index 00000000000..eb89decb4bf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-24.c
@@ -0,0 +1,44 @@
+/* { dg-options "-O2 -fno-signed-zeros -fdump-tree-phiopt" } */
+
+float f0(float A)
+{
+//     A == 0? A : -A    same as -A
+  if (A == 0)  return A;
+  return -A;
+}
+
+float f1(float A)
+{
+//     A != 0? A : -A    same as A
+  if (A != 0)  return A;
+  return -A;
+}
+float f2(float A)
+{
+//     A >= 0? A : -A    same as abs (A)
+  if (A >= 0)  return A;
+  return -A;
+}
+float f3(float A)
+{
+//     A > 0?  A : -A    same as abs (A)
+  if (A > 0)  return A;
+  return -A;
+}
+float f4(float A)
+{
+//     A <= 0? A : -A    same as -abs (A)
+  if (A <= 0)  return A;
+  return -A;
+}
+float f5(float A)
+{
+//     A < 0?  A : -A    same as -abs (A)
+  if (A < 0)  return A;
+  return -A;
+}
+
+/* These should be optimized in phiopt1 but is confused by predicts. */
+/* { dg-final { scan-tree-dump-not "if" "phiopt1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-not "if" "phiopt2" } } */
+
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index f8d7ae1c69d..ab63bf699e3 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -63,8 +63,6 @@ static int value_replacement (basic_block, basic_block,
 			      edge, edge, gphi *, tree, tree);
 static bool minmax_replacement (basic_block, basic_block,
 				edge, edge, gphi *, tree, tree);
-static bool abs_replacement (basic_block, basic_block,
-			     edge, edge, gphi *, tree, tree);
 static bool spaceship_replacement (basic_block, basic_block,
 				   edge, edge, gphi *, tree, tree);
 static bool cond_removal_in_popcount_clz_ctz_pattern (basic_block, basic_block,
@@ -350,8 +348,6 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads, bool early_p)
 					       arg0, arg1,
 					       early_p))
 	    cfgchanged = true;
-	  else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
-	    cfgchanged = true;
 	  else if (!early_p
 		   && cond_removal_in_popcount_clz_ctz_pattern (bb, bb1, e1,
 								e2, phi, arg0,
@@ -2606,134 +2602,6 @@ cond_removal_in_popcount_clz_ctz_pattern (basic_block cond_bb,
   return true;
 }
 
-/*  The function absolute_replacement does the main work of doing the absolute
-    replacement.  Return true if the replacement is done.  Otherwise return
-    false.
-    bb is the basic block where the replacement is going to be done on.  arg0
-    is argument 0 from the phi.  Likewise for arg1.  */
-
-static bool
-abs_replacement (basic_block cond_bb, basic_block middle_bb,
-		 edge e0 ATTRIBUTE_UNUSED, edge e1,
-		 gphi *phi, tree arg0, tree arg1)
-{
-  tree result;
-  gassign *new_stmt;
-  gimple *cond;
-  gimple_stmt_iterator gsi;
-  edge true_edge, false_edge;
-  gimple *assign;
-  edge e;
-  tree rhs, lhs;
-  bool negate;
-  enum tree_code cond_code;
-
-  /* If the type says honor signed zeros we cannot do this
-     optimization.  */
-  if (HONOR_SIGNED_ZEROS (arg1))
-    return false;
-
-  /* OTHER_BLOCK must have only one executable statement which must have the
-     form arg0 = -arg1 or arg1 = -arg0.  */
-
-  assign = last_and_only_stmt (middle_bb);
-  /* If we did not find the proper negation assignment, then we cannot
-     optimize.  */
-  if (assign == NULL)
-    return false;
-
-  /* If we got here, then we have found the only executable statement
-     in OTHER_BLOCK.  If it is anything other than arg = -arg1 or
-     arg1 = -arg0, then we cannot optimize.  */
-  if (gimple_code (assign) != GIMPLE_ASSIGN)
-    return false;
-
-  lhs = gimple_assign_lhs (assign);
-
-  if (gimple_assign_rhs_code (assign) != NEGATE_EXPR)
-    return false;
-
-  rhs = gimple_assign_rhs1 (assign);
-
-  /* The assignment has to be arg0 = -arg1 or arg1 = -arg0.  */
-  if (!(lhs == arg0 && rhs == arg1)
-      && !(lhs == arg1 && rhs == arg0))
-    return false;
-
-  cond = last_stmt (cond_bb);
-  result = PHI_RESULT (phi);
-
-  /* Only relationals comparing arg[01] against zero are interesting.  */
-  cond_code = gimple_cond_code (cond);
-  if (cond_code != GT_EXPR && cond_code != GE_EXPR
-      && cond_code != LT_EXPR && cond_code != LE_EXPR)
-    return false;
-
-  /* Make sure the conditional is arg[01] OP y.  */
-  if (gimple_cond_lhs (cond) != rhs)
-    return false;
-
-  if (FLOAT_TYPE_P (TREE_TYPE (gimple_cond_rhs (cond)))
-	       ? real_zerop (gimple_cond_rhs (cond))
-	       : integer_zerop (gimple_cond_rhs (cond)))
-    ;
-  else
-    return false;
-
-  /* We need to know which is the true edge and which is the false
-     edge so that we know if have abs or negative abs.  */
-  extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
-
-  /* For GT_EXPR/GE_EXPR, if the true edge goes to OTHER_BLOCK, then we
-     will need to negate the result.  Similarly for LT_EXPR/LE_EXPR if
-     the false edge goes to OTHER_BLOCK.  */
-  if (cond_code == GT_EXPR || cond_code == GE_EXPR)
-    e = true_edge;
-  else
-    e = false_edge;
-
-  if (e->dest == middle_bb)
-    negate = true;
-  else
-    negate = false;
-
-  /* If the code negates only iff positive then make sure to not
-     introduce undefined behavior when negating or computing the absolute.
-     ???  We could use range info if present to check for arg1 == INT_MIN.  */
-  if (negate
-      && (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg1))
-	  && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1))))
-    return false;
-
-  result = duplicate_ssa_name (result, NULL);
-
-  if (negate)
-    lhs = make_ssa_name (TREE_TYPE (result));
-  else
-    lhs = result;
-
-  /* Build the modify expression with abs expression.  */
-  new_stmt = gimple_build_assign (lhs, ABS_EXPR, rhs);
-
-  gsi = gsi_last_bb (cond_bb);
-  gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
-
-  if (negate)
-    {
-      /* Get the right GSI.  We want to insert after the recently
-	 added ABS_EXPR statement (which we know is the first statement
-	 in the block.  */
-      new_stmt = gimple_build_assign (result, NEGATE_EXPR, lhs);
-
-      gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
-    }
-
-  replace_phi_edge_with_variable (cond_bb, e1, phi, result);
-
-  /* Note that we optimized this PHI.  */
-  return true;
-}
-
 /* Auxiliary functions to determine the set of memory accesses which
    can't trap because they are preceded by accesses to the same memory
    portion.  We do that for MEM_REFs, so we only need to track
@@ -3670,7 +3538,7 @@ gate_hoist_loads (void)
    ABS Replacement
    ---------------
 
-   This transformation, implemented in abs_replacement, replaces
+   This transformation, implemented in match_simplify_replacement, replaces
 
      bb0:
        if (a >= 0) goto bb2; else goto bb1;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-07-05 20:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-05 20:42 [gcc r12-2041] Port most of the A CMP 0 ? A : -A to match Andrew Pinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).