https://gcc.gnu.org/g:91916b862d82d21d4271bcb191af6cfb710edbc7

commit 91916b862d82d21d4271bcb191af6cfb710edbc7
Author: Alexandre Oliva <ol...@gnu.org>
Date:   Thu Nov 21 22:36:38 2024 -0300

    fold_truth_andor: use pattern matching

Diff:
---
 gcc/gimple-fold.cc | 173 +++++++++--------------------------------------------
 gcc/match.pd       |   7 +++
 2 files changed, 36 insertions(+), 144 deletions(-)

diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index cf711081387d..d55e5941c1ae 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -7387,69 +7387,10 @@ maybe_fold_comparisons_from_match_pd (tree type, enum 
tree_code code,
   return NULL_TREE;
 }
 
-/* Return TRUE if expression STMT is suitable for replacement.  ???
-   Same as ssa_is_replaceable_p, except that we don't insist it has a
-   single use.  */
-
-static bool
-ssa_is_substitutable_p (gimple *stmt)
-{
-#if 0
-  use_operand_p use_p;
-#endif
-  tree def;
-#if 0
-  gimple *use_stmt;
-#endif
-
-  /* Only consider modify stmts.  */
-  if (!is_gimple_assign (stmt))
-    return false;
-
-  /* If the statement may throw an exception, it cannot be replaced.  */
-  if (stmt_could_throw_p (cfun, stmt))
-    return false;
-
-  /* Punt if there is more than 1 def.  */
-  def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
-  if (!def)
-    return false;
-
-#if 0
-  /* Only consider definitions which have a single use.  */
-  if (!single_imm_use (def, &use_p, &use_stmt))
-    return false;
-
-  /* Used in this block, but at the TOP of the block, not the end.  */
-  if (gimple_code (use_stmt) == GIMPLE_PHI)
-    return false;
-#endif
-
-  /* There must be no VDEFs.  */
-  if (gimple_vdef (stmt))
-    return false;
-
-  /* Float expressions must go through memory if float-store is on.  */
-  if (flag_float_store
-      && FLOAT_TYPE_P (TREE_TYPE (def)))
-    return false;
-
-  /* An assignment with a register variable on the RHS is not
-     replaceable.  */
-  if (gimple_assign_rhs_code (stmt) == VAR_DECL
-      && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt)))
-    return false;
-
-  /* No function calls can be replaced.  */
-  if (is_gimple_call (stmt))
-    return false;
-
-  /* Leave any stmt with volatile operands alone as well.  */
-  if (gimple_has_volatile_ops (stmt))
-    return false;
-
-  return true;
-}
+extern bool gimple_nop_convert (tree, tree *, tree (*)(tree));
+extern bool gimple_bit_and_cst (tree, tree *, tree (*)(tree));
+extern bool gimple_bit_xor_cst (tree, tree *, tree (*)(tree));
+extern bool gimple_rshift_cst (tree, tree *, tree (*)(tree));
 
 /* Follow substitutable SSA DEFs for *NAME, including type casts,
    adjusting *NAME to the single rhs or the type cast operand along
@@ -7460,79 +7401,18 @@ static tree
 is_cast_p (tree *name)
 {
   tree type = 0;
+  tree res_ops[1];
 
-  while (TREE_CODE (*name) == SSA_NAME
-        && !SSA_NAME_IS_DEFAULT_DEF (*name))
+  while (gimple_nop_convert (*name, res_ops, follow_all_ssa_edges))
     {
-      gimple *def = SSA_NAME_DEF_STMT (*name);
-
-      if (!ssa_is_substitutable_p (def))
-       break;
-
-      if (gimple_num_ops (def) != 2)
-       break;
-
-      if (gimple_assign_single_p (def))
-       {
-         if (gimple_assign_load_p (def))
-           break;
-         *name = gimple_assign_rhs1 (def);
-         continue;
-       }
-
-      if (!gimple_assign_cast_p (def))
-       break;
-
       if (!type)
        type = TREE_TYPE (*name);
-      *name = gimple_assign_rhs1 (def);
+      *name = res_ops[0];
     }
 
   return type;
 }
 
-/* Follow substitutable SSA DEFs for *NAME.  If we find it is assigned
-   a CODE binary expr, return the second operand, and set *NAME to the
-   first operand.  */
-
-static tree
-is_binop_p (enum tree_code code, tree *name)
-{
-  while (TREE_CODE (*name) == SSA_NAME
-        && !SSA_NAME_IS_DEFAULT_DEF (*name))
-    {
-      gimple *def = SSA_NAME_DEF_STMT (*name);
-
-      if (!ssa_is_substitutable_p (def))
-       return 0;
-
-      switch (gimple_num_ops (def))
-       {
-       default:
-         return 0;
-
-       case 2:
-         if (gimple_assign_single_p (def) && !gimple_assign_load_p (def))
-           {
-             *name = gimple_assign_rhs1 (def);
-             continue;
-           }
-         return 0;
-
-       case 3:
-         break;
-       }
-
-      if (gimple_assign_rhs_code (def) != code)
-       return 0;
-
-      *name = gimple_assign_rhs1 (def);
-      return gimple_assign_rhs2 (def);
-    }
-
-  return 0;
-}
-
 /* If *R_ARG is a constant zero, and L_ARG is a possibly masked
    BIT_XOR_EXPR, return 1 and set *r_arg to l_arg.
    Otherwise, return 0.
@@ -7549,14 +7429,12 @@ prepare_xor (tree l_arg, tree *r_arg)
     return ret;
 
   tree exp = l_arg;
+  tree res_ops[2];
 
-  if (tree and_mask = is_binop_p (BIT_AND_EXPR, &exp))
-    {
-      if (TREE_CODE (and_mask) != INTEGER_CST)
-       return ret;
-    }
+  if (gimple_bit_and_cst (exp, res_ops, follow_all_ssa_edges))
+    exp = res_ops[0];
 
-  if (is_binop_p (BIT_XOR_EXPR, &exp))
+  if (gimple_bit_xor_cst (exp, res_ops, follow_all_ssa_edges))
     {
       *r_arg = l_arg;
       return 1;
@@ -7645,29 +7523,36 @@ decode_field_reference (location_t loc, tree *exp_, 
HOST_WIDE_INT *pbitsize,
      outermost expression if it may matter below.  */
   outer_type = is_cast_p (&exp);
 
