From 711d703d07c8e9241361975674843cf0a3263f98 Mon Sep 17 00:00:00 2001 From: Lehua Ding Date: Tue, 19 Sep 2023 15:53:54 +0800 Subject: [PATCH] match.pd: Support combine cond_len_op + vec_cond similar to cond_op This patch adds combine cond_len_op and vec_cond to cond_len_op like cond_op. Consider this code (RISC-V target): void foo (uint8_t *__restrict x, uint8_t *__restrict y, uint8_t *__restrict z, uint8_t *__restrict pred, uint8_t *__restrict merged, int n) { for (int i = 0; i < n; ++i) x[i] = pred[i] != 1 ? y[i] / z[i] : merged[i]; } Before this patch: ... vect_iftmp.18_71 = .COND_LEN_DIV (mask__31.11_61, vect__5.14_65, vect__7.17_69, { 0, ... }, _86, 0); vect_iftmp.23_78 = .VCOND_MASK (mask__31.11_61, vect_iftmp.18_71, vect_iftmp.22_77); ... After this patch: ... _30 = .COND_LEN_DIV (mask__31.16_61, vect__5.19_65, vect__7.22_69, vect_iftmp.27_77, _85, 0); ... 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 bec3ff42e3ec..9892c1422855 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; +} + +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 070db9880ec5..424bbd022330 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 @@ -9046,6 +9056,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.43.5