This adds support to match_simplify_replacement to allowing of the middle-bbs 
to have more
than 1 statement in a few cases. If we are replacing the both middle bbs with a
fully independent sequence we can handle that. If we are replacing with a 
sequence
that depends on the first statement of either (or both) blocks, this allows 
that.
If the result is defined by part or fully of one of the middle bbs. Then make
the whole bb unconditional.

Note the middle bbs still need to have statements that can't trap nor have
side effects. And each of the statements need to feed into the next instruction
and including into the phi.

This allows removal of the manual matching done in 
cond_removal_in_builtin_zero_pattern
as those have been moved to match patterns back in r14-362-gc53237cefbad0c and 
r14-414-g078339fc04f5de.
So let's remove it too.

Bootstrapped and tested on x86_64-linux-gnu.

gcc/ChangeLog:

        * tree-ssa-phiopt.cc (gsi_next_nondebug_nonnop_non_predict): New 
function.
        (enum bbfeeding_info): New enum.
        (empty_bb_or_one_feeding_into_p): Rename to ...
        (feeding_bb_info): This and support few different other cases.
        (auto_flow_sensitive): Increase the vect base size to 4.
        (auto_flow_sensitive::auto_flow_sensitive(gimple*)): Split out into ...
        (auto_flow_sensitive::save_stmt): This.
        (auto_flow_sensitive::auto_flow_sensitive(basic_block)): New 
constructor.
        (match_simplify_replacement): Support More than one statement in the 
middle BB.
        (cond_removal_in_builtin_zero_pattern): Remove.
        (pass_phiopt::execute): Don't call cond_removal_in_builtin_zero_pattern.

Signed-off-by: Andrew Pinski <[email protected]>
---
 gcc/tree-ssa-phiopt.cc | 602 ++++++++++++++++-------------------------
 1 file changed, 239 insertions(+), 363 deletions(-)

diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index fd173ec01f4..efc818332b3 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -861,110 +861,132 @@ gimple_simplify_phiopt (bool early_p, tree type, gimple 
*comp_stmt,
   return NULL;
 }
 
