Message ID | 20240919041038.3796202-1-pan2.li@intel.com |
---|---|
State | New |
Headers | show |
Series | [v5,1/4] Match: Add interface match_cond_with_binary_phi for true/false arg | expand |
On Thu, Sep 19, 2024 at 6:11 AM <pan2.li@intel.com> wrote: > > From: Pan Li <pan2.li@intel.com> > > When matching the cond with 2 args phi node, we need to figure out > which arg of phi node comes from the true edge of cond block, as > well as the false edge. This patch would like to add interface > to perform the action and return the true and false arg in TREE type. > > The below test suites are passed for this patch. > * The rv64gcv fully regression test. > * The x86 bootstrap test. > * The x86 fully regression test. OK. Thanks, Richard. > gcc/ChangeLog: > > * gimple-match-head.cc (match_cond_with_binary_phi): Add new func > impl to match binary phi for true and false arg. > > Signed-off-by: Pan Li <pan2.li@intel.com> > --- > gcc/gimple-match-head.cc | 120 +++++++++++++++++++++++++++++++++++++++ > 1 file changed, 120 insertions(+) > > diff --git a/gcc/gimple-match-head.cc b/gcc/gimple-match-head.cc > index 924d3f1e710..b63b66e9485 100644 > --- a/gcc/gimple-match-head.cc > +++ b/gcc/gimple-match-head.cc > @@ -375,3 +375,123 @@ gimple_bitwise_inverted_equal_p (tree expr1, tree expr2, bool &wascmp, tree (*va > return true; > return false; > } > + > +/* > + * Return the relevant gcond * of the given phi, as well as the true > + * and false TREE args of the phi. Or return nullptr. > + * > + * If matched the gcond *, the output argument TREE true_arg and false_arg > + * will be updated to the relevant args of phi. > + * > + * If failed to match, nullptr gcond * will be returned, as well as the output > + * arguments will be set to NULL_TREE. > + */ > + > +static inline gcond * > +match_cond_with_binary_phi (gphi *phi, tree *true_arg, tree *false_arg) > +{ > + *true_arg = *false_arg = NULL_TREE; > + > + if (gimple_phi_num_args (phi) != 2) > + return nullptr; > + > + basic_block pred_b0 = EDGE_PRED (gimple_bb (phi), 0)->src; > + basic_block pred_b1 = EDGE_PRED (gimple_bb (phi), 1)->src; > + edge edge_for_pred_0 = nullptr; > + > + if (EDGE_COUNT (pred_b0->succs) == 2 > + && EDGE_COUNT (pred_b1->succs) == 1 > + && EDGE_COUNT (pred_b1->preds) == 1 > + && pred_b0 == EDGE_PRED (gimple_bb (phi), 0)->src) > + /* > + * +------+ > + * | b0: | > + * | def | +-----+ > + * | ... | | b1: | > + * | cond |------>| def | > + * +------+ | ... | > + * | +-----+ > + * # | > + * | | > + * v | > + * +-----+ | > + * | b2: | | > + * | def |<----------+ > + * +-----+ > + * #: edge_for_pred_0. > + */ > + edge_for_pred_0 = EDGE_PRED (gimple_bb (phi), 0); > + else if (EDGE_COUNT (pred_b1->succs) == 2 > + && EDGE_COUNT (pred_b0->succs) == 1 > + && EDGE_COUNT (pred_b0->preds) == 1 > + && pred_b1 == EDGE_PRED (pred_b0, 0)->src) > + /* > + * +------+ > + * | b1: | > + * +-----+ | def | > + * | b0: | | ... | > + * | def |<---#---| cond | > + * | ... | +------+ > + * +-----+ | > + * | | > + * | | > + * | | > + * v | > + * +-----+ | > + * | b2: | | > + * | def |<----------+ > + * +-----+ > + * #: edge_for_pred_0. > + */ > + edge_for_pred_0 = EDGE_PRED (pred_b0, 0); > + else if (EDGE_COUNT (pred_b0->succs) == 1 > + && EDGE_COUNT (pred_b1->succs) == 1 > + && EDGE_COUNT (pred_b0->preds) == 1 > + && EDGE_COUNT (pred_b1->preds) == 1 > + && EDGE_COUNT (EDGE_PRED (pred_b0, 0)->src->succs) == 2 > + && EDGE_PRED (pred_b0, 0)->src == EDGE_PRED (pred_b1, 0)->src) > + /* +------+ > + * | b0: | > + * | ... | +-----+ > + * | cond |------>| b2: | > + * +------+ | ... | > + * | +-----+ > + * # | > + * | | > + * v | > + * +-----+ | > + * | b1: | | > + * | ... | | > + * +-----+ | > + * | | > + * | | > + * v | > + * +-----+ | > + * | b3: |<----------+ > + * | ... | > + * +-----+ > + * #: edge_for_pred_0. > + */ > + edge_for_pred_0 = EDGE_PRED (pred_b0, 0); > + > + if (!edge_for_pred_0) > + return nullptr; > + > + gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (edge_for_pred_0->src)); > + > + if (!cond) > + return nullptr; > + > + if (edge_for_pred_0->flags & EDGE_TRUE_VALUE) > + { > + *true_arg = gimple_phi_arg_def (phi, 0); > + *false_arg = gimple_phi_arg_def (phi, 1); > + } > + else /* Aka edge_for_pred_0->flags & EDGE_FALSE_VALUE */ > + { > + *false_arg = gimple_phi_arg_def (phi, 0); > + *true_arg = gimple_phi_arg_def (phi, 1); > + } > + > + return cond; > +} > -- > 2.43.0 >
diff --git a/gcc/gimple-match-head.cc b/gcc/gimple-match-head.cc index 924d3f1e710..b63b66e9485 100644 --- a/gcc/gimple-match-head.cc +++ b/gcc/gimple-match-head.cc @@ -375,3 +375,123 @@ gimple_bitwise_inverted_equal_p (tree expr1, tree expr2, bool &wascmp, tree (*va return true; return false; } + +/* + * Return the relevant gcond * of the given phi, as well as the true + * and false TREE args of the phi. Or return nullptr. + * + * If matched the gcond *, the output argument TREE true_arg and false_arg + * will be updated to the relevant args of phi. + * + * If failed to match, nullptr gcond * will be returned, as well as the output + * arguments will be set to NULL_TREE. + */ + +static inline gcond * +match_cond_with_binary_phi (gphi *phi, tree *true_arg, tree *false_arg) +{ + *true_arg = *false_arg = NULL_TREE; + + if (gimple_phi_num_args (phi) != 2) + return nullptr; + + basic_block pred_b0 = EDGE_PRED (gimple_bb (phi), 0)->src; + basic_block pred_b1 = EDGE_PRED (gimple_bb (phi), 1)->src; + edge edge_for_pred_0 = nullptr; + + if (EDGE_COUNT (pred_b0->succs) == 2 + && EDGE_COUNT (pred_b1->succs) == 1 + && EDGE_COUNT (pred_b1->preds) == 1 + && pred_b0 == EDGE_PRED (gimple_bb (phi), 0)->src) + /* + * +------+ + * | b0: | + * | def | +-----+ + * | ... | | b1: | + * | cond |------>| def | + * +------+ | ... | + * | +-----+ + * # | + * | | + * v | + * +-----+ | + * | b2: | | + * | def |<----------+ + * +-----+ + * #: edge_for_pred_0. + */ + edge_for_pred_0 = EDGE_PRED (gimple_bb (phi), 0); + else if (EDGE_COUNT (pred_b1->succs) == 2 + && EDGE_COUNT (pred_b0->succs) == 1 + && EDGE_COUNT (pred_b0->preds) == 1 + && pred_b1 == EDGE_PRED (pred_b0, 0)->src) + /* + * +------+ + * | b1: | + * +-----+ | def | + * | b0: | | ... | + * | def |<---#---| cond | + * | ... | +------+ + * +-----+ | + * | | + * | | + * | | + * v | + * +-----+ | + * | b2: | | + * | def |<----------+ + * +-----+ + * #: edge_for_pred_0. + */ + edge_for_pred_0 = EDGE_PRED (pred_b0, 0); + else if (EDGE_COUNT (pred_b0->succs) == 1 + && EDGE_COUNT (pred_b1->succs) == 1 + && EDGE_COUNT (pred_b0->preds) == 1 + && EDGE_COUNT (pred_b1->preds) == 1 + && EDGE_COUNT (EDGE_PRED (pred_b0, 0)->src->succs) == 2 + && EDGE_PRED (pred_b0, 0)->src == EDGE_PRED (pred_b1, 0)->src) + /* +------+ + * | b0: | + * | ... | +-----+ + * | cond |------>| b2: | + * +------+ | ... | + * | +-----+ + * # | + * | | + * v | + * +-----+ | + * | b1: | | + * | ... | | + * +-----+ | + * | | + * | | + * v | + * +-----+ | + * | b3: |<----------+ + * | ... | + * +-----+ + * #: edge_for_pred_0. + */ + edge_for_pred_0 = EDGE_PRED (pred_b0, 0); + + if (!edge_for_pred_0) + return nullptr; + + gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (edge_for_pred_0->src)); + + if (!cond) + return nullptr; + + if (edge_for_pred_0->flags & EDGE_TRUE_VALUE) + { + *true_arg = gimple_phi_arg_def (phi, 0); + *false_arg = gimple_phi_arg_def (phi, 1); + } + else /* Aka edge_for_pred_0->flags & EDGE_FALSE_VALUE */ + { + *false_arg = gimple_phi_arg_def (phi, 0); + *true_arg = gimple_phi_arg_def (phi, 1); + } + + return cond; +}