On Wed, Sep 20, 2023 at 6:10 AM Lehua Ding <[email protected]> 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
>