-/* empty_bb_or_one_feeding_into_p returns true if bb was empty basic block
-   or it has one cheap preparation statement that feeds into the PHI
-   statement and it sets STMT to that statement. */
-static bool
-empty_bb_or_one_feeding_into_p (basic_block bb,
-                               gimple *phi,
-                               gimple *&stmt)
+/* Like gsi_next_nondebug but also skips over NOPs and predicats.  */
+static void
+gsi_next_nondebug_nonnop_nonpredict (gimple_stmt_iterator *i)
+{
+  do
+    {
+      gsi_next_nondebug (i);
+    }
+  while (!gsi_end_p (*i)
+        && (gimple_code (**i) == GIMPLE_PREDICT
+            || gimple_code (**i) == GIMPLE_NOP));
+}
+
+enum bbfeeding_info
+{
+  invalid_bb,
+  empty_bb,
+  one_stmt_bb,
+  feeding_bb
+};
+
+/* This returns empty_bb if bb was empty basic block.
+   or returns one_stmt_bb if it has one cheap preparation statement that feeds 
into the PHI
+   statement and it sets STMT to that statement.
+   Returns feeding_bb if the basic block is not empty but has a sequence of 
statements
+   feeding into the phi that has no side effects.   */
+static bbfeeding_info
+feeding_bb_info (basic_block bb,
+                gimple *phi,
+                gimple *&stmt)
 {
   stmt = nullptr;
   gimple *stmt_to_move = nullptr;
   tree lhs;
 
   if (empty_block_p (bb))
-    return true;
+    return empty_bb;
 
   if (!single_pred_p (bb))
-    return false;
+    return invalid_bb;
 
   /* The middle bb cannot have phi nodes as we don't
      move those assignments yet. */
   if (!gimple_seq_empty_p (phi_nodes (bb)))
-    return false;
+    return invalid_bb;
 
   gimple_stmt_iterator gsi;
 
   gsi = gsi_start_nondebug_after_labels_bb (bb);
+  bool more_than_one = false;
   while (!gsi_end_p (gsi))
     {
-      gimple *s = gsi_stmt (gsi);
-      gsi_next_nondebug (&gsi);
+      gimple *s = *gsi;
+      gsi_next_nondebug_nonnop_nonpredict (&gsi);
       /* Skip over Predict and nop statements. */
       if (gimple_code (s) == GIMPLE_PREDICT
          || gimple_code (s) == GIMPLE_NOP)
        continue;
       /* If there is more one statement return false. */
       if (stmt_to_move)
-       return false;
-      stmt_to_move = s;
-    }
-
-  /* The only statement here was a Predict or a nop statement
-     so return true. */
-  if (!stmt_to_move)
-    return true;
-
-  if (gimple_vuse (stmt_to_move))
-    return false;
-
-  if (gimple_could_trap_p (stmt_to_move)
-      || gimple_has_side_effects (stmt_to_move))
-    return false;
-
-  ssa_op_iter it;
-  tree use;
-  FOR_EACH_SSA_TREE_OPERAND (use, stmt_to_move, it, SSA_OP_USE)
-    if (ssa_name_maybe_undef_p (use))
-      return false;
-
-  /* Allow assignments but allow some builtin/internal calls.
-     As const calls don't match any of the above, yet they could
-     still have some side-effects - they could contain
-     gimple_could_trap_p statements, like floating point
-     exceptions or integer division by zero.  See PR70586.
-     FIXME: perhaps gimple_has_side_effects or gimple_could_trap_p
-     should handle this.
-     Allow some known builtin/internal calls that are known not to
-     trap: logical functions (e.g. bswap and bit counting). */
-  if (!is_gimple_assign (stmt_to_move))
-    {
-      if (!is_gimple_call (stmt_to_move))
-       return false;
-      combined_fn cfn = gimple_call_combined_fn (stmt_to_move);
-      switch (cfn)
+       more_than_one = true;
+      if (gimple_vuse (s))
+       return invalid_bb;
+      if (gimple_could_trap_p (s)
+         || gimple_has_side_effects (s))
+       return invalid_bb;
+      ssa_op_iter it;
+      tree use;
+      FOR_EACH_SSA_TREE_OPERAND (use, s, it, SSA_OP_USE)
+       if (ssa_name_maybe_undef_p (use))
+         return invalid_bb;
+
+      /* Allow assignments but allow some builtin/internal calls.
+        As const calls don't match any of the above, yet they could
+        still have some side-effects - they could contain
+        gimple_could_trap_p statements, like floating point
+        exceptions or integer division by zero.  See PR70586.
+        FIXME: perhaps gimple_has_side_effects or gimple_could_trap_p
+        should handle this.
+        Allow some known builtin/internal calls that are known not to
+        trap: logical functions (e.g. bswap and bit counting). */
+      if (!is_gimple_assign (s))
        {
-       default:
-         return false;
-       CASE_CFN_BSWAP:
-       CASE_CFN_BITREVERSE:
-       CASE_CFN_FFS:
-       CASE_CFN_PARITY:
-       CASE_CFN_POPCOUNT:
-       CASE_CFN_CLZ:
-       CASE_CFN_CTZ:
-       case CFN_BUILT_IN_CLRSB:
-       case CFN_BUILT_IN_CLRSBL:
-       case CFN_BUILT_IN_CLRSBLL:
-         lhs = gimple_call_lhs (stmt_to_move);
-         break;
+         if (!is_gimple_call (s))
+           return invalid_bb;
+         combined_fn cfn = gimple_call_combined_fn (s);
+         switch (cfn)
+           {
+           default:
+             return invalid_bb;
+           CASE_CFN_BSWAP:
+           CASE_CFN_BITREVERSE:
+           CASE_CFN_FFS:
+           CASE_CFN_PARITY:
+           CASE_CFN_POPCOUNT:
+           CASE_CFN_CLZ:
+           CASE_CFN_CTZ:
+           case CFN_BUILT_IN_CLRSB:
+           case CFN_BUILT_IN_CLRSBL:
+           case CFN_BUILT_IN_CLRSBLL:
+             lhs = gimple_call_lhs (s);
+             break;
+           }
        }
-    }
-  else
-    lhs = gimple_assign_lhs (stmt_to_move);
+      else
+       lhs = gimple_assign_lhs (s);
 
-  gimple *use_stmt;
-  use_operand_p use_p;
+      gimple *use_stmt;
+      use_operand_p use_p;
 
-  /* Allow only a statement which feeds into the other stmt.  */
-  if (!lhs || TREE_CODE (lhs) != SSA_NAME
-      || !single_imm_use (lhs, &use_p, &use_stmt)
-      || use_stmt != phi)
-    return false;
+      /* Allow only a statement which feeds into the next stmt
+        or the phi (when last statement).  */
+      if (!lhs || TREE_CODE (lhs) != SSA_NAME
+         || !single_imm_use (lhs, &use_p, &use_stmt)
+         || use_stmt != (gsi_end_p (gsi) ? phi : *gsi ))
+       return invalid_bb;
+      if (!stmt_to_move)
+       stmt_to_move = s;
+    }
 
