On Tue, Oct 20, 2026 at 5:56 PM Andrea Pinski
<[email protected]> wrote:
>
> 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. And there is a limited number of stmts is allowed.
> Also have an allow list of expressions type to be used after the first few 
> stmts.
>
> 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.
>
> Changes since v1:
> * v2: Add allow list to feeding_bb_info and add a limit to
> the number of stmts to consider. Adds 2 testcases based on 2 pre-existing 
> match patterns to
> show what can be done.

Just an FYI.  There are some bugs in this patch; I am fixing them.

>
> 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.
>         * params.opt (-param=phiopt-max-feeding-stmts=): New option.
>         * doc/params.texi (phiopt-max-feeding-stmts): Document.
>
>         PR tree-optimization/127166
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/tree-ssa/ssa-dom-thread-16.c: Disable phiopt.
>         * gcc.dg/tree-ssa/clamp-1.c: New test.
>         * gcc.dg/tree-ssa/umax-sub-1.c: New test.
>
> Signed-off-by: Andrea Pinski <[email protected]>
> ---
>  gcc/doc/params.texi                           |   5 +
>  gcc/params.opt                                |   4 +
>  gcc/testsuite/gcc.dg/tree-ssa/clamp-1.c       |  25 ++
>  .../gcc.dg/tree-ssa/ssa-dom-thread-16.c       |   2 +-
>  gcc/testsuite/gcc.dg/tree-ssa/umax-sub-1.c    |  14 +
>  gcc/tree-ssa-phiopt.cc                        | 373 +++++++++++++-----
>  6 files changed, 331 insertions(+), 92 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/clamp-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/umax-sub-1.c
>
> diff --git a/gcc/doc/params.texi b/gcc/doc/params.texi
> index 090af64a7e7..b26513a7ea1 100644
> --- a/gcc/doc/params.texi
> +++ b/gcc/doc/params.texi
> @@ -57,6 +57,11 @@ When factoring statements out of if/then/else, this is the 
> maximum number
>  of statements
>  after the defining statement to be allowed to extend the lifetime of a name.
>
> +@paindex phiopt-max-feeding-stmts
> +@item phiopt-max-feeding-stmts
> +When deciding if a basic block is too big to phiopt, this decides the maximum
> +number of statements that feed into one another is too many. This excludes 
> converts.
> +
>  @paindex predictable-branch-outcome
>  @item predictable-branch-outcome
>  When branch is predicted to be taken with probability lower than this 
> threshold
> diff --git a/gcc/params.opt b/gcc/params.opt
> index 29a5c7018a8..f0702f97625 100644
> --- a/gcc/params.opt
> +++ b/gcc/params.opt
> @@ -958,6 +958,10 @@ Maximum probability of the entry BB of split region (as 
> a percentage relative to
>  Common Joined UInteger Var(param_phiopt_factor_max_stmts_live) Init(5) 
> Optimization IntegerRange(0, 100) Param
>  Maximum number of statements allowed between a defining statement and the 
> end of the basic block before extending the live range is considered 
> profitable.
>
> +-param=phiopt-max-feeding-stmts=
> +Common Joined UInteger Var(param_phiopt_max_feeding_stmts) Init(4) 
> Optimization IntegerRange(1, 100) Param
> +Maximum number of statements can considered for each basic block excluding 
> converts.
> +
>  -param=predictable-branch-outcome=
>  Common Joined UInteger Var(param_predictable_branch_outcome) Init(2) 
> IntegerRange(0, 50) Param Optimization
>  Maximal estimated outcome of branch considered predictable.
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/clamp-1.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/clamp-1.c
> new file mode 100644
> index 00000000000..43239772ca0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/clamp-1.c
> @@ -0,0 +1,25 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-phiopt2-details -fdump-tree-optimized" } */
> +
> +/* PR tree-optimization/127166 */
> +
> +unsigned char clip(int x)
> +{
> +  unsigned u;
> +  unsigned char r;
> +  u = x;
> +  r = x;
> +  if (u > 255)
> +  {
> +    int n = -x;
> +    int s = n >> (sizeof(int)*8 - 1);
> +    r = s;
> +  }
> +  return r;
> +}
> +
> +
> +/* { dg-final { scan-tree-dump "converted to straightline code" "phiopt2" } 
> } */
> +/* { dg-final { scan-tree-dump "MAX_EXPR" "phiopt2" } } */
> +/* { dg-final { scan-tree-dump "MIN_EXPR" "phiopt2" } } */
> +/* { dg-final { scan-tree-dump-not "if " "optimized" } } */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
> index e8555f2d963..51b686b1de8 100644
> --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-16.c
> @@ -1,5 +1,5 @@
>  /* { dg-do compile } */
> -/* { dg-options "-O2 -fdump-tree-dom2-details -w --param 
> logical-op-non-short-circuit=1 -fdisable-tree-threadfull1" } */
> +/* { dg-options "-O2 -fdump-tree-dom2-details -w --param 
> logical-op-non-short-circuit=1 -fdisable-tree-threadfull1 -fno-ssa-phiopt" } 
> */
>  unsigned char
>  validate_subreg (unsigned int offset, unsigned int isize, unsigned int 
> osize, int zz, int qq)
>  {
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/umax-sub-1.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/umax-sub-1.c
> new file mode 100644
> index 00000000000..c07eb4154d6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/umax-sub-1.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-phiopt2-details -fdump-tree-optimized" } */
> +
> +signed f1 (signed  x)
> +{
> +  if (x == 0)  return 0;
> +  unsigned y = x;
> +  y -= 1;
> +  x = y;
> +  return x;
> +}
> +
> +/* { dg-final { scan-tree-dump "converted to straightline code" "phiopt2" } 
> } */
> +/* { dg-final { scan-tree-dump-not "if " "optimized" } } */
> diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
> index 6f4eb8fe547..0408780d97a 100644
> --- a/gcc/tree-ssa-phiopt.cc
> +++ b/gcc/tree-ssa-phiopt.cc
> @@ -826,6 +826,19 @@ gimple_simplify_phiopt (bool early_p, tree type, gimple 
> *comp_stmt,
>    return NULL;
>  }
>
> +/* 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));
> +}
> +
>  /* one_feeding_comparison_into_p returns true if BB has one comparison
>     statement and it sets STMT to that statement.  Note the comparison can
>     be trapping too.  */
> @@ -890,110 +903,158 @@ one_feeding_comparison_into_p (basic_block bb,
>    return true;
>  }
>
> -/* 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)
> +
> +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);
> +  int stmts = 0;
> +  int stmts_minus_convert = 0;
> +  bool non_allowed_stmt = false;
>    while (!gsi_end_p (gsi))
>      {
> -      gimple *s = gsi_stmt (gsi);
> -      gsi_next_nondebug (&gsi);
> -      /* Skip over Predict and nop statements. */
> +      gimple *s = *gsi;
> +      gsi_next_nondebug_nonnop_nonpredict (&gsi);
> +      // Skip over predict and nop statements which could happen
> +      // if they are at the beginging.
>        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)
> +      stmts++;
> +      stmts_minus_convert++;
> +      if (stmts_minus_convert > param_phiopt_max_feeding_stmts)
> +       return invalid_bb;
> +      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 some 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);
> +             // A call can only be the first non-allowed stmt.
> +             if (non_allowed_stmt)
> +               return invalid_bb;
> +             break;
> +           }
> +       }
> +      else
> +       {
> +         // Only allow a few different for the feeding list.
> +         switch (gimple_assign_rhs_code (s))
> +           {
> +           // Always allow a convert.
> +           CASE_CONVERT:
> +             stmts_minus_convert --;
> +             break;
> +           case PLUS_EXPR:
> +           case MINUS_EXPR:
> +           case ABS_EXPR:
> +           case ABSU_EXPR:
> +           case BIT_IOR_EXPR:
> +           case BIT_XOR_EXPR:
> +           case BIT_AND_EXPR:
> +           case MIN_EXPR:
> +           case MAX_EXPR:
> +           case NEGATE_EXPR:
> +             break;
> +           // Shifts with a constant shifter are on the allow list.
> +           case LSHIFT_EXPR:
> +           case RSHIFT_EXPR:
> +             if (TREE_CODE (gimple_assign_rhs2 (s)) == INTEGER_CST)
> +               break;
> +           // FALLTHRU
> +           default:
> +             // Allow all kind of expressions after the first convert.
> +             if (stmts_minus_convert > 1 && non_allowed_stmt)
> +               return invalid_bb;
> +             non_allowed_stmt = true;
> +           }
> +         lhs = gimple_assign_lhs (s);
>         }
> -    }
> -  else
> -    lhs = gimple_assign_lhs (stmt_to_move);
>
> -  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 (stmts == 0)
> +    return empty_bb;
>    stmt = stmt_to_move;
> -  return true;
> +  return stmts > 1 ? feeding_bb : one_stmt_bb;
>  }
>
>  /* Move STMT to before GSI and insert its defining
> @@ -1025,14 +1086,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
> @@ -1044,6 +1108,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)
> @@ -1054,6 +1127,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.  */
>
> @@ -1112,14 +1200,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
> @@ -1169,12 +1263,15 @@ 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,
> -                                   &seq);
> +                                    &seq);
>    }
>
>    /* For early phiopt, we don't want to lose user generated predictors
> @@ -1214,7 +1311,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
> @@ -1236,11 +1334,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 one statements.   */
> +  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;
> +       }
> +      if (!ok)
> +       {
> +         if (dump_file && (dump_flags & TDF_FOLDING))
> +           fprintf (dump_file, "rejected the phiopt match-simplify for 
> having more stmts.\n");
> +         return false;
> +       }
> +      statistics_counter_event (cfun, "unconditionalized one middle bb 
> phiopt",
> +                               1);
> +      // 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)))
> @@ -1260,7 +1451,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);
> --
> 2.43.0
>

Reply via email to