On Wed, Sep 11, 2024 at 8:31 AM <pan2...@intel.com> wrote: > > From: Pan Li <pan2...@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. > > There will be some additional handling if one of the arg is INTEGER_CST. > Because the INTEGER_CST args may have no source block, thus its' edge > source points to the condition block. See below example in line 31, > the 255 INTEGER_CST has block 2 as source. Thus, we need to find > the non-INTEGER_CST (aka _1) to tell which one is the true/false edge. > For example, the _1(3) takes block 3 as source, which is the dest > of false edge of the condition block. > > 4 │ __attribute__((noinline)) > 5 │ uint8_t sat_u_add_imm_type_check_uint8_t_fmt_2 (uint8_t x) > 6 │ { > 7 │ unsigned char _1; > 8 │ unsigned char _2; > 9 │ uint8_t _3; > 10 │ __complex__ unsigned char _5; > 11 │ > 12 │ ;; basic block 2, loop depth 0 > 13 │ ;; pred: ENTRY > 14 │ _5 = .ADD_OVERFLOW (x_4(D), 9); > 15 │ _2 = IMAGPART_EXPR <_5>; > 16 │ if (_2 != 0) > 17 │ goto <bb 4>; [35.00%] > 18 │ else > 19 │ goto <bb 3>; [65.00%] > 20 │ ;; succ: 3 > 21 │ ;; 4 > 22 │ > 23 │ ;; basic block 3, loop depth 0 > 24 │ ;; pred: 2 > 25 │ _1 = REALPART_EXPR <_5>; > 26 │ ;; succ: 4 > 27 │ > 28 │ ;; basic block 4, loop depth 0 > 29 │ ;; pred: 2 > 30 │ ;; 3 > 31 │ # _3 = PHI <255(2), _1(3)> > 32 │ return _3; > 33 │ ;; succ: EXIT > 34 │ > 35 │ } > > The below test suites are passed for this patch. > * The rv64gcv fully regression test. > * The x86 bootstrap test. > * The x86 fully regression test. > > 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...@intel.com> > --- > gcc/gimple-match-head.cc | 60 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 60 insertions(+) > > diff --git a/gcc/gimple-match-head.cc b/gcc/gimple-match-head.cc > index c51728ae742..64f4f28cc72 100644 > --- a/gcc/gimple-match-head.cc > +++ b/gcc/gimple-match-head.cc > @@ -490,3 +490,63 @@ match_control_flow_graph_case_1 (basic_block b3, > basic_block *b_out) > *b_out = b0; > return true; > } > + > +/* > + * Return the relevant gcond * of the given phi, as well as the true > + * and false TREE args of the phi. Or return NULL. > + * > + * 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, NULL 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) > +{ > + basic_block cond_block; > + *true_arg = *false_arg = NULL_TREE; > + > + if (gimple_phi_num_args (phi) != 2) > + return NULL; > + > + if (!match_control_flow_graph_case_0 (gimple_bb (phi), &cond_block) > + && !match_control_flow_graph_case_1 (gimple_bb (phi), &cond_block)) > + return NULL; > + > + gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (cond_block)); > + > + if (!cond || EDGE_COUNT (cond_block->succs) != 2) > + return NULL; > + > + tree t0 = gimple_phi_arg_def (phi, 0); > + tree t1 = gimple_phi_arg_def (phi, 1); > + edge e0 = gimple_phi_arg_edge (phi, 0); > + edge e1 = gimple_phi_arg_edge (phi, 1); > + > + if (TREE_CODE (t0) == INTEGER_CST && TREE_CODE (t1) == INTEGER_CST) > + return NULL; > + > + bool arg_0_cst_p = TREE_CODE (t0) == INTEGER_CST; > + edge arg_edge = arg_0_cst_p ? e1 : e0; > + tree arg = arg_0_cst_p ? t1 : t0; > + tree other_arg = arg_0_cst_p ? t0 : t1;
why would arg_edge depend on whether t0 is INTEGER_CST or not? > + edge cond_e0 = EDGE_SUCC (cond_block, 0); > + edge cond_e1 = EDGE_SUCC (cond_block, 1); > + edge matched_edge = arg_edge->src == cond_e0->dest ? cond_e0 : cond_e1; > + > + if (matched_edge->flags & EDGE_TRUE_VALUE) I don't think this works reliably like for case 0 if cond_e0 leads to the PHI block? Can you instead inline match_control_flow_graph_case_0 and _1 and do the argument assignment within the three cases of CFGs we accept? That would be much easier to follow. > + { > + *true_arg = arg; > + *false_arg = other_arg; > + } > + else > + { > + *false_arg = arg; > + *true_arg = other_arg; > + } > + > + return cond; > +} > -- > 2.43.0 >