On Wed, Sep 20, 2023 at 6:10 AM Lehua Ding <lehua.d...@rivai.ai> wrote: > > This patch adds combine cond_len_op and vec_cond to cond_len_op like > cond_op. > > gcc/ChangeLog: > > * gimple-match.h (gimple_match_op::gimple_match_op): > Add interfaces for more arguments. > (gimple_match_op::set_op): Add interfaces for more arguments. > * match.pd: Add support of combining cond_len_op + vec_cond > --- > gcc/gimple-match.h | 72 ++++++++++++++++++++++++++++++++++++++++++++++ > gcc/match.pd | 39 +++++++++++++++++++++++++ > 2 files changed, 111 insertions(+) > > diff --git a/gcc/gimple-match.h b/gcc/gimple-match.h > index bec3ff42e3e..9892c142285 100644 > --- a/gcc/gimple-match.h > +++ b/gcc/gimple-match.h > @@ -92,6 +92,10 @@ public: > code_helper, tree, tree, tree, tree, tree); > gimple_match_op (const gimple_match_cond &, > code_helper, tree, tree, tree, tree, tree, tree); > + gimple_match_op (const gimple_match_cond &, > + code_helper, tree, tree, tree, tree, tree, tree, tree); > + gimple_match_op (const gimple_match_cond &, > + code_helper, tree, tree, tree, tree, tree, tree, tree, > tree); > > void set_op (code_helper, tree, unsigned int); > void set_op (code_helper, tree, tree); > @@ -100,6 +104,8 @@ public: > void set_op (code_helper, tree, tree, tree, tree, bool); > void set_op (code_helper, tree, tree, tree, tree, tree); > void set_op (code_helper, tree, tree, tree, tree, tree, tree); > + void set_op (code_helper, tree, tree, tree, tree, tree, tree, tree); > + void set_op (code_helper, tree, tree, tree, tree, tree, tree, tree, tree); > void set_value (tree); > > tree op_or_null (unsigned int) const; > @@ -212,6 +218,39 @@ gimple_match_op::gimple_match_op (const > gimple_match_cond &cond_in, > ops[4] = op4; > } > > +inline > +gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, > + code_helper code_in, tree type_in, > + tree op0, tree op1, tree op2, tree op3, > + tree op4, tree op5) > + : cond (cond_in), code (code_in), type (type_in), reverse (false), > + num_ops (6) > +{ > + ops[0] = op0; > + ops[1] = op1; > + ops[2] = op2; > + ops[3] = op3; > + ops[4] = op4; > + ops[5] = op5; > +}
Hmm, does it make sense to start to use variadic templates for these constructors instead of writing them out? And we can even add a static_assert to make sure the number of arguments is <= MAX_NUM_OPS to make sure they are correct. And use std::is_same to make sure we are only passing tree types. Thanks, Andrew > + > +inline > +gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, > + code_helper code_in, tree type_in, > + tree op0, tree op1, tree op2, tree op3, > + tree op4, tree op5, tree op6) > + : cond (cond_in), code (code_in), type (type_in), reverse (false), > + num_ops (7) > +{ > + ops[0] = op0; > + ops[1] = op1; > + ops[2] = op2; > + ops[3] = op3; > + ops[4] = op4; > + ops[5] = op5; > + ops[6] = op6; > +} > + > /* Change the operation performed to CODE_IN, the type of the result to > TYPE_IN, and the number of operands to NUM_OPS_IN. The caller needs > to set the operands itself. */ > @@ -299,6 +338,39 @@ gimple_match_op::set_op (code_helper code_in, tree > type_in, > ops[4] = op4; > } > > +inline void > +gimple_match_op::set_op (code_helper code_in, tree type_in, > + tree op0, tree op1, tree op2, tree op3, tree op4, > + tree op5) > +{ > + code = code_in; > + type = type_in; > + num_ops = 6; > + ops[0] = op0; > + ops[1] = op1; > + ops[2] = op2; > + ops[3] = op3; > + ops[4] = op4; > + ops[5] = op5; > +} > + > +inline void > +gimple_match_op::set_op (code_helper code_in, tree type_in, > + tree op0, tree op1, tree op2, tree op3, tree op4, > + tree op5, tree op6) > +{ > + code = code_in; > + type = type_in; > + num_ops = 7; > + ops[0] = op0; > + ops[1] = op1; > + ops[2] = op2; > + ops[3] = op3; > + ops[4] = op4; > + ops[5] = op5; > + ops[6] = op6; > +} > + > /* Set the "operation" to be the single value VALUE, such as a constant > or SSA_NAME. */ > > diff --git a/gcc/match.pd b/gcc/match.pd > index a37af05f873..75b7e100120 100644 > --- a/gcc/match.pd > +++ b/gcc/match.pd > @@ -103,12 +103,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > IFN_COND_FMIN IFN_COND_FMAX > IFN_COND_AND IFN_COND_IOR IFN_COND_XOR > IFN_COND_SHL IFN_COND_SHR) > +(define_operator_list COND_LEN_BINARY > + IFN_COND_LEN_ADD IFN_COND_LEN_SUB > + IFN_COND_LEN_MUL IFN_COND_LEN_DIV > + IFN_COND_LEN_MOD IFN_COND_LEN_RDIV > + IFN_COND_LEN_MIN IFN_COND_LEN_MAX > + IFN_COND_LEN_FMIN IFN_COND_LEN_FMAX > + IFN_COND_LEN_AND IFN_COND_LEN_IOR IFN_COND_LEN_XOR > + IFN_COND_LEN_SHL IFN_COND_LEN_SHR) > > /* Same for ternary operations. */ > (define_operator_list UNCOND_TERNARY > IFN_FMA IFN_FMS IFN_FNMA IFN_FNMS) > (define_operator_list COND_TERNARY > IFN_COND_FMA IFN_COND_FMS IFN_COND_FNMA IFN_COND_FNMS) > +(define_operator_list COND_LEN_TERNARY > + IFN_COND_LEN_FMA IFN_COND_LEN_FMS IFN_COND_LEN_FNMA IFN_COND_LEN_FNMS) > > /* __atomic_fetch_or_*, __atomic_fetch_xor_*, __atomic_xor_fetch_* */ > (define_operator_list ATOMIC_FETCH_OR_XOR_N > @@ -8861,6 +8871,35 @@ and, > && element_precision (type) == element_precision (op_type)) > (view_convert (cond_op @2 @3 @4 @5 (view_convert:op_type @1))))))) > > +/* Detect cases in which a VEC_COND_EXPR effectively replaces the > + "else" value of an IFN_COND_LEN_*. */ > +(for cond_len_op (COND_LEN_BINARY) > + (simplify > + (vec_cond @0 (view_convert? (cond_len_op @0 @1 @2 @3 @4 @5)) @6) > + (with { tree op_type = TREE_TYPE (@3); } > + (if (element_precision (type) == element_precision (op_type)) > + (view_convert (cond_len_op @0 @1 @2 (view_convert:op_type @6) @4 @5))))) > + (simplify > + (vec_cond @0 @1 (view_convert? (cond_len_op @2 @3 @4 @5 @6 @7))) > + (with { tree op_type = TREE_TYPE (@5); } > + (if (inverse_conditions_p (@0, @2) > + && element_precision (type) == element_precision (op_type)) > + (view_convert (cond_len_op @2 @3 @4 (view_convert:op_type @1) @6 @7)))))) > + > +/* Same for ternary operations. */ > +(for cond_len_op (COND_LEN_TERNARY) > + (simplify > + (vec_cond @0 (view_convert? (cond_len_op @0 @1 @2 @3 @4 @5 @6)) @7) > + (with { tree op_type = TREE_TYPE (@4); } > + (if (element_precision (type) == element_precision (op_type)) > + (view_convert (cond_len_op @0 @1 @2 @3 (view_convert:op_type @7) @5 > @6))))) > + (simplify > + (vec_cond @0 @1 (view_convert? (cond_len_op @2 @3 @4 @5 @6 @7 @8))) > + (with { tree op_type = TREE_TYPE (@6); } > + (if (inverse_conditions_p (@0, @2) > + && element_precision (type) == element_precision (op_type)) > + (view_convert (cond_len_op @2 @3 @4 @5 (view_convert:op_type @1) @7 > @8)))))) > + > /* Detect simplication for a conditional reduction where > > a = mask1 ? b : 0 > -- > 2.36.3 >