From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtpbg150.qq.com (smtpbg150.qq.com [18.132.163.193]) by sourceware.org (Postfix) with ESMTPS id D9D443858D33 for ; Mon, 13 Feb 2023 07:41:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D9D443858D33 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=rivai.ai Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=rivai.ai X-QQ-mid: bizesmtp62t1676274074tmlq434r Received: from rios-cad5.localdomain ( [58.60.1.11]) by bizesmtp.qq.com (ESMTP) with id ; Mon, 13 Feb 2023 15:41:13 +0800 (CST) X-QQ-SSF: 01400000000000E0L000000A0000000 X-QQ-FEAT: RmDZc/K2LPGQa8VeO8Mm2pFOf9EnzuCpF5spByZMFugmmZ/4bM53mKa7a35Yz k4UahsFSJPOchC+AiGS0YwuqP6CqNMTr8R4CjSa6Kzpr9macMArR4DEhX/uTnC2D0kXxn4g 57LjbEUiq1GrlgWMQ3iAlbj6+MbDcfcmh33Wzw3fJQyYK8S34bhzx8z0qPfC6pT2WGpo0v7 CSN1Lmn+D2zFeWn8EYTp/2aRTQi5SmHCZEyQeVg2rJyjy7orlAWI4FuDXShXtpH0Mtd4ALg fAxmxTr2w4V+b4UJ3NjtUdcWY7rQq5xzUiVKzFiRxSWYJrjgZKlSXWP7IiME1DKnqyx9Ntt /ADT8eVZ80NwtoDf8vK7c8rjvg4wJqwqOThEdOgvb58qIz0ofyPMHFiF9qsG1Gowb5AyF8L X-QQ-GoodBg: 2 From: juzhe.zhong@rivai.ai To: gcc-patches@gcc.gnu.org Cc: kito.cheng@gmail.com, Ju-Zhe Zhong Subject: [PATCH] RISC-V: Add integer compare C/C++ intrinsic support Date: Mon, 13 Feb 2023 15:41:13 +0800 Message-Id: <20230213074113.266716-1-juzhe.zhong@rivai.ai> X-Mailer: git-send-email 2.36.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:rivai.ai:qybglogicsvr:qybglogicsvr7 X-Spam-Status: No, score=-12.5 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_ASCII_DIVIDERS,KAM_DMARC_STATUS,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Ju-Zhe Zhong gcc/ChangeLog: * config/riscv/predicates.md (vector_mask_operand): Refine the codes. (vector_all_trues_mask_operand): New predicate. (vector_undef_operand): New predicate. (ltge_operator): New predicate. (comparison_except_ltge_operator): New predicate. (comparison_except_eqge_operator): New predicate. (ge_operator): New predicate. * config/riscv/riscv-v.cc (has_vi_variant_p): Add compare support. * config/riscv/riscv-vector-builtins-bases.cc (class icmp): New class. (BASE): Ditto. * config/riscv/riscv-vector-builtins-bases.h: Ditto. * config/riscv/riscv-vector-builtins-functions.def (vmseq): Ditto. (vmsne): Ditto. (vmslt): Ditto. (vmsgt): Ditto. (vmsle): Ditto. (vmsge): Ditto. (vmsltu): Ditto. (vmsgtu): Ditto. (vmsleu): Ditto. (vmsgeu): Ditto. * config/riscv/riscv-vector-builtins-shapes.cc (struct return_mask_def): Adjust for compare support. * config/riscv/riscv-vector-builtins.cc (function_expander::use_compare_insn): New function. * config/riscv/riscv-vector-builtins.h (function_expander::add_integer_operand): Ditto. * config/riscv/riscv.cc (riscv_print_operand): Add compare support. * config/riscv/riscv.md: Add vector min/max attributes. * config/riscv/vector-iterators.md (xnor): New iterator. * config/riscv/vector.md (@pred_cmp): New pattern. (*pred_cmp): Ditto. (*pred_cmp_narrow): Ditto. (@pred_ltge): Ditto. (*pred_ltge): Ditto. (*pred_ltge_narrow): Ditto. (@pred_cmp_scalar): Ditto. (*pred_cmp_scalar): Ditto. (*pred_cmp_scalar_narrow): Ditto. (@pred_eqne_scalar): Ditto. (*pred_eqne_scalar): Ditto. (*pred_eqne_scalar_narrow): Ditto. (*pred_cmp_extended_scalar): Ditto. (*pred_cmp_extended_scalar_narrow): Ditto. (*pred_eqne_extended_scalar): Ditto. (*pred_eqne_extended_scalar_narrow): Ditto. (@pred_ge_scalar): Ditto. (@pred_): Ditto. (@pred_n): Ditto. (@pred_n): Ditto. (@pred_not): Ditto. --- gcc/config/riscv/predicates.md | 25 +- gcc/config/riscv/riscv-v.cc | 32 +- .../riscv/riscv-vector-builtins-bases.cc | 54 ++ .../riscv/riscv-vector-builtins-bases.h | 10 + .../riscv/riscv-vector-builtins-functions.def | 20 + .../riscv/riscv-vector-builtins-shapes.cc | 2 + gcc/config/riscv/riscv-vector-builtins.cc | 77 ++ gcc/config/riscv/riscv-vector-builtins.h | 9 + gcc/config/riscv/riscv.cc | 7 +- gcc/config/riscv/riscv.md | 10 +- gcc/config/riscv/vector-iterators.md | 20 +- gcc/config/riscv/vector.md | 774 +++++++++++++++++- 12 files changed, 999 insertions(+), 41 deletions(-) diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index fe2c5ba3c5c..bbbf523d588 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -283,14 +283,21 @@ || satisfies_constraint_vi (op) || satisfies_constraint_Wc0 (op)")))) -(define_predicate "vector_mask_operand" +(define_predicate "vector_all_trues_mask_operand" (ior (match_operand 0 "register_operand") (match_test "op == CONSTM1_RTX (GET_MODE (op))"))) +(define_predicate "vector_mask_operand" + (ior (match_operand 0 "register_operand") + (match_operand 0 "vector_all_trues_mask_operand"))) + +(define_predicate "vector_undef_operand" + (match_test "GET_CODE (op) == UNSPEC + && (XINT (op, 1) == UNSPEC_VUNDEF)")) + (define_predicate "vector_merge_operand" (ior (match_operand 0 "register_operand") - (match_test "GET_CODE (op) == UNSPEC - && (XINT (op, 1) == UNSPEC_VUNDEF)"))) + (match_operand 0 "vector_undef_operand"))) (define_predicate "vector_arith_operand" (ior (match_operand 0 "register_operand") @@ -307,6 +314,18 @@ (and (match_code "const_vector") (match_test "riscv_vector::const_vec_all_same_in_range_p (op, 0, 31)")))) +(define_predicate "ltge_operator" + (match_code "lt,ltu,ge,geu")) + +(define_predicate "comparison_except_ltge_operator" + (match_code "eq,ne,le,leu,gt,gtu")) + +(define_predicate "comparison_except_eqge_operator" + (match_code "le,leu,gt,gtu,lt,ltu")) + +(define_predicate "ge_operator" + (match_code "ge,geu")) + ;; pmode_reg_or_uimm5_operand can be used by vsll.vx/vsrl.vx/vsra.vx instructions. ;; Since it has the same predicate with vector_length_operand which allows register ;; or immediate (0 ~ 31), we define this predicate same as vector_length_operand here. diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index 83cb1f83606..cc26888d58b 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -427,11 +427,33 @@ neg_simm5_p (rtx x) bool has_vi_variant_p (rtx_code code, rtx x) { - if (code != PLUS && code != MINUS && code != AND && code != IOR && code != XOR - && code != SS_PLUS && code != SS_MINUS && code != US_PLUS - && code != US_MINUS) - return false; - return simm5_p (x); + switch (code) + { + case PLUS: + case MINUS: + case AND: + case IOR: + case XOR: + case SS_PLUS: + case SS_MINUS: + case US_PLUS: + case US_MINUS: + case EQ: + case NE: + case LE: + case LEU: + case GT: + case GTU: + return simm5_p (x); + + case LT: + case LTU: + case GE: + case GEU: + return neg_simm5_p (x); + default: + return false; + } } } // namespace riscv_vector diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc index 6eb6dab3149..4f3531d4486 100644 --- a/gcc/config/riscv/riscv-vector-builtins-bases.cc +++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc @@ -505,6 +505,40 @@ public: } }; +/* Implements vmseq/vmsne/vmslt/vmsgt/vmsle/vmsge. */ +template +class icmp : public function_base +{ +public: + rtx expand (function_expander &e) const override + { + switch (e.op_info->op) + { + case OP_TYPE_vx: { + if (CODE == GE || CODE == GEU) + return e.use_compare_insn (CODE, code_for_pred_ge_scalar ( + e.vector_mode ())); + else if (CODE == EQ || CODE == NE) + return e.use_compare_insn (CODE, code_for_pred_eqne_scalar ( + e.vector_mode ())); + else + return e.use_compare_insn (CODE, code_for_pred_cmp_scalar ( + e.vector_mode ())); + } + case OP_TYPE_vv: { + if (CODE == LT || CODE == LTU || CODE == GE || CODE == GEU) + return e.use_compare_insn (CODE, + code_for_pred_ltge (e.vector_mode ())); + else + return e.use_compare_insn (CODE, + code_for_pred_cmp (e.vector_mode ())); + } + default: + gcc_unreachable (); + } + } +}; + static CONSTEXPR const vsetvl vsetvl_obj; static CONSTEXPR const vsetvl vsetvlmax_obj; static CONSTEXPR const loadstore vle_obj; @@ -572,6 +606,16 @@ static CONSTEXPR const vnshift vnsra_obj; static CONSTEXPR const vncvt_x vncvt_x_obj; static CONSTEXPR const vmerge vmerge_obj; static CONSTEXPR const vmv_v vmv_v_obj; +static CONSTEXPR const icmp vmseq_obj; +static CONSTEXPR const icmp vmsne_obj; +static CONSTEXPR const icmp vmslt_obj; +static CONSTEXPR const icmp vmsgt_obj; +static CONSTEXPR const icmp vmsle_obj; +static CONSTEXPR const icmp vmsge_obj; +static CONSTEXPR const icmp vmsltu_obj; +static CONSTEXPR const icmp vmsgtu_obj; +static CONSTEXPR const icmp vmsleu_obj; +static CONSTEXPR const icmp vmsgeu_obj; static CONSTEXPR const binop vsadd_obj; static CONSTEXPR const binop vssub_obj; static CONSTEXPR const binop vsaddu_obj; @@ -658,6 +702,16 @@ BASE (vnsra) BASE (vncvt_x) BASE (vmerge) BASE (vmv_v) +BASE (vmseq) +BASE (vmsne) +BASE (vmslt) +BASE (vmsgt) +BASE (vmsle) +BASE (vmsge) +BASE (vmsltu) +BASE (vmsgtu) +BASE (vmsleu) +BASE (vmsgeu) BASE (vsadd) BASE (vssub) BASE (vsaddu) diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.h b/gcc/config/riscv/riscv-vector-builtins-bases.h index dcc706ea805..6233b4122f8 100644 --- a/gcc/config/riscv/riscv-vector-builtins-bases.h +++ b/gcc/config/riscv/riscv-vector-builtins-bases.h @@ -91,6 +91,16 @@ extern const function_base *const vnsra; extern const function_base *const vncvt_x; extern const function_base *const vmerge; extern const function_base *const vmv_v; +extern const function_base *const vmseq; +extern const function_base *const vmsne; +extern const function_base *const vmslt; +extern const function_base *const vmsgt; +extern const function_base *const vmsle; +extern const function_base *const vmsge; +extern const function_base *const vmsltu; +extern const function_base *const vmsgtu; +extern const function_base *const vmsleu; +extern const function_base *const vmsgeu; extern const function_base *const vsadd; extern const function_base *const vssub; extern const function_base *const vsaddu; diff --git a/gcc/config/riscv/riscv-vector-builtins-functions.def b/gcc/config/riscv/riscv-vector-builtins-functions.def index 66fa63530f3..f61f48d36a0 100644 --- a/gcc/config/riscv/riscv-vector-builtins-functions.def +++ b/gcc/config/riscv/riscv-vector-builtins-functions.def @@ -157,6 +157,26 @@ DEF_RVV_FUNCTION (vmerge, no_mask_policy, tu_preds, all_vvvm_ops) DEF_RVV_FUNCTION (vmerge, no_mask_policy, tu_preds, iu_vvxm_ops) DEF_RVV_FUNCTION (vmv_v, move, tu_preds, all_v_ops) DEF_RVV_FUNCTION (vmv_v, move, tu_preds, iu_x_ops) +DEF_RVV_FUNCTION (vmseq, return_mask, none_m_mu_preds, iu_mvv_ops) +DEF_RVV_FUNCTION (vmsne, return_mask, none_m_mu_preds, iu_mvv_ops) +DEF_RVV_FUNCTION (vmslt, return_mask, none_m_mu_preds, i_mvv_ops) +DEF_RVV_FUNCTION (vmsgt, return_mask, none_m_mu_preds, i_mvv_ops) +DEF_RVV_FUNCTION (vmsle, return_mask, none_m_mu_preds, i_mvv_ops) +DEF_RVV_FUNCTION (vmsge, return_mask, none_m_mu_preds, i_mvv_ops) +DEF_RVV_FUNCTION (vmsltu, return_mask, none_m_mu_preds, u_mvv_ops) +DEF_RVV_FUNCTION (vmsgtu, return_mask, none_m_mu_preds, u_mvv_ops) +DEF_RVV_FUNCTION (vmsleu, return_mask, none_m_mu_preds, u_mvv_ops) +DEF_RVV_FUNCTION (vmsgeu, return_mask, none_m_mu_preds, u_mvv_ops) +DEF_RVV_FUNCTION (vmseq, return_mask, none_m_mu_preds, iu_mvx_ops) +DEF_RVV_FUNCTION (vmsne, return_mask, none_m_mu_preds, iu_mvx_ops) +DEF_RVV_FUNCTION (vmslt, return_mask, none_m_mu_preds, i_mvx_ops) +DEF_RVV_FUNCTION (vmsgt, return_mask, none_m_mu_preds, i_mvx_ops) +DEF_RVV_FUNCTION (vmsle, return_mask, none_m_mu_preds, i_mvx_ops) +DEF_RVV_FUNCTION (vmsge, return_mask, none_m_mu_preds, i_mvx_ops) +DEF_RVV_FUNCTION (vmsltu, return_mask, none_m_mu_preds, u_mvx_ops) +DEF_RVV_FUNCTION (vmsgtu, return_mask, none_m_mu_preds, u_mvx_ops) +DEF_RVV_FUNCTION (vmsleu, return_mask, none_m_mu_preds, u_mvx_ops) +DEF_RVV_FUNCTION (vmsgeu, return_mask, none_m_mu_preds, u_mvx_ops) /* 12. Vector Fixed-Point Arithmetic Instructions. */ DEF_RVV_FUNCTION (vsadd, alu, full_preds, i_vvv_ops) DEF_RVV_FUNCTION (vssub, alu, full_preds, i_vvv_ops) diff --git a/gcc/config/riscv/riscv-vector-builtins-shapes.cc b/gcc/config/riscv/riscv-vector-builtins-shapes.cc index e1d8f4f13f0..2836170323a 100644 --- a/gcc/config/riscv/riscv-vector-builtins-shapes.cc +++ b/gcc/config/riscv/riscv-vector-builtins-shapes.cc @@ -288,6 +288,8 @@ struct return_mask_def : public build_base b.append_name (type_suffixes[ret_type_idx].vector); } + if (overloaded_p && instance.pred == PRED_TYPE_m) + return b.finish_name (); b.append_name (predication_suffixes[instance.pred]); return b.finish_name (); } diff --git a/gcc/config/riscv/riscv-vector-builtins.cc b/gcc/config/riscv/riscv-vector-builtins.cc index 486b8b722b5..3d842c6e3a3 100644 --- a/gcc/config/riscv/riscv-vector-builtins.cc +++ b/gcc/config/riscv/riscv-vector-builtins.cc @@ -438,6 +438,10 @@ static CONSTEXPR const predication_type_index tu_preds[] static CONSTEXPR const predication_type_index none_m_preds[] = {PRED_TYPE_none, PRED_TYPE_m, NUM_PRED_TYPES}; +/* vop/vop_m/vop_mu will be registered. */ +static CONSTEXPR const predication_type_index none_m_mu_preds[] + = {PRED_TYPE_none, PRED_TYPE_m, PRED_TYPE_mu, NUM_PRED_TYPES}; + /* A static operand information for size_t func (void) function registration. */ static CONSTEXPR const rvv_op_info i_none_size_void_ops = {i_ops, /* Types */ @@ -621,6 +625,22 @@ static CONSTEXPR const rvv_op_info iu_mvv_ops rvv_arg_type_info (RVV_BASE_mask), /* Return type */ vv_args /* Args */}; +/* A static operand information for mask_type func (vector_type, vector_type) + * function registration. */ +static CONSTEXPR const rvv_op_info i_mvv_ops + = {i_ops, /* Types */ + OP_TYPE_vv, /* Suffix */ + rvv_arg_type_info (RVV_BASE_mask), /* Return type */ + vv_args /* Args */}; + +/* A static operand information for mask_type func (vector_type, vector_type) + * function registration. */ +static CONSTEXPR const rvv_op_info u_mvv_ops + = {u_ops, /* Types */ + OP_TYPE_vv, /* Suffix */ + rvv_arg_type_info (RVV_BASE_mask), /* Return type */ + vv_args /* Args */}; + /* A static operand information for mask_type func (vector_type, scalar_type) * function registration. */ static CONSTEXPR const rvv_op_info iu_mvx_ops @@ -629,6 +649,22 @@ static CONSTEXPR const rvv_op_info iu_mvx_ops rvv_arg_type_info (RVV_BASE_mask), /* Return type */ vx_args /* Args */}; +/* A static operand information for mask_type func (vector_type, scalar_type) + * function registration. */ +static CONSTEXPR const rvv_op_info i_mvx_ops + = {i_ops, /* Types */ + OP_TYPE_vx, /* Suffix */ + rvv_arg_type_info (RVV_BASE_mask), /* Return type */ + vx_args /* Args */}; + +/* A static operand information for mask_type func (vector_type, scalar_type) + * function registration. */ +static CONSTEXPR const rvv_op_info u_mvx_ops + = {u_ops, /* Types */ + OP_TYPE_vx, /* Suffix */ + rvv_arg_type_info (RVV_BASE_mask), /* Return type */ + vx_args /* Args */}; + /* A static operand information for vector_type func (vector_type, vector_type) * function registration. */ static CONSTEXPR const rvv_op_info i_vvv_ops @@ -1902,6 +1938,47 @@ function_expander::use_contiguous_store_insn (insn_code icode) return generate_insn (icode); } +/* Implement the call using instruction ICODE, with a 1:1 mapping between + arguments and input operands. */ +rtx +function_expander::use_compare_insn (rtx_code rcode, insn_code icode) +{ + machine_mode mode = TYPE_MODE (builtin_types[type.index].vector); + machine_mode mask_mode = TYPE_MODE (TREE_TYPE (exp)); + + /* Record the offset to get the argument. */ + int arg_offset = 0; + + if (use_real_mask_p (pred)) + add_input_operand (arg_offset++); + else + add_all_one_mask_operand (mask_mode); + + if (use_real_merge_p (pred)) + add_input_operand (arg_offset++); + else + add_vundef_operand (mask_mode); + + rtx op1 = expand_normal (CALL_EXPR_ARG (exp, arg_offset++)); + rtx op2 = expand_normal (CALL_EXPR_ARG (exp, arg_offset++)); + rtx comparison = gen_rtx_fmt_ee (rcode, mask_mode, op1, op2); + if (!VECTOR_MODE_P (GET_MODE (op2))) + comparison = gen_rtx_fmt_ee (rcode, mask_mode, op1, + gen_rtx_VEC_DUPLICATE (mode, op2)); + add_fixed_operand (comparison); + add_fixed_operand (op1); + if (CONST_INT_P (op2)) + add_integer_operand (op2); + else + add_fixed_operand (op2); + for (int argno = arg_offset; argno < call_expr_nargs (exp); argno++) + add_input_operand (argno); + + add_input_operand (Pmode, get_mask_policy_for_pred (pred)); + add_input_operand (Pmode, get_avl_type_rtx (avl_type::NONVLMAX)); + return generate_insn (icode); +} + /* Generate instruction ICODE, given that its operands have already been added to M_OPS. Return the value of the first operand. */ rtx diff --git a/gcc/config/riscv/riscv-vector-builtins.h b/gcc/config/riscv/riscv-vector-builtins.h index f00b2c51020..9807fdf2938 100644 --- a/gcc/config/riscv/riscv-vector-builtins.h +++ b/gcc/config/riscv/riscv-vector-builtins.h @@ -338,6 +338,7 @@ public: void add_all_one_mask_operand (machine_mode); void add_vundef_operand (machine_mode); void add_fixed_operand (rtx); + void add_integer_operand (rtx); void add_mem_operand (machine_mode, unsigned); machine_mode vector_mode (void) const; @@ -346,6 +347,7 @@ public: rtx use_exact_insn (insn_code); rtx use_contiguous_load_insn (insn_code); rtx use_contiguous_store_insn (insn_code); + rtx use_compare_insn (rtx_code, insn_code); rtx generate_insn (insn_code); /* The function call expression. */ @@ -467,6 +469,13 @@ function_expander::add_fixed_operand (rtx x) create_fixed_operand (&m_ops[opno++], x); } +/* Add an integer operand X. */ +inline void +function_expander::add_integer_operand (rtx x) +{ + create_integer_operand (&m_ops[opno++], INTVAL (x)); +} + /* Return the machine_mode of the corresponding vector type. */ inline machine_mode function_expander::vector_mode (void) const diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 88a73297ffa..8078dd4727f 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -4263,7 +4263,8 @@ riscv_print_operand (FILE *file, rtx op, int letter) output_operand_lossage ("invalid vector constant"); else if (satisfies_constraint_Wc0 (op)) asm_fprintf (file, "0"); - else if (satisfies_constraint_vi (op)) + else if (satisfies_constraint_vi (op) + || satisfies_constraint_vj (op)) asm_fprintf (file, "%wd", INTVAL (elt)); else output_operand_lossage ("invalid vector constant"); @@ -4376,6 +4377,10 @@ riscv_print_operand (FILE *file, rtx op, int letter) fputs ("i", file); break; + case 'B': + fputs (GET_RTX_NAME (code), file); + break; + case 'S': { rtx newop = GEN_INT (ctz_hwi (INTVAL (op))); diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index c8adc5af5d2..487059ebe97 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -267,7 +267,8 @@ ;; vicalu vector arithmetic with carry or borrow instructions ;; vshift vector single-width bit shift instructions ;; vnshift vector narrowing integer shift instructions -;; vicmp vector integer comparison/min/max instructions +;; viminmax vector integer min/max instructions +;; vicmp vector integer comparison instructions ;; vimul vector single-width integer multiply instructions ;; vidiv vector single-width integer divide instructions ;; viwmul vector widening integer multiply instructions @@ -291,7 +292,8 @@ ;; vfwmuladd vector widening floating-point multiply-add instructions ;; vfsqrt vector floating-point square-root instructions ;; vfrecp vector floating-point reciprocal square-root instructions -;; vfcmp vector floating-point comparison/min/max instructions +;; vfminmax vector floating-point min/max instructions +;; vfcmp vector floating-point comparison instructions ;; vfsgnj vector floating-point sign-injection instructions ;; vfclass vector floating-point classify instruction ;; vfmerge vector floating-point merge instruction @@ -335,11 +337,11 @@ fmadd,fdiv,fcmp,fcvt,fsqrt,multi,auipc,sfb_alu,nop,ghost,bitmanip,rotate, atomic,rdvlenb,rdvl,vsetvl,vlde,vste,vldm,vstm,vlds,vsts, vldux,vldox,vstux,vstox,vldff,vldr,vstr, - vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp, + vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax, vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge,vimov, vsalu,vaalu,vsmul,vsshift,vnclip, vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp, - vfcmp,vfsgnj,vfclass,vfmerge,vfmov, + vfcmp,vfminmax,vfsgnj,vfclass,vfmerge,vfmov, vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi, vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof, vired,viwred,vfred,vfredo,vfwred,vfwredo, diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md index 9087129c70a..c8b24150f4e 100644 --- a/gcc/config/riscv/vector-iterators.md +++ b/gcc/config/riscv/vector-iterators.md @@ -225,6 +225,15 @@ (VNx1DF "VNx1BI") (VNx2DF "VNx2BI") (VNx4DF "VNx4BI") (VNx8DF "VNx8BI") ]) +(define_mode_attr vm [ + (VNx1QI "vnx1bi") (VNx2QI "vnx2bi") (VNx4QI "vnx4bi") (VNx8QI "vnx8bi") (VNx16QI "vnx16bi") (VNx32QI "vnx32bi") (VNx64QI "vnx64bi") + (VNx1HI "vnx1bi") (VNx2HI "vnx2bi") (VNx4HI "vnx4bi") (VNx8HI "vnx8bi") (VNx16HI "vnx16bi") (VNx32HI "vnx32bi") + (VNx1SI "vnx1bi") (VNx2SI "vnx2bi") (VNx4SI "vnx4bi") (VNx8SI "vnx8bi") (VNx16SI "vnx16bi") + (VNx1DI "vnx1bi") (VNx2DI "vnx2bi") (VNx4DI "vnx4bi") (VNx8DI "vnx8bi") + (VNx1SF "vnx1bi") (VNx2SF "vnx2bi") (VNx4SF "vnx4bi") (VNx8SF "vnx8bi") (VNx16SF "vnx16bi") + (VNx1DF "vnx1bi") (VNx2DF "vnx2bi") (VNx4DF "vnx4bi") (VNx8DF "vnx8bi") +]) + (define_mode_attr VEL [ (VNx1QI "QI") (VNx2QI "QI") (VNx4QI "QI") (VNx8QI "QI") (VNx16QI "QI") (VNx32QI "QI") (VNx64QI "QI") (VNx1HI "HI") (VNx2HI "HI") (VNx4HI "HI") (VNx8HI "HI") (VNx16HI "HI") (VNx32HI "HI") @@ -322,6 +331,9 @@ (define_code_attr macc_nmsac [(plus "macc") (minus "nmsac")]) (define_code_attr madd_nmsub [(plus "madd") (minus "nmsub")]) +(define_code_iterator and_ior [and ior]) +(define_code_attr ninsn [(and "nand") (ior "nor") (xor "xnor")]) + (define_code_attr binop_rhs1_predicate [ (plus "register_operand") (minus "vector_arith_operand") @@ -419,10 +431,10 @@ (ashift "vshift") (ashiftrt "vshift") (lshiftrt "vshift") - (smin "vicmp") - (smax "vicmp") - (umin "vicmp") - (umax "vicmp") + (smin "viminmax") + (smax "viminmax") + (umin "viminmax") + (umax "viminmax") (mult "vimul") (div "vidiv") (mod "vidiv") diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md index 68472797a9c..239ffc851e3 100644 --- a/gcc/config/riscv/vector.md +++ b/gcc/config/riscv/vector.md @@ -41,11 +41,11 @@ (define_attr "has_vtype_op" "false,true" (cond [(eq_attr "type" "vlde,vste,vldm,vstm,vlds,vsts,\ vldux,vldox,vstux,vstox,vldff,\ - vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,\ + vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,\ vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge,vimov,\ vsalu,vaalu,vsmul,vsshift,vnclip,\ vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp,\ - vfcmp,vfsgnj,vfclass,vfmerge,vfmov,\ + vfcmp,vfminmax,vfsgnj,vfclass,vfmerge,vfmov,\ vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi,\ vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof,\ vired,viwred,vfred,vfredo,vfwred,vfwredo,\ @@ -61,11 +61,11 @@ (define_attr "has_vl_op" "false,true" (cond [(eq_attr "type" "vlde,vste,vldm,vstm,vlds,vsts,\ vldux,vldox,vstux,vstox,vldff,\ - vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,\ + vialu,viwalu,vext,vicalu,vshift,vnshift,vicmp,viminmax,\ vimul,vidiv,viwmul,vimuladd,viwmuladd,vimerge,vimov,\ vsalu,vaalu,vsmul,vsshift,vnclip,\ vfalu,vfwalu,vfmul,vfdiv,vfwmul,vfmuladd,vfwmuladd,vfsqrt,vfrecp,\ - vfcmp,vfsgnj,vfclass,vfmerge,vfmov,\ + vfcmp,vfminmax,vfsgnj,vfclass,vfmerge,vfmov,\ vfcvtitof,vfcvtftoi,vfwcvtitof,vfwcvtftoi,\ vfwcvtftof,vfncvtitof,vfncvtftoi,vfncvtftof,\ vired,viwred,vfred,vfredo,vfwred,vfwredo,\ @@ -146,7 +146,7 @@ vialu,vshift,vicmp,vimul,vidiv,vsalu,\ vext,viwalu,viwmul,vicalu,vnshift,\ vimuladd,vimerge,vaalu,vsmul,vsshift,\ - vnclip") + vnclip,viminmax") (const_int INVALID_ATTRIBUTE) (eq_attr "mode" "VNx1QI,VNx1BI") (symbol_ref "riscv_vector::get_ratio(E_VNx1QImode)") @@ -196,8 +196,8 @@ ;; The index of operand[] to get the merge op. (define_attr "merge_op_idx" "" - (cond [(eq_attr "type" "vlde,vimov,vfmov,vldm,vlds,vmalu,vldux,vldox,\ - vialu,vshift,vicmp,vimul,vidiv,vsalu,vext,viwalu,\ + (cond [(eq_attr "type" "vlde,vimov,vfmov,vldm,vlds,vmalu,vldux,vldox,vicmp,\ + vialu,vshift,viminmax,vimul,vidiv,vsalu,vext,viwalu,\ viwmul,vnshift,vimuladd,vaalu,vsmul,vsshift,vnclip") (const_int 2) @@ -218,10 +218,13 @@ (const_int 5) (const_int 4)) - (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu,\ + (eq_attr "type" "vldux,vldox,vialu,vshift,viminmax,vimul,vidiv,vsalu,\ viwalu,viwmul,vnshift,vimuladd,vimerge,vaalu,vsmul,\ vsshift,vnclip") - (const_int 5)] + (const_int 5) + + (eq_attr "type" "vicmp") + (const_int 6)] (const_int INVALID_ATTRIBUTE))) ;; The tail policy op value. @@ -236,7 +239,7 @@ (symbol_ref "riscv_vector::get_ta(operands[6])") (symbol_ref "riscv_vector::get_ta(operands[5])")) - (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu,\ + (eq_attr "type" "vldux,vldox,vialu,vshift,viminmax,vimul,vidiv,vsalu,\ viwalu,viwmul,vnshift,vimuladd,vimerge,vaalu,vsmul,\ vsshift,vnclip") (symbol_ref "riscv_vector::get_ta(operands[6])")] @@ -254,9 +257,9 @@ (symbol_ref "riscv_vector::get_ma(operands[7])") (symbol_ref "riscv_vector::get_ma(operands[6])")) - (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu,\ + (eq_attr "type" "vldux,vldox,vialu,vshift,viminmax,vimul,vidiv,vsalu,\ viwalu,viwmul,vnshift,vimuladd,vaalu,vsmul,vsshift,\ - vnclip") + vnclip,vicmp") (symbol_ref "riscv_vector::get_ma(operands[7])")] (const_int INVALID_ATTRIBUTE))) @@ -274,9 +277,9 @@ (const_int INVALID_ATTRIBUTE) (symbol_ref "INTVAL (operands[7])")) - (eq_attr "type" "vldux,vldox,vialu,vshift,vicmp,vimul,vidiv,vsalu,\ + (eq_attr "type" "vldux,vldox,vialu,vshift,viminmax,vimul,vidiv,vsalu,\ viwalu,viwmul,vnshift,vimuladd,vaalu,vsmul,vsshift,\ - vnclip") + vnclip,vicmp") (symbol_ref "INTVAL (operands[8])") (eq_attr "type" "vstux,vstox") (symbol_ref "INTVAL (operands[5])")] @@ -763,16 +766,16 @@ ;; constraint alternative 3 match vmclr.m. ;; constraint alternative 4 match vmset.m. (define_insn_and_split "@pred_mov" - [(set (match_operand:VB 0 "nonimmediate_operand" "=vr, m, vr, vr, vr") + [(set (match_operand:VB 0 "nonimmediate_operand" "=vr, m, vr, vr, vr") (if_then_else:VB (unspec:VB - [(match_operand:VB 1 "vector_mask_operand" "Wc1, Wc1, Wc1, Wc1, Wc1") - (match_operand 4 "vector_length_operand" " rK, rK, rK, rK, rK") - (match_operand 5 "const_int_operand" " i, i, i, i, i") + [(match_operand:VB 1 "vector_all_trues_mask_operand" "Wc1, Wc1, Wc1, Wc1, Wc1") + (match_operand 4 "vector_length_operand" " rK, rK, rK, rK, rK") + (match_operand 5 "const_int_operand" " i, i, i, i, i") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) - (match_operand:VB 3 "vector_move_operand" " m, vr, vr, Wc0, Wc1") - (match_operand:VB 2 "vector_merge_operand" " vu, vu, vu, vu, vu")))] + (match_operand:VB 3 "vector_move_operand" " m, vr, vr, Wc0, Wc1") + (match_operand:VB 2 "vector_undef_operand" " vu, vu, vu, vu, vu")))] "TARGET_VECTOR" "@ vlm.v\t%0,%3 @@ -790,14 +793,14 @@ ;; Dedicated pattern for vsm.v instruction since we can't reuse pred_mov pattern to include ;; memory operand as input which will produce inferior codegen. (define_insn "@pred_store" - [(set (match_operand:VB 0 "memory_operand" "+m") + [(set (match_operand:VB 0 "memory_operand" "+m") (if_then_else:VB (unspec:VB - [(match_operand:VB 1 "vector_mask_operand" "Wc1") - (match_operand 3 "vector_length_operand" " rK") + [(match_operand:VB 1 "vector_all_trues_mask_operand" "Wc1") + (match_operand 3 "vector_length_operand" " rK") (reg:SI VL_REGNUM) (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) - (match_operand:VB 2 "register_operand" " vr") + (match_operand:VB 2 "register_operand" " vr") (match_dup 0)))] "TARGET_VECTOR" "vsm.v\t%2,%0" @@ -3399,3 +3402,726 @@ "vnclip.w%o4\t%0,%3,%4%p1" [(set_attr "type" "vnclip") (set_attr "mode" "")]) + +;; ------------------------------------------------------------------------------- +;; ---- Predicated comparison operations +;; ------------------------------------------------------------------------------- +;; Includes: +;; - 11.8 Vector Integer Comparision Instructions +;; ------------------------------------------------------------------------------- + +(define_expand "@pred_cmp" + [(set (match_operand: 0 "register_operand") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand") + (match_operand 6 "vector_length_operand") + (match_operand 7 "const_int_operand") + (match_operand 8 "const_int_operand") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_ltge_operator" + [(match_operand:VI 4 "register_operand") + (match_operand:VI 5 "vector_arith_operand")]) + (match_operand: 2 "vector_merge_operand")))] + "TARGET_VECTOR" + {}) + +;; We don't use early-clobber for LMUL <= 1 to get better codegen. +(define_insn "*pred_cmp" + [(set (match_operand: 0 "register_operand" "=vr, vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1,vmWc1") + (match_operand 6 "vector_length_operand" " rK, rK") + (match_operand 7 "const_int_operand" " i, i") + (match_operand 8 "const_int_operand" " i, i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_ltge_operator" + [(match_operand:VI 4 "register_operand" " vr, vr") + (match_operand:VI 5 "vector_arith_operand" " vr, vi")]) + (match_operand: 2 "vector_merge_operand" " 0vu, 0vu")))] + "TARGET_VECTOR && known_le (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.v%o5\t%0,%4,%v5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; We use early-clobber for source LMUL > dest LMUL. +(define_insn "*pred_cmp_narrow" + [(set (match_operand: 0 "register_operand" "=&vr, &vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1,vmWc1") + (match_operand 6 "vector_length_operand" " rK, rK") + (match_operand 7 "const_int_operand" " i, i") + (match_operand 8 "const_int_operand" " i, i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_ltge_operator" + [(match_operand:VI 4 "register_operand" " vr, vr") + (match_operand:VI 5 "vector_arith_operand" " vr, vi")]) + (match_operand: 2 "vector_merge_operand" " 0vu, 0vu")))] + "TARGET_VECTOR && known_gt (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.v%o5\t%0,%4,%v5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +(define_expand "@pred_ltge" + [(set (match_operand: 0 "register_operand") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand") + (match_operand 6 "vector_length_operand") + (match_operand 7 "const_int_operand") + (match_operand 8 "const_int_operand") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "ltge_operator" + [(match_operand:VI 4 "register_operand") + (match_operand:VI 5 "vector_neg_arith_operand")]) + (match_operand: 2 "vector_merge_operand")))] + "TARGET_VECTOR" + {}) + +;; We don't use early-clobber for LMUL <= 1 to get better codegen. +(define_insn "*pred_ltge" + [(set (match_operand: 0 "register_operand" "=vr, vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1,vmWc1") + (match_operand 6 "vector_length_operand" " rK, rK") + (match_operand 7 "const_int_operand" " i, i") + (match_operand 8 "const_int_operand" " i, i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "ltge_operator" + [(match_operand:VI 4 "register_operand" " vr, vr") + (match_operand:VI 5 "vector_neg_arith_operand" " vr, vj")]) + (match_operand: 2 "vector_merge_operand" " 0vu, 0vu")))] + "TARGET_VECTOR && known_le (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.v%o5\t%0,%4,%v5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; We use early-clobber for source LMUL > dest LMUL. +(define_insn "*pred_ltge_narrow" + [(set (match_operand: 0 "register_operand" "=&vr, &vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1,vmWc1") + (match_operand 6 "vector_length_operand" " rK, rK") + (match_operand 7 "const_int_operand" " i, i") + (match_operand 8 "const_int_operand" " i, i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "ltge_operator" + [(match_operand:VI 4 "register_operand" " vr, vr") + (match_operand:VI 5 "vector_neg_arith_operand" " vr, vj")]) + (match_operand: 2 "vector_merge_operand" " 0vu, 0vu")))] + "TARGET_VECTOR && known_gt (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.v%o5\t%0,%4,%v5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +(define_expand "@pred_cmp_scalar" + [(set (match_operand: 0 "register_operand") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand") + (match_operand 6 "vector_length_operand") + (match_operand 7 "const_int_operand") + (match_operand 8 "const_int_operand") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_eqge_operator" + [(match_operand:VI_QHS 4 "register_operand") + (vec_duplicate:VI_QHS + (match_operand: 5 "register_operand"))]) + (match_operand: 2 "vector_merge_operand")))] + "TARGET_VECTOR" + {}) + +;; We don't use early-clobber for LMUL <= 1 to get better codegen. +(define_insn "*pred_cmp_scalar" + [(set (match_operand: 0 "register_operand" "=vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_eqge_operator" + [(match_operand:VI_QHS 4 "register_operand" " vr") + (vec_duplicate:VI_QHS + (match_operand: 5 "register_operand" " r"))]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_le (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; We use early-clobber for source LMUL > dest LMUL. +(define_insn "*pred_cmp_scalar_narrow" + [(set (match_operand: 0 "register_operand" "=&vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_eqge_operator" + [(match_operand:VI_QHS 4 "register_operand" " vr") + (vec_duplicate:VI_QHS + (match_operand: 5 "register_operand" " r"))]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_gt (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +(define_expand "@pred_eqne_scalar" + [(set (match_operand: 0 "register_operand") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand") + (match_operand 6 "vector_length_operand") + (match_operand 7 "const_int_operand") + (match_operand 8 "const_int_operand") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "equality_operator" + [(vec_duplicate:VI_QHS + (match_operand: 5 "register_operand")) + (match_operand:VI_QHS 4 "register_operand")]) + (match_operand: 2 "vector_merge_operand")))] + "TARGET_VECTOR" + {}) + +;; We don't use early-clobber for LMUL <= 1 to get better codegen. +(define_insn "*pred_eqne_scalar" + [(set (match_operand: 0 "register_operand" "=vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "equality_operator" + [(vec_duplicate:VI_QHS + (match_operand: 5 "register_operand" " r")) + (match_operand:VI_QHS 4 "register_operand" " vr")]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_le (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; We use early-clobber for source LMUL > dest LMUL. +(define_insn "*pred_eqne_scalar_narrow" + [(set (match_operand: 0 "register_operand" "=&vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "equality_operator" + [(vec_duplicate:VI_QHS + (match_operand: 5 "register_operand" " r")) + (match_operand:VI_QHS 4 "register_operand" " vr")]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_gt (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; Handle GET_MODE_INNER (mode) = DImode. We need to split them since +;; we need to deal with SEW = 64 in RV32 system. +(define_expand "@pred_cmp_scalar" + [(set (match_operand: 0 "register_operand") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand") + (match_operand 6 "vector_length_operand") + (match_operand 7 "const_int_operand") + (match_operand 8 "const_int_operand") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_eqge_operator" + [(match_operand:VI_D 4 "register_operand") + (vec_duplicate:VI_D + (match_operand: 5 "reg_or_int_operand"))]) + (match_operand: 2 "vector_merge_operand")))] + "TARGET_VECTOR" + { + enum rtx_code code = GET_CODE (operands[3]); + + if (riscv_vector::has_vi_variant_p (code, operands[5])) + operands[5] = force_reg (mode, operands[5]); + else if (!TARGET_64BIT) + { + rtx v = gen_reg_rtx (mode); + + if (riscv_vector::simm32_p (operands[5])) + { + if (!rtx_equal_p (operands[5], const0_rtx)) + operands[5] = force_reg (Pmode, operands[5]); + operands[5] = gen_rtx_SIGN_EXTEND (mode, operands[5]); + } + else + { + if (CONST_INT_P (operands[5])) + operands[5] = force_reg (mode, operands[5]); + + riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (mode), + v, operands[5], operands[6], mode); + if (code == LT || code == LTU) + emit_insn (gen_pred_ltge (operands[0], operands[1], + operands[2], operands[3], operands[4], v, + operands[6], operands[7], operands[8])); + else + emit_insn (gen_pred_cmp (operands[0], operands[1], + operands[2], operands[3], operands[4], v, + operands[6], operands[7], operands[8])); + DONE; + } + } + else + operands[5] = force_reg (mode, operands[5]); + }) + +(define_expand "@pred_eqne_scalar" + [(set (match_operand: 0 "register_operand") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand") + (match_operand 6 "vector_length_operand") + (match_operand 7 "const_int_operand") + (match_operand 8 "const_int_operand") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "equality_operator" + [(vec_duplicate:VI_D + (match_operand: 5 "reg_or_int_operand")) + (match_operand:VI_D 4 "register_operand")]) + (match_operand: 2 "vector_merge_operand")))] + "TARGET_VECTOR" + { + enum rtx_code code = GET_CODE (operands[3]); + + if (riscv_vector::has_vi_variant_p (code, operands[5])) + operands[5] = force_reg (mode, operands[5]); + else if (!TARGET_64BIT) + { + rtx v = gen_reg_rtx (mode); + + if (riscv_vector::simm32_p (operands[5])) + { + if (!rtx_equal_p (operands[5], const0_rtx)) + operands[5] = force_reg (Pmode, operands[5]); + operands[5] = gen_rtx_SIGN_EXTEND (mode, operands[5]); + } + else + { + if (CONST_INT_P (operands[5])) + operands[5] = force_reg (mode, operands[5]); + + riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (mode), + v, operands[5], operands[6], mode); + emit_insn (gen_pred_cmp (operands[0], operands[1], + operands[2], operands[3], operands[4], v, + operands[6], operands[7], operands[8])); + DONE; + } + } + else + operands[5] = force_reg (mode, operands[5]); + }) + +;; We don't use early-clobber for LMUL <= 1 to get better codegen. +(define_insn "*pred_cmp_scalar" + [(set (match_operand: 0 "register_operand" "=vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_eqge_operator" + [(match_operand:VI_D 4 "register_operand" " vr") + (vec_duplicate:VI_D + (match_operand: 5 "register_operand" " r"))]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_le (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; We use early-clobber for source LMUL > dest LMUL. +(define_insn "*pred_cmp_scalar_narrow" + [(set (match_operand: 0 "register_operand" "=&vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_eqge_operator" + [(match_operand:VI_D 4 "register_operand" " vr") + (vec_duplicate:VI_D + (match_operand: 5 "register_operand" " r"))]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_gt (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; We don't use early-clobber for LMUL <= 1 to get better codegen. +(define_insn "*pred_eqne_scalar" + [(set (match_operand: 0 "register_operand" "=vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "equality_operator" + [(vec_duplicate:VI_D + (match_operand: 5 "register_operand" " r")) + (match_operand:VI_D 4 "register_operand" " vr")]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_le (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; We use early-clobber for source LMUL > dest LMUL. +(define_insn "*pred_eqne_scalar_narrow" + [(set (match_operand: 0 "register_operand" "=&vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "equality_operator" + [(vec_duplicate:VI_D + (match_operand: 5 "register_operand" " r")) + (match_operand:VI_D 4 "register_operand" " vr")]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_gt (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; We don't use early-clobber for LMUL <= 1 to get better codegen. +(define_insn "*pred_cmp_extended_scalar" + [(set (match_operand: 0 "register_operand" "=vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_eqge_operator" + [(match_operand:VI_D 4 "register_operand" " vr") + (vec_duplicate:VI_D + (sign_extend: + (match_operand: 5 "register_operand" " r")))]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_le (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +(define_insn "*pred_cmp_extended_scalar_narrow" + [(set (match_operand: 0 "register_operand" "=&vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "comparison_except_eqge_operator" + [(match_operand:VI_D 4 "register_operand" " vr") + (vec_duplicate:VI_D + (sign_extend: + (match_operand: 5 "register_operand" " r")))]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_gt (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; We don't use early-clobber for LMUL <= 1 to get better codegen. +(define_insn "*pred_eqne_extended_scalar" + [(set (match_operand: 0 "register_operand" "=vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "equality_operator" + [(vec_duplicate:VI_D + (sign_extend: + (match_operand: 5 "register_operand" " r"))) + (match_operand:VI_D 4 "register_operand" " vr")]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_le (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +(define_insn "*pred_eqne_extended_scalar_narrow" + [(set (match_operand: 0 "register_operand" "=&vr") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand" "vmWc1") + (match_operand 6 "vector_length_operand" " rK") + (match_operand 7 "const_int_operand" " i") + (match_operand 8 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "equality_operator" + [(vec_duplicate:VI_D + (sign_extend: + (match_operand: 5 "register_operand" " r"))) + (match_operand:VI_D 4 "register_operand" " vr")]) + (match_operand: 2 "vector_merge_operand" " 0vu")))] + "TARGET_VECTOR && known_gt (GET_MODE_SIZE (mode), BYTES_PER_RISCV_VECTOR)" + "vms%B3.vx\t%0,%4,%5%p1" + [(set_attr "type" "vicmp") + (set_attr "mode" "")]) + +;; GE, vmsge.vx/vmsgeu.vx +;; +;; unmasked va >= x +;; - pseudoinstruction: vmsge{u}.vx vd, va, x +;; - expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd +;; +;; masked va >= x, vd != v0 +;; - pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t +;; - expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0 +;; +;; masked va >= x, vd == v0 +;; - pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt +;; - expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt +(define_expand "@pred_ge_scalar" + [(set (match_operand: 0 "register_operand") + (if_then_else: + (unspec: + [(match_operand: 1 "vector_mask_operand") + (match_operand 6 "vector_length_operand") + (match_operand 7 "const_int_operand") + (match_operand 8 "const_int_operand") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (match_operator: 3 "ge_operator" + [(match_operand:VI 4 "register_operand") + (vec_duplicate:VI + (match_operand: 5 "reg_or_int_operand"))]) + (match_operand: 2 "vector_merge_operand")))] + "TARGET_VECTOR" +{ + enum rtx_code code = GET_CODE (operands[3]); + rtx undef = gen_rtx_UNSPEC (mode, gen_rtvec (1, const0_rtx), UNSPEC_VUNDEF); + if (code == GEU && rtx_equal_p (operands[5], const0_rtx)) + { + /* If vmsgeu with 0 immediate, expand it to vmset. */ + if (satisfies_constraint_Wc1 (operands[1])) + emit_insn ( + gen_pred_mov (mode, operands[0], CONSTM1_RTX (mode), undef, + CONSTM1_RTX (mode), operands[6], operands[8])); + else + { + /* If vmsgeu_mask with 0 immediate, expand it to vmor mask, maskedoff. + */ + if (rtx_equal_p (operands[1], operands[2])) + emit_move_insn (operands[0], operands[1]); + else if (register_operand (operands[2], mode)) + emit_insn (gen_pred (IOR, mode, operands[0], + CONSTM1_RTX (mode), undef, operands[1], + operands[2], operands[6], operands[8])); + else + emit_insn (gen_pred (IOR, mode, operands[0], + CONSTM1_RTX (mode), undef, operands[1], + operands[1], operands[6], operands[8])); + } + } + else if (riscv_vector::neg_simm5_p (operands[5])) + emit_insn ( + gen_pred_ltge (operands[0], operands[1], operands[2], operands[3], + operands[4], + gen_const_vec_duplicate (mode, operands[5]), + operands[6], operands[7], operands[8])); + else + { + if (code == GE) + operands[3] = gen_rtx_fmt_ee (LT, mode, XEXP (operands[3], 0), + XEXP (operands[3], 1)); + else + operands[3] = gen_rtx_fmt_ee (LTU, mode, XEXP (operands[3], 0), + XEXP (operands[3], 1)); + if (GET_MODE_BITSIZE (mode) <= GET_MODE_BITSIZE (Pmode)) + operands[5] = force_reg (mode, operands[5]); + + if (satisfies_constraint_Wc1 (operands[1])) + { + /* unmasked va >= x + - pseudoinstruction: vmsge{u}.vx vd, va, x + - expansion: vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd. */ + emit_insn ( + gen_pred_cmp_scalar (operands[0], operands[1], operands[2], + operands[3], operands[4], operands[5], + operands[6], operands[7], operands[8])); + emit_insn (gen_pred_nand (operands[0], CONSTM1_RTX (mode), + undef, operands[0], operands[0], + operands[6], operands[8])); + } + else + { + if (rtx_equal_p (operands[1], operands[2])) + { + /* masked va >= x, vd == v0 + - pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t, vt + - expansion: vmslt{u}.vx vt, va, x; vmandn.mm vd, vd, vt. */ + rtx reg = gen_reg_rtx (mode); + emit_insn (gen_pred_cmp_scalar ( + reg, CONSTM1_RTX (mode), undef, operands[3], operands[4], + operands[5], operands[6], operands[7], operands[8])); + emit_insn ( + gen_pred_andn (operands[0], CONSTM1_RTX (mode), undef, + operands[1], reg, operands[6], operands[8])); + } + else + { + /* masked va >= x, vd != v0 + - pseudoinstruction: vmsge{u}.vx vd, va, x, v0.t + - expansion: vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0. + */ + emit_insn (gen_pred_cmp_scalar ( + operands[0], operands[1], operands[2], operands[3], operands[4], + operands[5], operands[6], operands[7], operands[8])); + emit_insn (gen_pred (XOR, mode, operands[0], + CONSTM1_RTX (mode), undef, operands[0], + operands[1], operands[6], operands[8])); + } + } + } + DONE; +}) + +;; ------------------------------------------------------------------------------- +;; ---- Predicated BOOL mask operations +;; ------------------------------------------------------------------------------- +;; Includes: +;; - 15.1 Vector Mask-Register Logical Instructions +;; ------------------------------------------------------------------------------- + +;; We keep this pattern same as pred_mov so that we can gain more optimizations. +;; For example, if we have vmxor.mm v1,v1,v1. It will be optmized as vmclr.m which +;; is generated by pred_mov. +(define_insn "@pred_" + [(set (match_operand:VB 0 "register_operand" "=vr") + (if_then_else:VB + (unspec:VB + [(match_operand:VB 1 "vector_all_trues_mask_operand" "Wc1") + (match_operand 5 "vector_length_operand" " rK") + (match_operand 6 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (any_bitwise:VB + (match_operand:VB 3 "register_operand" " vr") + (match_operand:VB 4 "register_operand" " vr")) + (match_operand:VB 2 "vector_undef_operand" " vu")))] + "TARGET_VECTOR" + "vm.mm\t%0,%3,%4" + [(set_attr "type" "vmalu") + (set_attr "mode" "") + (set_attr "vl_op_idx" "5") + (set (attr "avl_type") (symbol_ref "INTVAL (operands[6])"))]) + +(define_insn "@pred_n" + [(set (match_operand:VB 0 "register_operand" "=vr") + (if_then_else:VB + (unspec:VB + [(match_operand:VB 1 "vector_all_trues_mask_operand" "Wc1") + (match_operand 5 "vector_length_operand" " rK") + (match_operand 6 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (not:VB + (any_bitwise:VB + (match_operand:VB 3 "register_operand" " vr") + (match_operand:VB 4 "register_operand" " vr"))) + (match_operand:VB 2 "vector_undef_operand" " vu")))] + "TARGET_VECTOR" + "vm.mm\t%0,%3,%4" + [(set_attr "type" "vmalu") + (set_attr "mode" "") + (set_attr "vl_op_idx" "5") + (set (attr "avl_type") (symbol_ref "INTVAL (operands[6])"))]) + +(define_insn "@pred_n" + [(set (match_operand:VB 0 "register_operand" "=vr") + (if_then_else:VB + (unspec:VB + [(match_operand:VB 1 "vector_all_trues_mask_operand" "Wc1") + (match_operand 5 "vector_length_operand" " rK") + (match_operand 6 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (and_ior:VB + (match_operand:VB 3 "register_operand" " vr") + (not:VB + (match_operand:VB 4 "register_operand" " vr"))) + (match_operand:VB 2 "vector_undef_operand" " vu")))] + "TARGET_VECTOR" + "vmn.mm\t%0,%3,%4" + [(set_attr "type" "vmalu") + (set_attr "mode" "") + (set_attr "vl_op_idx" "5") + (set (attr "avl_type") (symbol_ref "INTVAL (operands[6])"))]) + +(define_insn "@pred_not" + [(set (match_operand:VB 0 "register_operand" "=vr") + (if_then_else:VB + (unspec:VB + [(match_operand:VB 1 "vector_all_trues_mask_operand" "Wc1") + (match_operand 4 "vector_length_operand" " rK") + (match_operand 5 "const_int_operand" " i") + (reg:SI VL_REGNUM) + (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE) + (not:VB + (match_operand:VB 3 "register_operand" " vr")) + (match_operand:VB 2 "vector_undef_operand" " vu")))] + "TARGET_VECTOR" + "vmnot.mm\t%0,%3" + [(set_attr "type" "vmalu") + (set_attr "mode" "") + (set_attr "vl_op_idx" "4") + (set (attr "avl_type") (symbol_ref "INTVAL (operands[5])"))]) -- 2.36.3