-  if ((and_mask = is_binop_p (BIT_AND_EXPR, &exp)))
+  tree res_ops[2];
+  if (gimple_bit_and_cst (exp, res_ops, follow_all_ssa_edges))
     {
-      if (TREE_CODE (and_mask) != INTEGER_CST)
-       return NULL_TREE;
+      exp = res_ops[0];
+      and_mask = res_ops[1];
     }
 
   if (xor_which)
     {
-      tree op2 = is_binop_p (BIT_XOR_EXPR, &exp);
-      gcc_checking_assert (op2);
-      if (xor_which > 1)
-       exp = op2;
+      if (!gimple_bit_xor_cst (exp, res_ops, follow_all_ssa_edges))
+       gcc_unreachable ();
+      switch (xor_which)
+       {
+       case 1:
+       case 2:
+         exp = res_ops[xor_which - 1];
+         break;
+       default:
+         gcc_unreachable ();
+       }
     }
 
   if (tree t = is_cast_p (&exp))
     if (!outer_type)
       outer_type = t;
 
-  if (tree shift = is_binop_p (RSHIFT_EXPR, &exp))
+  if (gimple_rshift_cst (exp, res_ops, follow_all_ssa_edges))
     {
-      if (TREE_CODE (shift) != INTEGER_CST || !tree_fits_shwi_p (shift))
-       return NULL_TREE;
-      shiftrt = tree_to_shwi (shift);
+      exp = res_ops[0];
+      shiftrt = tree_to_shwi (res_ops[1]);
       if (shiftrt <= 0)
        return NULL_TREE;
     }
diff --git a/gcc/match.pd b/gcc/match.pd
index 48317dc80b63..598624086bd5 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -201,6 +201,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
 (match (maybe_bit_not @0)
  (bit_xor_cst@0 @1 @2))
 
+/* These are used by ifcombine fold_truth_andor.  */
+(match (bit_and_cst @0 @1)
+ (bit_and @0 uniform_integer_cst_p@1))
+(match (rshift_cst @0 @1)
+ (rshift @0 uniform_integer_cst_p@1)
+ (if (tree_fits_shwi_p (@1))))
+
 #if GIMPLE
 (match (maybe_truncate @0)
  (convert @0)

Reply via email to