+  /* The only statement here was a Predict or a nop statement
+     so return 1. */
+  if (!stmt_to_move)
+    return empty_bb;
   stmt = stmt_to_move;
-  return true;
+  return more_than_one ? feeding_bb : one_stmt_bb;
 }
 
 /* Move STMT to before GSI and insert its defining
@@ -996,14 +1018,17 @@ move_stmt (gimple *stmt, gimple_stmt_iterator *gsi, 
auto_bitmap &inserted_exprs)
 }
 
 /* RAII style class to temporarily remove flow sensitive
-   from ssa names defined by a gimple statement.  */
+   from ssa names defined by a gimple statement or
+   a whole Basic block.  */
 class auto_flow_sensitive
 {
 public:
   auto_flow_sensitive (gimple *s);
+  auto_flow_sensitive (basic_block bb);
   ~auto_flow_sensitive ();
 private:
-  auto_vec<std::pair<tree, flow_sensitive_info_storage>, 2> stack;
+  auto_vec<std::pair<tree, flow_sensitive_info_storage>, 4> stack;
+  void save_stmt (gimple *s);
 };
 
 /* Constructor for auto_flow_sensitive. Saves
@@ -1015,6 +1040,15 @@ auto_flow_sensitive::auto_flow_sensitive (gimple *s)
 {
   if (!s)
     return;
+  save_stmt (s);
+}
+
+/* Saves off the ssa names' flow sensitive information
+   that was defined by gimple statement S and
+   resets it to be non-flow based ones. */
+void
+auto_flow_sensitive::save_stmt (gimple *s)
+{
   ssa_op_iter it;
   tree def;
   FOR_EACH_SSA_TREE_OPERAND (def, s, it, SSA_OP_DEF)
@@ -1025,6 +1059,21 @@ auto_flow_sensitive::auto_flow_sensitive (gimple *s)
     }
 }
 
+/* Constructor for auto_flow_sensitive. Saves
+   off the ssa names' flow sensitive information
+   that was defined in the BB and
+   resets it to be non-flow based ones. */
+
+auto_flow_sensitive::auto_flow_sensitive (basic_block bb)
+{
+  if (!bb)
+    return;
+  gimple_stmt_iterator gsi;
+  gsi = gsi_start_nondebug_after_labels_bb (bb);
+  for (; !gsi_end_p (gsi); gsi_next_nondebug (&gsi))
+    save_stmt (*gsi);
+}
+
 /* Deconstructor, restores the flow sensitive information
    for the SSA names that had been saved off.  */
 
