From patchwork Tue Aug 22 05:41:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lehua Ding X-Patchwork-Id: 136455 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b82d:0:b0:3f2:4152:657d with SMTP id z13csp3423549vqi; Mon, 21 Aug 2023 22:42:22 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEBaD5Nd+wFfxxgQ2ASlSnENie+14c5Asb1tdsYP10bLkY/nS9hKLF+BRtuPomTbNrxdhTf X-Received: by 2002:a17:906:3287:b0:992:a836:a194 with SMTP id 7-20020a170906328700b00992a836a194mr6373279ejw.59.1692682942033; Mon, 21 Aug 2023 22:42:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1692682942; cv=none; d=google.com; s=arc-20160816; b=gv0nkT8QFAxRnx5mMhCMMVEiFkWkLckbeC+S8ILrlbGJu0CoXpivvFhdbfkNkwsuo/ w8kcD2Yf+FfaMCM6eyZv605zLJPRD68ntoRIBh5JWEDhtGuq+TWeu4LkVRnuBjhbwFTP fg1C22gcLTXHlpZd8yF3lT4dDh3V76pDMgUejbkMkweLqeW78oWegPC3i50OzrrbIyNA 2pNWrt9Ua07qCT0wNObYCaAQlY/I7ZWvOEk+WLr+pT49GWZKc6efQFZMw5QVhMTtR72b zwTjYsmVwNF687gOnjcWm5AtOksUmXePDxD0Jk0aVsLNiKjPPrZw1XModnRom2MN7Pff lE/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:feedback-id :content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:dmarc-filter:delivered-to; bh=7sU17jEeXUgH+xKkj4tipiZhjEaut7s/nsWo0Cj2ZVA=; fh=ONiMOI/ENLIlS9wfuem4ok3wONuoCfEFq6S0X8Aqib8=; b=e//QVVZaKbIbAyUWUfTAeEuRg1t9yy/hEL/Uaec+eJ1yXicoWTMB0Nog16x32hCWFO cbHKA3L/WseJf0kQqLYalosIhaWkESkkgN0Bo4evIt4AdZ9Ws4j16HFGghbKIRMs7ppS I3LJ3OvTvuAeaENQUUm+esLX/NOwI1L77G15iECiextDgNh41b/Q0pkHkzzQ6HQDK6Vo R45orx6xCDDTgzjpsup8bet3Ay8mcqiQwrC74FajvczIKdGTIpVY5O+ukR+OpsjphvQA acqAerfXNPoXoSvnXgjCJvMyS/0yjUubkrWANLbsW+3cnR8/kS+7GwEwC8WBs00th36y EQ1g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org" Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id i9-20020a17090685c900b009a197afe799si2589783ejy.368.2023.08.21.22.42.21 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 21 Aug 2023 22:42:22 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org" Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 34F2B3850218 for ; Tue, 22 Aug 2023 05:42:08 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtpbgbr1.qq.com (smtpbgbr1.qq.com [54.207.19.206]) by sourceware.org (Postfix) with ESMTPS id 3A8183858CDB for ; Tue, 22 Aug 2023 05:41:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3A8183858CDB 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: bizesmtp66t1692682890tij7afo4 Received: from rios-cad122.hadoop.rioslab.org ( [58.60.1.8]) by bizesmtp.qq.com (ESMTP) with id ; Tue, 22 Aug 2023 13:41:29 +0800 (CST) X-QQ-SSF: 01400000000000C0F000000A0000000 X-QQ-FEAT: oH0qrucfWSz4V4gM8vYfDgB/zYQGq1zrzHAHh9snioz+oeVP+Qb91coR+Q3a5 7pEWihOXqvYB5E8J3E0XU9UbWV6ew98jM9i6o8q7Yw47SEWmo8XLoeEiDEpHGxh0aPKhwTv Qv9AZyp2BckbKqzONvaVzWUGMrxYzJ7dvsW/cy4vA8Q2ZcxhQfZXwGObcIhkUstCUFw82Hf MHLjZphzlGI+UHNQy86wc6dqt3OEvinHDs4MQhx+Am6/5WxBisSvgQaqRMDSp7EVoR+6KAh Kiv8TftWLWZx8K72KkcyYDUjVbaPteCIeuxqEUoKkDeSx598nIf+Q2IkuDKaKlAcgqME1/A 03KRYayNq90lmaggkPf0YzwlKMHYaLSOCIaIDMOYTYHpluMvHCMYS665ysrWJnDWOshiAiq X-QQ-GoodBg: 2 X-BIZMAIL-ID: 18227881912384434680 From: Lehua Ding To: gcc-patches@gcc.gnu.org Cc: juzhe.zhong@rivai.ai, kito.cheng@gmail.com, rdapp.gcc@gmail.com, palmer@rivosinc.com, jeffreyalaw@gmail.com Subject: [PATCH] RISC-V: Add conditional unary neg/abs/not autovec patterns Date: Tue, 22 Aug 2023 13:41:28 +0800 Message-Id: <20230822054128.1401166-1-lehua.ding@rivai.ai> X-Mailer: git-send-email 2.36.3 MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:rivai.ai:qybglogicsvrgz:qybglogicsvrgz6a-0 X-Spam-Status: No, score=-9.0 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, 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 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1774906708724999308 X-GMAIL-MSGID: 1774906708724999308 Hi, This patch add conditional unary neg/abs/not autovec patterns to RISC-V backend. Consider this C code: void test_3 (float *__restrict a, float *__restrict b, int *__restrict pred, int n) { for (int i = 0; i < n; i += 1) { a[i] = pred[i] ? __builtin_fabsf (b[i]) : a[i]; } } Before this patch: ... vsetvli a7,zero,e32,m1,ta,ma vfabs.v v2,v2 vmerge.vvm v1,v1,v2,v0 ... After this patch: ... vsetvli a7,zero,e32,m1,ta,mu vfabs.v v1,v2,v0.t ... For int neg/abs/not and FP neg patterns, Defining the corresponding cond_xxx paterns is enough. For the FP abs pattern, We need to change the definition of `abs2` and `@vcond_mask_` pattern from define_expand to define_insn_and_split in order to fuse them into a new pattern `*cond_abs` at the combine pass. After changing the pattern of neg, a vlmax copysin + neg fusion pattern needs to be added. A fusion process similar to the one below: (insn 30 29 31 4 (set (reg:RVVM1SF 152 [ vect_iftmp.15 ]) (abs:RVVM1SF (reg:RVVM1SF 137 [ vect__6.14 ]))) "float.c":15:56 discrim 1 12799 {absrvvm1sf2} (expr_list:REG_DEAD (reg:RVVM1SF 137 [ vect__6.14 ]) (nil))) (insn 31 30 32 4 (set (reg:RVVM1SF 140 [ vect_iftmp.19 ]) (if_then_else:RVVM1SF (reg:RVVMF32BI 136 [ mask__27.11 ]) (reg:RVVM1SF 152 [ vect_iftmp.15 ]) (reg:RVVM1SF 139 [ vect_iftmp.18 ]))) 12707 {vcond_mask_rvvm1sfrvvmf32bi} (expr_list:REG_DEAD (reg:RVVM1SF 152 [ vect_iftmp.15 ]) (expr_list:REG_DEAD (reg:RVVM1SF 139 [ vect_iftmp.18 ]) (expr_list:REG_DEAD (reg:RVVMF32BI 136 [ mask__27.11 ]) (nil))))) ==> (insn 31 30 32 4 (set (reg:RVVM1SF 140 [ vect_iftmp.19 ]) (if_then_else:RVVM1SF (reg:RVVMF32BI 136 [ mask__27.11 ]) (abs:RVVM1SF (reg:RVVM1SF 137 [ vect__6.14 ])) (reg:RVVM1SF 139 [ vect_iftmp.18 ]))) 13444 {*cond_absrvvm1sf} (expr_list:REG_DEAD (reg:RVVM1SF 137 [ vect__6.14 ]) (expr_list:REG_DEAD (reg:RVVMF32BI 136 [ mask__27.11 ]) (expr_list:REG_DEAD (reg:RVVM1SF 139 [ vect_iftmp.18 ]) (nil))))) Best, Lehua gcc/ChangeLog: * config/riscv/autovec-opt.md (*cond_abs): New combine pattern. (*copysign_neg): Ditto. * config/riscv/autovec.md (@vcond_mask_): Adjust. (2): Ditto. (cond_): New. (cond_len_): Ditto. * config/riscv/riscv-protos.h (enum insn_type): New. (expand_cond_len_unop): New helper func. * config/riscv/riscv-v.cc (shuffle_merge_patterns): Adjust. (expand_cond_len_unop): New helper func. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c: New test. * gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c: New test. --- gcc/config/riscv/autovec-opt.md | 39 ++++++++ gcc/config/riscv/autovec.md | 97 +++++++++++++++++-- gcc/config/riscv/riscv-protos.h | 7 +- gcc/config/riscv/riscv-v.cc | 56 ++++++++++- .../riscv/rvv/autovec/cond/cond_unary_1.c | 43 ++++++++ .../riscv/rvv/autovec/cond/cond_unary_1_run.c | 27 ++++++ .../riscv/rvv/autovec/cond/cond_unary_2.c | 47 +++++++++ .../riscv/rvv/autovec/cond/cond_unary_2_run.c | 28 ++++++ .../riscv/rvv/autovec/cond/cond_unary_3.c | 43 ++++++++ .../riscv/rvv/autovec/cond/cond_unary_3_run.c | 27 ++++++ .../riscv/rvv/autovec/cond/cond_unary_4.c | 43 ++++++++ .../riscv/rvv/autovec/cond/cond_unary_4_run.c | 27 ++++++ .../riscv/rvv/autovec/cond/cond_unary_5.c | 37 +++++++ .../riscv/rvv/autovec/cond/cond_unary_5_run.c | 26 +++++ .../riscv/rvv/autovec/cond/cond_unary_6.c | 41 ++++++++ .../riscv/rvv/autovec/cond/cond_unary_6_run.c | 27 ++++++ .../riscv/rvv/autovec/cond/cond_unary_7.c | 37 +++++++ .../riscv/rvv/autovec/cond/cond_unary_7_run.c | 26 +++++ .../riscv/rvv/autovec/cond/cond_unary_8.c | 37 +++++++ .../riscv/rvv/autovec/cond/cond_unary_8_run.c | 28 ++++++ 20 files changed, 730 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md index 99b609a99d9..8247eb87ddb 100644 --- a/gcc/config/riscv/autovec-opt.md +++ b/gcc/config/riscv/autovec-opt.md @@ -684,3 +684,42 @@ } [(set_attr "type" "vfwmuladd") (set_attr "mode" "")]) + +;; Combine and vcond_mask generated by midend into cond_len_ +;; Currently supported operations: +;; abs(FP) +(define_insn_and_split "*cond_abs" + [(set (match_operand:VF 0 "register_operand") + (if_then_else:VF + (match_operand: 3 "register_operand") + (abs:VF (match_operand:VF 1 "nonmemory_operand")) + (match_operand:VF 2 "register_operand")))] + "TARGET_VECTOR && can_create_pseudo_p ()" + "#" + "&& 1" + [(const_int 0)] +{ + emit_insn (gen_cond_len_abs (operands[0], operands[3], operands[1], + operands[2], + gen_int_mode (GET_MODE_NUNITS (mode), Pmode), + const0_rtx)); + DONE; +}) + +;; Combine vlmax neg and UNSPEC_VCOPYSIGN +(define_insn_and_split "*copysign_neg" + [(set (match_operand:VF 0 "register_operand") + (neg:VF + (unspec:VF [ + (match_operand:VF 1 "register_operand") + (match_operand:VF 2 "register_operand") + ] UNSPEC_VCOPYSIGN)))] + "TARGET_VECTOR && can_create_pseudo_p ()" + "#" + "&& 1" + [(const_int 0)] +{ + riscv_vector::emit_vlmax_insn (code_for_pred_ncopysign (mode), + riscv_vector::RVV_BINOP, operands); + DONE; +}) diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md index acca4c22b90..e1addc07036 100644 --- a/gcc/config/riscv/autovec.md +++ b/gcc/config/riscv/autovec.md @@ -552,12 +552,16 @@ ;; - vfmerge.vf ;; ------------------------------------------------------------------------- -(define_expand "@vcond_mask_" - [(match_operand:V 0 "register_operand") - (match_operand: 3 "register_operand") - (match_operand:V 1 "nonmemory_operand") - (match_operand:V 2 "register_operand")] - "TARGET_VECTOR" +(define_insn_and_split "@vcond_mask_" + [(set (match_operand:V 0 "register_operand") + (if_then_else:V + (match_operand: 3 "register_operand") + (match_operand:V 1 "nonmemory_operand") + (match_operand:V 2 "register_operand")))] + "TARGET_VECTOR && can_create_pseudo_p ()" + "#" + "&& 1" + [(const_int 0)] { /* The order of vcond_mask is opposite to pred_merge. */ std::swap (operands[1], operands[2]); @@ -979,11 +983,14 @@ ;; Includes: ;; - vfneg.v/vfabs.v ;; ------------------------------------------------------------------------------- -(define_expand "2" +(define_insn_and_split "2" [(set (match_operand:VF 0 "register_operand") (any_float_unop_nofrm:VF (match_operand:VF 1 "register_operand")))] - "TARGET_VECTOR" + "TARGET_VECTOR && can_create_pseudo_p ()" + "#" + "&& 1" + [(const_int 0)] { insn_code icode = code_for_pred (, mode); riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands); @@ -1499,6 +1506,80 @@ DONE; }) +;; ------------------------------------------------------------------------- +;; ---- [INT] Conditional unary operations +;; ------------------------------------------------------------------------- +;; Includes: +;; - vneg/vnot +;; ------------------------------------------------------------------------- + +(define_expand "cond_" + [(match_operand:VI 0 "register_operand") + (match_operand: 1 "vector_mask_operand") + (any_int_unop:VI + (match_operand:VI 2 "register_operand")) + (match_operand:VI 3 "register_operand")] + "TARGET_VECTOR" +{ + /* Normalize into cond_len_* operations. */ + emit_insn (gen_cond_len_ (operands[0], operands[1], operands[2], + operands[3], + gen_int_mode (GET_MODE_NUNITS (mode), Pmode), + const0_rtx)); + DONE; +}) + +(define_expand "cond_len_" + [(match_operand:VI 0 "register_operand") + (match_operand: 1 "vector_mask_operand") + (any_int_unop:VI + (match_operand:VI 2 "register_operand")) + (match_operand:VI 3 "register_operand") + (match_operand 4 "autovec_length_operand") + (match_operand 5 "const_0_operand")] + "TARGET_VECTOR" +{ + riscv_vector::expand_cond_len_unop (, operands); + DONE; +}) + +;; ------------------------------------------------------------------------- +;; ---- [FP] Conditional unary operations +;; ------------------------------------------------------------------------- +;; Includes: +;; - vfneg/vfabs +;; ------------------------------------------------------------------------- + +(define_expand "cond_" + [(match_operand:VF 0 "register_operand") + (match_operand: 1 "vector_mask_operand") + (any_float_unop_nofrm:VF + (match_operand:VF 2 "register_operand")) + (match_operand:VF 3 "register_operand")] + "TARGET_VECTOR" +{ + /* Normalize into cond_len_* operations. */ + emit_insn (gen_cond_len_ (operands[0], operands[1], operands[2], + operands[3], + gen_int_mode (GET_MODE_NUNITS (mode), Pmode), + const0_rtx)); + DONE; +}) + +(define_expand "cond_len_" + [(match_operand:VF 0 "register_operand") + (match_operand: 1 "vector_mask_operand") + (any_float_unop_nofrm:VF + (match_operand:VF 2 "register_operand")) + (match_operand:VF 3 "register_operand") + (match_operand 4 "autovec_length_operand") + (match_operand 5 "const_0_operand")] + "TARGET_VECTOR" +{ + riscv_vector::expand_cond_len_unop (, operands); + DONE; +}) + ;; ------------------------------------------------------------------------- ;; ---- [INT] Conditional binary operations ;; ------------------------------------------------------------------------- diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 472c00dc439..2c4405c9860 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -184,6 +184,10 @@ enum insn_type { RVV_MISC_OP = 1, RVV_UNOP = 2, + RVV_UNOP_M = RVV_UNOP + 2, + RVV_UNOP_MU = RVV_UNOP + 2, + RVV_UNOP_TU = RVV_UNOP + 2, + RVV_UNOP_TUMU = RVV_UNOP + 2, RVV_BINOP = 3, RVV_BINOP_MU = RVV_BINOP + 2, RVV_BINOP_TU = RVV_BINOP + 2, @@ -191,8 +195,6 @@ enum insn_type RVV_MERGE_OP = 4, RVV_CMP_OP = 4, RVV_CMP_MU_OP = RVV_CMP_OP + 2, /* +2 means mask and maskoff operand. */ - RVV_UNOP_MU = RVV_UNOP + 2, /* Likewise. */ - RVV_UNOP_M = RVV_UNOP + 2, /* Likewise. */ RVV_TERNOP = 5, RVV_TERNOP_MU = RVV_TERNOP + 1, RVV_TERNOP_TU = RVV_TERNOP + 1, @@ -294,6 +296,7 @@ bool neg_simm5_p (rtx); bool has_vi_variant_p (rtx_code, rtx); void expand_vec_cmp (rtx, rtx_code, rtx, rtx); bool expand_vec_cmp_float (rtx, rtx_code, rtx, rtx, bool); +void expand_cond_len_unop (rtx_code, rtx *); void expand_cond_len_binop (rtx_code, rtx *); void expand_reduction (rtx_code, rtx *, rtx, reduction_type = reduction_type::UNORDERED); diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc index b01028c6201..14eda581d00 100644 --- a/gcc/config/riscv/riscv-v.cc +++ b/gcc/config/riscv/riscv-v.cc @@ -2992,7 +2992,9 @@ shuffle_merge_patterns (struct expand_vec_perm_d *d) emit_vlmax_cmp_insn (icode, ops); /* TARGET = MASK ? OP0 : OP1. */ - emit_insn (gen_vcond_mask (vmode, vmode, d->target, d->op0, d->op1, mask)); + /* swap op0 and op1 since the order is opposite to pred_merge. */ + rtx ops2[] = {d->target, d->op1, d->op0, mask}; + emit_vlmax_merge_insn (code_for_pred_merge (vmode), riscv_vector::RVV_MERGE_OP, ops2); return true; } @@ -3384,10 +3386,58 @@ needs_fp_rounding (rtx_code code, machine_mode mode) { if (!FLOAT_MODE_P (mode)) return false; - return code != SMIN && code != SMAX; + return code != SMIN && code != SMAX && code != NEG && code != ABS; } -/* Expand COND_LEN_*. */ +/* Expand unary ops COND_LEN_*. */ +void +expand_cond_len_unop (rtx_code code, rtx *ops) +{ + rtx dest = ops[0]; + rtx mask = ops[1]; + rtx src = ops[2]; + rtx merge = ops[3]; + rtx len = ops[4]; + machine_mode mode = GET_MODE (dest); + machine_mode mask_mode = GET_MODE (mask); + + poly_int64 value; + bool is_dummy_mask = rtx_equal_p (mask, CONSTM1_RTX (mask_mode)); + bool is_vlmax_len + = poly_int_rtx_p (len, &value) && known_eq (value, GET_MODE_NUNITS (mode)); + rtx cond_ops[] = {dest, mask, merge, src}; + insn_code icode = code_for_pred (code, mode); + + if (is_dummy_mask) + { + /* Use TU, MASK ANY policy. */ + if (needs_fp_rounding (code, mode)) + emit_nonvlmax_fp_tu_insn (icode, RVV_UNOP_TU, cond_ops, len); + else + emit_nonvlmax_tu_insn (icode, RVV_UNOP_TU, cond_ops, len); + } + else + { + if (is_vlmax_len) + { + /* Use TAIL ANY, MU policy. */ + if (needs_fp_rounding (code, mode)) + emit_vlmax_masked_fp_mu_insn (icode, RVV_UNOP_MU, cond_ops); + else + emit_vlmax_masked_mu_insn (icode, RVV_UNOP_MU, cond_ops); + } + else + { + /* Use TU, MU policy. */ + if (needs_fp_rounding (code, mode)) + emit_nonvlmax_fp_tumu_insn (icode, RVV_UNOP_TUMU, cond_ops, len); + else + emit_nonvlmax_tumu_insn (icode, RVV_UNOP_TUMU, cond_ops, len); + } + } +} + +/* Expand binary ops COND_LEN_*. */ void expand_cond_len_binop (rtx_code code, rtx *ops) { diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c new file mode 100644 index 00000000000..e8bf41a55a1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include + +#define abs(A) ((A) < 0 ? -(A) : (A)) +#define neg(A) (-(A)) +#define not(A) (~(A)) + +#define DEF_LOOP(TYPE, OP) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##OP (TYPE *__restrict r, TYPE *__restrict a, \ + TYPE *__restrict pred, int n) \ + { \ + for (int i = 0; i < n; ++i) \ + r[i] = pred[i] ? OP (a[i]) : a[i]; \ + } + +#define TEST_INT_TYPE(T, TYPE) \ + T (TYPE, abs) \ + T (TYPE, neg) \ + T (TYPE, not) + +#define TEST_FLOAT_TYPE(T, TYPE, SUFFIX) \ + T (TYPE, __builtin_fabs##SUFFIX) \ + T (TYPE, neg) + +#define TEST_ALL(T) \ + TEST_INT_TYPE (T, int8_t) \ + TEST_INT_TYPE (T, int16_t) \ + TEST_INT_TYPE (T, int32_t) \ + TEST_INT_TYPE (T, int64_t) \ + TEST_FLOAT_TYPE (T, _Float16, f16) \ + TEST_FLOAT_TYPE (T, float, f) \ + TEST_FLOAT_TYPE (T, double, ) + +TEST_ALL (DEF_LOOP) + +/* NOTE: int abs operator is converted to vmslt + vneg.v */ +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 8 } } */ +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 4 } } */ +/* { dg-final { scan-assembler-times {\tvfabs\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } } */ +/* { dg-final { scan-assembler-times {\tvfneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c new file mode 100644 index 00000000000..90f1c1a71e7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_1_run.c @@ -0,0 +1,27 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include "cond_unary_1.c" + +#define N 99 + +#define TEST_LOOP(TYPE, OP) \ + { \ + TYPE r[N], a[N], pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ + pred[i] = (i % 7 < 4); \ + asm volatile ("" ::: "memory"); \ + } \ + test_##TYPE##_##OP (r, a, pred, N); \ + for (int i = 0; i < N; ++i) \ + if (r[i] != (pred[i] ? OP (a[i]) : a[i])) \ + __builtin_abort (); \ + } + +int main () +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c new file mode 100644 index 00000000000..fb984ded12f --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include + +#define abs(A) ((A) < 0 ? -(A) : (A)) +#define neg(A) (-(A)) +#define not(A) (~(A)) + +#define DEF_LOOP(TYPE, OP) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##OP (TYPE *__restrict r, TYPE *__restrict a, \ + TYPE *__restrict b, \ + TYPE *__restrict pred, int n) \ + { \ + for (int i = 0; i < n; ++i) \ + { \ + TYPE bi = b[i]; \ + r[i] = pred[i] ? OP (a[i]) : bi; \ + } \ + } + +#define TEST_INT_TYPE(T, TYPE) \ + T (TYPE, abs) \ + T (TYPE, neg) \ + T (TYPE, not) + +#define TEST_FLOAT_TYPE(T, TYPE, SUFFIX) \ + T (TYPE, __builtin_fabs##SUFFIX) \ + T (TYPE, neg) + +#define TEST_ALL(T) \ + TEST_INT_TYPE (T, int8_t) \ + TEST_INT_TYPE (T, int16_t) \ + TEST_INT_TYPE (T, int32_t) \ + TEST_INT_TYPE (T, int64_t) \ + TEST_FLOAT_TYPE (T, _Float16, f16) \ + TEST_FLOAT_TYPE (T, float, f) \ + TEST_FLOAT_TYPE (T, double, ) + +TEST_ALL (DEF_LOOP) + +/* NOTE: int abs operator is converted to vmslt + vneg.v */ +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 8 } } */ +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 4 } } */ +/* { dg-final { scan-assembler-times {\tvfabs\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } } */ +/* { dg-final { scan-assembler-times {\tvfneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c new file mode 100644 index 00000000000..b739c5d8df2 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_2_run.c @@ -0,0 +1,28 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include "cond_unary_2.c" + +#define N 99 + +#define TEST_LOOP(TYPE, OP) \ + { \ + TYPE r[N], a[N], b[N], pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ + b[i] = (i % 9) * (i % 7 + 1); \ + pred[i] = (i % 7 < 4); \ + asm volatile ("" ::: "memory"); \ + } \ + test_##TYPE##_##OP (r, a, b, pred, N); \ + for (int i = 0; i < N; ++i) \ + if (r[i] != (pred[i] ? OP (a[i]) : b[i])) \ + __builtin_abort (); \ + } + +int main () +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c new file mode 100644 index 00000000000..a1aeaf076de --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include + +#define abs(A) ((A) < 0 ? -(A) : (A)) +#define neg(A) (-(A)) +#define not(A) (~(A)) + +#define DEF_LOOP(TYPE, OP) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##OP (TYPE *__restrict r, TYPE *__restrict a, \ + TYPE *__restrict pred, int n) \ + { \ + for (int i = 0; i < n; ++i) \ + r[i] = pred[i] ? OP (a[i]) : 5; \ + } + +#define TEST_INT_TYPE(T, TYPE) \ + T (TYPE, abs) \ + T (TYPE, neg) \ + T (TYPE, not) + +#define TEST_FLOAT_TYPE(T, TYPE, SUFFIX) \ + T (TYPE, __builtin_fabs##SUFFIX) \ + T (TYPE, neg) + +#define TEST_ALL(T) \ + TEST_INT_TYPE (T, int8_t) \ + TEST_INT_TYPE (T, int16_t) \ + TEST_INT_TYPE (T, int32_t) \ + TEST_INT_TYPE (T, int64_t) \ + TEST_FLOAT_TYPE (T, _Float16, f16) \ + TEST_FLOAT_TYPE (T, float, f) \ + TEST_FLOAT_TYPE (T, double, ) + +TEST_ALL (DEF_LOOP) + +/* NOTE: int abs operator is converted to vmslt + vneg.v */ +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 8 } } */ +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 4 } } */ +/* { dg-final { scan-assembler-times {\tvfabs\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } } */ +/* { dg-final { scan-assembler-times {\tvfneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c new file mode 100644 index 00000000000..9234c94d9bf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_3_run.c @@ -0,0 +1,27 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include "cond_unary_3.c" + +#define N 99 + +#define TEST_LOOP(TYPE, OP) \ + { \ + TYPE r[N], a[N], pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ + pred[i] = (i % 7 < 4); \ + asm volatile ("" ::: "memory"); \ + } \ + test_##TYPE##_##OP (r, a, pred, N); \ + for (int i = 0; i < N; ++i) \ + if (r[i] != (pred[i] ? OP (a[i]) : 5)) \ + __builtin_abort (); \ + } + +int main () +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c new file mode 100644 index 00000000000..ed041fe28cd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include + +#define abs(A) ((A) < 0 ? -(A) : (A)) +#define neg(A) (-(A)) +#define not(A) (~(A)) + +#define DEF_LOOP(TYPE, OP) \ + void __attribute__ ((noipa)) \ + test_##TYPE##_##OP (TYPE *__restrict r, TYPE *__restrict a, \ + TYPE *__restrict pred, int n) \ + { \ + for (int i = 0; i < n; ++i) \ + r[i] = pred[i] ? OP (a[i]) : 0; \ + } + +#define TEST_INT_TYPE(T, TYPE) \ + T (TYPE, abs) \ + T (TYPE, neg) \ + T (TYPE, not) + +#define TEST_FLOAT_TYPE(T, TYPE, SUFFIX) \ + T (TYPE, __builtin_fabs##SUFFIX) \ + T (TYPE, neg) + +#define TEST_ALL(T) \ + TEST_INT_TYPE (T, int8_t) \ + TEST_INT_TYPE (T, int16_t) \ + TEST_INT_TYPE (T, int32_t) \ + TEST_INT_TYPE (T, int64_t) \ + TEST_FLOAT_TYPE (T, _Float16, f16) \ + TEST_FLOAT_TYPE (T, float, f) \ + TEST_FLOAT_TYPE (T, double, ) + +TEST_ALL (DEF_LOOP) + +/* NOTE: int abs operator is converted to vmslt + vneg.v */ +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 8 } } */ +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 4 } } */ +/* { dg-final { scan-assembler-times {\tvfabs\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } } */ +/* { dg-final { scan-assembler-times {\tvfneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 3 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c new file mode 100644 index 00000000000..52fd4d07be9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_4_run.c @@ -0,0 +1,27 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include "cond_unary_4.c" + +#define N 99 + +#define TEST_LOOP(TYPE, OP) \ + { \ + TYPE r[N], a[N], pred[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ + pred[i] = (i % 7 < 4); \ + asm volatile ("" ::: "memory"); \ + } \ + test_##TYPE##_##OP (r, a, pred, N); \ + for (int i = 0; i < N; ++i) \ + if (r[i] != (pred[i] ? OP (a[i]) : 0)) \ + __builtin_abort (); \ + } + +int main () +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c new file mode 100644 index 00000000000..6c0a25aad6b --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include + +#define abs(A) ((A) < 0 ? -(A) : (A)) +#define neg(A) (-(A)) +#define not(A) (~(A)) + +#define DEF_LOOP(TYPE1, TYPE2, COUNT, OP) \ + void __attribute__ ((noipa)) \ + test_##TYPE1##_##TYPE2##_##OP (TYPE2 *__restrict r, \ + TYPE2 *__restrict a, \ + TYPE1 *__restrict pred) \ + { \ + for (int i = 0; i < COUNT; ++i) \ + r[i] = pred[i] ? OP (a[i]) : a[i]; \ + } + +#define TEST_TYPES(T, TYPE1, TYPE2, COUNT) \ + T (TYPE1, TYPE2, COUNT, abs) \ + T (TYPE1, TYPE2, COUNT, neg) \ + T (TYPE1, TYPE2, COUNT, not) + +#define TEST_ALL(T) \ + TEST_TYPES (T, int16_t, int8_t, 7) \ + TEST_TYPES (T, int32_t, int8_t, 3) \ + TEST_TYPES (T, int32_t, int16_t, 3) \ + TEST_TYPES (T, int64_t, int8_t, 5) \ + TEST_TYPES (T, int64_t, int16_t, 5) \ + TEST_TYPES (T, int64_t, int32_t, 5) + +TEST_ALL (DEF_LOOP) + +/* NOTE: int abs operator is converted to vmslt + vneg.v */ +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 12 { xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 6 { xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c new file mode 100644 index 00000000000..efd4c2936f1 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_5_run.c @@ -0,0 +1,26 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include "cond_unary_5.c" + +#define TEST_LOOP(TYPE1, TYPE2, N, OP) \ + { \ + TYPE1 pred[N]; \ + TYPE2 r[N], a[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ + pred[i] = (i % 4 < 2); \ + asm volatile ("" ::: "memory"); \ + } \ + test_##TYPE1##_##TYPE2##_##OP (r, a, pred); \ + for (int i = 0; i < N; ++i) \ + if (r[i] != (pred[i] ? OP (a[i]) : a[i])) \ + __builtin_abort (); \ + } + +int main () +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c new file mode 100644 index 00000000000..b2050f21389 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include + +#define abs(A) ((A) < 0 ? -(A) : (A)) +#define neg(A) (-(A)) +#define not(A) (~(A)) + +#define DEF_LOOP(TYPE1, TYPE2, COUNT, OP) \ + void __attribute__ ((noipa)) \ + test_##TYPE1##_##TYPE2##_##OP (TYPE2 *__restrict r, \ + TYPE2 *__restrict a, \ + TYPE2 *__restrict b, \ + TYPE1 *__restrict pred) \ + { \ + for (int i = 0; i < COUNT; ++i) \ + { \ + TYPE2 bi = b[i]; \ + r[i] = pred[i] ? OP (a[i]) : bi; \ + } \ + } + +#define TEST_TYPES(T, TYPE1, TYPE2, COUNT) \ + T (TYPE1, TYPE2, COUNT, abs) \ + T (TYPE1, TYPE2, COUNT, neg) \ + T (TYPE1, TYPE2, COUNT, not) + +#define TEST_ALL(T) \ + TEST_TYPES (T, int16_t, int8_t, 7) \ + TEST_TYPES (T, int32_t, int8_t, 3) \ + TEST_TYPES (T, int32_t, int16_t, 3) \ + TEST_TYPES (T, int64_t, int8_t, 5) \ + TEST_TYPES (T, int64_t, int16_t, 5) \ + TEST_TYPES (T, int64_t, int32_t, 5) + +TEST_ALL (DEF_LOOP) + +/* NOTE: int abs operator is converted to vmslt + vneg.v */ +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 12 { xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 6 { xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c new file mode 100644 index 00000000000..e42be948748 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_6_run.c @@ -0,0 +1,27 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include "cond_unary_6.c" + +#define TEST_LOOP(TYPE1, TYPE2, N, OP) \ + { \ + TYPE1 pred[N]; \ + TYPE2 r[N], a[N], b[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ + b[i] = (i % 5) * (i % 6 + 3); \ + pred[i] = (i % 4 < 2); \ + asm volatile ("" ::: "memory"); \ + } \ + test_##TYPE1##_##TYPE2##_##OP (r, a, b, pred); \ + for (int i = 0; i < N; ++i) \ + if (r[i] != (pred[i] ? OP (a[i]) : b[i])) \ + __builtin_abort (); \ + } + +int main () +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c new file mode 100644 index 00000000000..72577703cee --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include + +#define abs(A) ((A) < 0 ? -(A) : (A)) +#define neg(A) (-(A)) +#define not(A) (~(A)) + +#define DEF_LOOP(TYPE1, TYPE2, COUNT, OP) \ + void __attribute__ ((noipa)) \ + test_##TYPE1##_##TYPE2##_##OP (TYPE2 *__restrict r, \ + TYPE2 *__restrict a, \ + TYPE1 *__restrict pred) \ + { \ + for (int i = 0; i < COUNT; ++i) \ + r[i] = pred[i] ? OP (a[i]) : 5; \ + } + +#define TEST_TYPES(T, TYPE1, TYPE2, COUNT) \ + T (TYPE1, TYPE2, COUNT, abs) \ + T (TYPE1, TYPE2, COUNT, neg) \ + T (TYPE1, TYPE2, COUNT, not) + +#define TEST_ALL(T) \ + TEST_TYPES (T, int16_t, int8_t, 7) \ + TEST_TYPES (T, int32_t, int8_t, 3) \ + TEST_TYPES (T, int32_t, int16_t, 3) \ + TEST_TYPES (T, int64_t, int8_t, 5) \ + TEST_TYPES (T, int64_t, int16_t, 5) \ + TEST_TYPES (T, int64_t, int32_t, 5) + +TEST_ALL (DEF_LOOP) + +/* NOTE: int abs operator is converted to vmslt + vneg.v */ +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 12 { xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 6 { xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c new file mode 100644 index 00000000000..50ff6727086 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_7_run.c @@ -0,0 +1,26 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include "cond_unary_7.c" + +#define TEST_LOOP(TYPE1, TYPE2, N, OP) \ + { \ + TYPE1 pred[N]; \ + TYPE2 r[N], a[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ + pred[i] = (i % 4 < 2); \ + asm volatile ("" ::: "memory"); \ + } \ + test_##TYPE1##_##TYPE2##_##OP (r, a, pred); \ + for (int i = 0; i < N; ++i) \ + if (r[i] != (pred[i] ? OP (a[i]) : 5)) \ + __builtin_abort (); \ + } + +int main () +{ + TEST_ALL (TEST_LOOP) + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c new file mode 100644 index 00000000000..269cc3ded95 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-march=rv64gcv_zvfh -mabi=lp64d --param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include + +#define abs(A) ((A) < 0 ? -(A) : (A)) +#define neg(A) (-(A)) +#define not(A) (~(A)) + +#define DEF_LOOP(TYPE1, TYPE2, COUNT, OP) \ + void __attribute__ ((noipa)) \ + test_##TYPE1##_##TYPE2##_##OP (TYPE2 *__restrict r, \ + TYPE2 *__restrict a, \ + TYPE1 *__restrict pred) \ + { \ + for (int i = 0; i < COUNT; ++i) \ + r[i] = pred[i] ? OP (a[i]) : 0; \ + } + +#define TEST_TYPES(T, TYPE1, TYPE2, COUNT) \ + T (TYPE1, TYPE2, COUNT, abs) \ + T (TYPE1, TYPE2, COUNT, neg) \ + T (TYPE1, TYPE2, COUNT, not) + +#define TEST_ALL(T) \ + TEST_TYPES (T, int16_t, int8_t, 7) \ + TEST_TYPES (T, int32_t, int8_t, 3) \ + TEST_TYPES (T, int32_t, int16_t, 3) \ + TEST_TYPES (T, int64_t, int8_t, 5) \ + TEST_TYPES (T, int64_t, int16_t, 5) \ + TEST_TYPES (T, int64_t, int32_t, 5) + +TEST_ALL (DEF_LOOP) + +/* NOTE: int abs operator is converted to vmslt + vneg.v */ +/* { dg-final { scan-assembler-times {\tvneg\.v\tv[0-9]+,v[0-9]+,v0\.t} 12 { xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ +/* { dg-final { scan-assembler-times {\tvnot\.v\tv[0-9]+,v[0-9]+,v0\.t} 6 { xfail { any-opts "--param riscv-autovec-lmul=m2" } } } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c new file mode 100644 index 00000000000..dcc72313f99 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/cond/cond_unary_8_run.c @@ -0,0 +1,28 @@ +/* { dg-do run { target { riscv_vector } } } */ +/* { dg-additional-options "--param riscv-autovec-preference=scalable -fno-vect-cost-model" } */ + +#include "cond_unary_8.c" + +#define N 99 + +#define TEST_LOOP(TYPE1, TYPE2, N, OP) \ + { \ + TYPE1 pred[N]; \ + TYPE2 r[N], a[N]; \ + for (int i = 0; i < N; ++i) \ + { \ + a[i] = (i & 1 ? i : 3 * i) * (i % 3 == 0 ? 1 : -1); \ + pred[i] = (i % 4 < 2); \ + asm volatile ("" ::: "memory"); \ + } \ + test_##TYPE1##_##TYPE2##_##OP (r, a, pred); \ + for (int i = 0; i < N; ++i) \ + if (r[i] != (pred[i] ? OP (a[i]) : 0)) \ + __builtin_abort (); \ + } + +int main () +{ + TEST_ALL (TEST_LOOP) + return 0; +}