@@ -1083,14 +1132,20 @@ match_simplify_replacement (basic_block cond_bb, 
basic_block middle_bb,
 
   /* If the basic block only has a cheap preparation statement,
      allow it and move it once the transformation is done. */
-  if (!empty_bb_or_one_feeding_into_p (middle_bb, phi, stmt_to_move))
+  bbfeeding_info middle_bb_info = feeding_bb_info (middle_bb,
+                                                     phi, stmt_to_move);
+  if (middle_bb_info == invalid_bb)
     return false;
 
+  bbfeeding_info middle_bb_alt_info = invalid_bb;
   if (threeway_p
-      && middle_bb != middle_bb_alt
-      && !empty_bb_or_one_feeding_into_p (middle_bb_alt, phi,
-                                         stmt_to_move_alt))
-    return false;
+      && middle_bb != middle_bb_alt)
+    {
+      middle_bb_alt_info = feeding_bb_info (middle_bb_alt, phi,
+                                             stmt_to_move_alt);
+     if (middle_bb_alt_info == invalid_bb)
+       return false;
+    }
 
   /* Do not make conditional undefs unconditional.  */
   if ((TREE_CODE (arg0) == SSA_NAME
@@ -1140,8 +1195,11 @@ match_simplify_replacement (basic_block cond_bb, 
basic_block middle_bb,
 
   tree type = TREE_TYPE (gimple_phi_result (phi));
   {
-    auto_flow_sensitive s1(stmt_to_move);
-    auto_flow_sensitive s_alt(stmt_to_move_alt);
+    auto_flow_sensitive s1(middle_bb);
+    basic_block other_bb = nullptr;
+    if (middle_bb_alt_info >= one_stmt_bb)
+      other_bb = middle_bb_alt;
+    auto_flow_sensitive s_alt(other_bb);
 
     result = gimple_simplify_phiopt (early_p, type, stmt,
                                     arg_true, arg_false,
@@ -1185,7 +1243,8 @@ match_simplify_replacement (basic_block cond_bb, 
basic_block middle_bb,
         semantics (that's not IEEE max semantics).  */
       if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
         return false;
-      if (stmt_to_move || stmt_to_move_alt)
+      if (middle_bb_info >= one_stmt_bb
+         || middle_bb_alt_info >= one_stmt_bb)
        return false;
       tree_code cmp = gimple_cond_code (stmt);
       if (cmp != LT_EXPR && cmp != LE_EXPR
@@ -1207,11 +1266,104 @@ match_simplify_replacement (basic_block cond_bb, 
basic_block middle_bb,
       statistics_counter_event (cfun, "Non-IEEE FP MIN/MAX PHI replacement",
                                1);
     }
-  if (dump_file && (dump_flags & TDF_FOLDING))
-    fprintf (dump_file, "accepted the phiopt match-simplify.\n");
 
   auto_bitmap exprs_maybe_dce;
 
+  /* One of the middle BBs had more than 1 statement.   */
+  if (middle_bb_info == feeding_bb
+      || middle_bb_alt_info == feeding_bb)
+    {
+      gimple_stmt_iterator gsi = gsi_start (seq);
+      bool ok = true;
+      /* Check to see if any of the new sequence uses the definitions
+        from the middle bbs.  */
+      for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
+       {
+         gimple *s = *gsi;
+         for (unsigned i = 0; i < gimple_num_ops (s); i++)
+           {
+             tree use = gimple_op (s, i);
+             if (!use)
+               continue;
+             if (TREE_CODE (use) != SSA_NAME)
+               continue;
+             gimple *us = SSA_NAME_DEF_STMT (use);
+             if (!us)
+               continue;
+             if (us == stmt_to_move || us == stmt_to_move_alt)
+               continue;
+             basic_block use_bb = gimple_bb (us);
+             /* If an operand is defined from the middle bb
+                where there was more one statement, reject it.  */
+             if ((middle_bb_info == feeding_bb
+                  && use_bb == middle_bb)
+                 || (middle_bb_alt_info == feeding_bb
+                     && use_bb == middle_bb_alt))
+               {
+                 ok = false;
+                 break;
+               }
+           }
+         if (!ok)
+           break;
+       statistics_counter_event (cfun, "unconditionalized one middle bb 
phiopt",
+                                 1);
+       }
+      if (!ok)
+       {
+         if (dump_file && (dump_flags & TDF_FOLDING))
+           fprintf (dump_file, "rejected the phiopt match-simplify for having 
more stmts.\n");
+         return false;
+       }
+      // If the result is the one of the arguments or a partial
+      // defined in the middle bb, then make those statements unconditional.
+      if (TREE_CODE (result) == SSA_NAME
+         && (middle_bb_info == feeding_bb
+             || middle_bb_alt_info == feeding_bb))
+       {
+         gimple *us = SSA_NAME_DEF_STMT (result);
+         if (us && ((middle_bb_info == feeding_bb
+                     && gimple_bb (us) == middle_bb)
+                    || (middle_bb_alt_info == feeding_bb
+                        && gimple_bb (us) == middle_bb_alt)))
+           {
+             gimple_stmt_iterator middle_gsi;
+             basic_block use_bb = gimple_bb (us);
+             middle_gsi = gsi_start_nondebug_after_labels_bb (use_bb);
+
+             // Move the statements one at a time until reach the last 
statement
+             // or the statement that is referenced from the result.
+             while (!gsi_end_p (middle_gsi))
+               {
+                 // Skip over nop or predicates
+                 // Also don't move debug statements
+                 if (gimple_code (*middle_gsi) == GIMPLE_NOP
+                     || gimple_code (*middle_gsi) == GIMPLE_PREDICT)
+                   {
+                     gsi_next_nondebug_nonnop_nonpredict (&middle_gsi);
+                     continue;
+                   }
+                 gsi = gsi_last_bb (cond_bb);
+                 gimple *s = *middle_gsi;
+                 move_stmt (s, &gsi, exprs_maybe_dce);
+
+                 // Reached the last statement that is refenced,
+                 // all the rest would be DCEd anyways.
+                 if (s == us)
+                   break;
+                 middle_gsi = gsi_start_nondebug_after_labels_bb (use_bb);
+               }
+             stmt_to_move = nullptr;
+             stmt_to_move_alt = nullptr;
+             statistics_counter_event (cfun, "unconditionalized one middle bb 
phiopt",
+                                       1);
+           }
+       }
+    }
+
+  if (dump_file && (dump_flags & TDF_FOLDING))
+    fprintf (dump_file, "accepted the phiopt match-simplify.\n");
+
   /* Mark the cond statements' lhs/rhs as maybe dce.  */
   if (TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME
       && !SSA_NAME_IS_DEFAULT_DEF (gimple_cond_lhs (stmt)))
@@ -1231,7 +1383,7 @@ match_simplify_replacement (basic_block cond_bb, 
basic_block middle_bb,
       gsi_insert_seq_before (&gsi, seq, GSI_CONTINUE_LINKING);
     }
 
-  /* If there was a statement to move, move it to right before
+  /* If there was one statement to move, move it to right before
      the original conditional.  */
   move_stmt (stmt_to_move, &gsi, exprs_maybe_dce);
   move_stmt (stmt_to_move_alt, &gsi, exprs_maybe_dce);
@@ -2603,276 +2755,6 @@ spaceship_replacement (basic_block cond_bb, basic_block 
middle_bb,
   return true;
 }
 
-/* Optimize x ? __builtin_fun (x) : C, where C is __builtin_fun (0).
-   Convert
-
-   <bb 2>
-   if (b_4(D) != 0)
-   goto <bb 3>
-   else
-   goto <bb 4>
-
-   <bb 3>
-   _2 = (unsigned long) b_4(D);
-   _9 = __builtin_popcountl (_2);
-   OR
-   _9 = __builtin_popcountl (b_4(D));
-
-   <bb 4>
-   c_12 = PHI <0(2), _9(3)>
-
-   Into
-   <bb 2>
-   _2 = (unsigned long) b_4(D);
-   _9 = __builtin_popcountl (_2);
-   OR
-   _9 = __builtin_popcountl (b_4(D));
-
-   <bb 4>
-   c_12 = PHI <_9(2)>
-
-   Similarly for __builtin_clz or __builtin_ctz if
-   C?Z_DEFINED_VALUE_AT_ZERO is 2, optab is present and
-   instead of 0 above it uses the value from that macro.  */
-
-static bool
-cond_removal_in_builtin_zero_pattern (basic_block cond_bb,
-                                     basic_block middle_bb,
-                                     edge e1, edge e2, gphi *phi,
-                                     tree arg0, tree arg1)
-{
-  gimple_stmt_iterator gsi, gsi_from;
-  gimple *call;
-  gimple *cast = NULL;
-  tree lhs, arg;
-
-  /* Check that
-   _2 = (unsigned long) b_4(D);
-   _9 = __builtin_popcountl (_2);
-   OR
-   _9 = __builtin_popcountl (b_4(D));
-   are the only stmts in the middle_bb.  */
-
-  gsi = gsi_start_nondebug_after_labels_bb (middle_bb);
-  if (gsi_end_p (gsi))
-    return false;
-  cast = gsi_stmt (gsi);
-  gsi_next_nondebug (&gsi);
-  if (!gsi_end_p (gsi))
-    {
-      call = gsi_stmt (gsi);
-      gsi_next_nondebug (&gsi);
-      if (!gsi_end_p (gsi))
-       return false;
-    }
-  else
-    {
-      call = cast;
-      cast = NULL;
-    }
-
-  /* Check that we have a popcount/clz/ctz builtin.  */
-  if (!is_gimple_call (call))
-    return false;
-
-  lhs = gimple_get_lhs (call);
-
-  if (lhs == NULL_TREE)
-    return false;
-
-  combined_fn cfn = gimple_call_combined_fn (call);
-  if (gimple_call_num_args (call) != 1
-      && (gimple_call_num_args (call) != 2
-         || cfn == CFN_CLZ
-         || cfn == CFN_CTZ))
-    return false;
-
-  arg = gimple_call_arg (call, 0);
-
-  internal_fn ifn = IFN_LAST;
-  int val = 0;
-  bool any_val = false;
-  switch (cfn)
-    {
-    CASE_CFN_BSWAP:
-    CASE_CFN_BITREVERSE:
-    CASE_CFN_FFS:
-    CASE_CFN_PARITY:
-    CASE_CFN_POPCOUNT:
-      break;
-    CASE_CFN_CLZ:
-      if (INTEGRAL_TYPE_P (TREE_TYPE (arg)))
-       {
-         tree type = TREE_TYPE (arg);
-         if (BITINT_TYPE_P (type))
-           {
-             if (gimple_call_num_args (call) == 1)
-               {
-                 any_val = true;
-                 ifn = IFN_CLZ;
-                 break;
-               }
-             if (!tree_fits_shwi_p (gimple_call_arg (call, 1)))
-               return false;
-             HOST_WIDE_INT at_zero = tree_to_shwi (gimple_call_arg (call, 1));
-             if ((int) at_zero != at_zero)
-               return false;
-             ifn = IFN_CLZ;
-             val = at_zero;
-             break;
-           }
-         if (direct_internal_fn_supported_p (IFN_CLZ, type, OPTIMIZE_FOR_BOTH)
-             && CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (type),
-                                           val) == 2)
-           {
-             ifn = IFN_CLZ;
-             break;
-           }
-       }
-      return false;
-    CASE_CFN_CTZ:
-      if (INTEGRAL_TYPE_P (TREE_TYPE (arg)))
-       {
-         tree type = TREE_TYPE (arg);
-         if (BITINT_TYPE_P (type))
-           {
-             if (gimple_call_num_args (call) == 1)
-               {
-                 any_val = true;
-                 ifn = IFN_CTZ;
-                 break;
-               }
-             if (!tree_fits_shwi_p (gimple_call_arg (call, 1)))
-               return false;
-             HOST_WIDE_INT at_zero = tree_to_shwi (gimple_call_arg (call, 1));
-             if ((int) at_zero != at_zero)
-               return false;
-             ifn = IFN_CTZ;
-             val = at_zero;
-             break;
-           }
-         if (direct_internal_fn_supported_p (IFN_CTZ, type, OPTIMIZE_FOR_BOTH)
-             && CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_INT_TYPE_MODE (type),
-                                           val) == 2)
-           {
-             ifn = IFN_CTZ;
-             break;
-           }
-       }
-      return false;
-    case CFN_BUILT_IN_CLRSB:
-      val = TYPE_PRECISION (integer_type_node) - 1;
-      break;
-    case CFN_BUILT_IN_CLRSBL:
-      val = TYPE_PRECISION (long_integer_type_node) - 1;
-      break;
-    case CFN_BUILT_IN_CLRSBLL:
-      val = TYPE_PRECISION (long_long_integer_type_node) - 1;
-      break;
-    default:
-      return false;
-    }
-
-  if (cast)
-    {
-      /* We have a cast stmt feeding popcount/clz/ctz builtin.  */
-      /* Check that we have a cast prior to that.  */
-      if (gimple_code (cast) != GIMPLE_ASSIGN
-         || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (cast)))
-       return false;
-      /* Result of the cast stmt is the argument to the builtin.  */
-      if (arg != gimple_assign_lhs (cast))
-       return false;
-      arg = gimple_assign_rhs1 (cast);
-    }
-
-  gcond *cond = dyn_cast <gcond *> (*gsi_last_bb (cond_bb));
-
-  /* Cond_bb has a check for b_4 [!=|==] 0 before calling the popcount/clz/ctz
-     builtin.  */
-  if (!cond
-      || (gimple_cond_code (cond) != NE_EXPR
-         && gimple_cond_code (cond) != EQ_EXPR)
-      || !integer_zerop (gimple_cond_rhs (cond))
-      || arg != gimple_cond_lhs (cond))
-    return false;
-
-  edge true_edge, false_edge;
-  /* We need to know which is the true edge and which is the false
-     edge so that we know when to invert the condition below.  */
-  extract_true_false_edges_from_block (cond_bb, &true_edge, &false_edge);
-
-  /* Forward the edges over the middle basic block.  */
-  if (true_edge->dest == middle_bb)
-    true_edge = EDGE_SUCC (true_edge->dest, 0);
-  if (false_edge->dest == middle_bb)
-    false_edge = EDGE_SUCC (false_edge->dest, 0);
-
-  /* Canonicalize the args with respect to the edges,
-     arg0 is from the true edge and arg1 is from the
-     false edge.
-     That is `cond ? arg0 : arg1`.*/
-  if (true_edge == e1)
-    gcc_assert (false_edge == e2);
-  else
-    {
-      gcc_assert (false_edge == e1);
-      gcc_assert (true_edge == e2);
-      std::swap (arg0, arg1);
-    }
-
-  /* Canonicalize the args such that we get:
-     `arg != 0 ? arg0 : arg1`. So swap arg0/arg1
-     around if cond was an equals.  */
-  if (gimple_cond_code (cond) == EQ_EXPR)
-    std::swap (arg0, arg1);
-
-  /* Check PHI arguments.  */
-  if (lhs != arg0
-      || TREE_CODE (arg1) != INTEGER_CST)
-    return false;
-  if (any_val)
-    {
-      if (!tree_fits_shwi_p (arg1))
-       return false;
-      HOST_WIDE_INT at_zero = tree_to_shwi (arg1);
-      if ((int) at_zero != at_zero)
-       return false;
-      val = at_zero;
-    }
-  else if (wi::to_wide (arg1) != val)
-    return false;
-
-  /* And insert the popcount/clz/ctz builtin and cast stmt before the
-     cond_bb.  */
-  gsi = gsi_last_bb (cond_bb);
-  if (cast)
-    {
-      gsi_from = gsi_for_stmt (cast);
-      gsi_move_before (&gsi_from, &gsi);
-      reset_flow_sensitive_info (gimple_get_lhs (cast));
-    }
-  gsi_from = gsi_for_stmt (call);
-  if (ifn == IFN_LAST
-      || (gimple_call_internal_p (call) && gimple_call_num_args (call) == 2))
-    gsi_move_before (&gsi_from, &gsi);
-  else
-    {
-      /* For __builtin_c[lt]z* force .C[LT]Z ifn, because only
-        the latter is well defined at zero.  */
-      call = gimple_build_call_internal (ifn, 2, gimple_call_arg (call, 0),
-                                        build_int_cst (integer_type_node, 
val));
-      gimple_call_set_lhs (call, lhs);
-      gsi_insert_before (&gsi, call, GSI_SAME_STMT);
-      gsi_remove (&gsi_from, true);
-    }
-  reset_flow_sensitive_info (lhs);
-
-  /* Now update the PHI and remove unneeded bbs.  */
-  replace_phi_edge_with_variable (cond_bb, e2, phi, lhs);
-  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
@@ -4535,12 +4417,6 @@ pass_phiopt::execute (function *)
       if (match_simplify_replacement (bb, bb1, bb2, e1, e2, phi,
                                      arg0, arg1, early_p, diamond_p))
        cfgchanged = true;
-      else if (!early_p
-              && !diamond_p
-              && single_pred_p (bb1)
-              && cond_removal_in_builtin_zero_pattern (bb, bb1, e1, e2,
-                                                       phi, arg0, arg1))
-       cfgchanged = true;
       else if (single_pred_p (bb1)
               && !diamond_p
               && spaceship_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
-- 
2.43.0

Reply via email to