* [PATCH 0/5] Recognize Zicond extension
@ 2023-07-19 10:11 Xiao Zeng
2023-07-19 10:11 ` [PATCH 1/5] [RISC-V] " Xiao Zeng
` (5 more replies)
0 siblings, 6 replies; 40+ messages in thread
From: Xiao Zeng @ 2023-07-19 10:11 UTC (permalink / raw)
To: gcc-patches
Cc: jeffreyalaw, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain, Xiao Zeng
Hi all RISC-V folks:
This series of patches completes support for the riscv architecture's
Zicond standard extension instruction set.
Currently, Zicond is in a frozen state.
See the Zicond specification for details:
https://github.com/riscv/riscv-zicond/releases/download/v1.0-rc2/riscv-zicond-v1.0-rc2.pdf
Prior to this, other community members have also done related work, as shown in:
https://gcc.gnu.org/pipermail/gcc-patches/2023-February/611767.html
https://sourceware.org/pipermail/binutils/2023-January/125773.html
Xiao Zeng (5):
[RISC-V] Recognize Zicond extension
[RISC-V] Generate Zicond instruction for basic semantics
[RISC-V] Generate Zicond instruction for select pattern with condition
eq or neq to 0
[RISC-V] Generate Zicond instruction for select pattern with condition
eq or neq to non-zero
[RISC-V] Generate Zicond instruction for conditional execution
gcc/common/config/riscv/riscv-common.cc | 3 +
gcc/config/riscv/riscv-opts.h | 3 +
gcc/config/riscv/riscv.cc | 141 +++++
gcc/config/riscv/riscv.md | 3 +-
gcc/config/riscv/zicond.md | 84 +++
gcc/ifcvt.cc | 251 ++++++++
gcc/testsuite/gcc.target/riscv/attribute-20.c | 6 +
gcc/testsuite/gcc.target/riscv/attribute-21.c | 6 +
...ionalArithmetic_compare_0_return_imm_reg.c | 553 +++++++++++++++++
...ionalArithmetic_compare_0_return_reg_reg.c | 585 ++++++++++++++++++
...nalArithmetic_compare_imm_return_imm_reg.c | 297 +++++++++
...nalArithmetic_compare_imm_return_reg_reg.c | 297 +++++++++
...nalArithmetic_compare_reg_return_imm_reg.c | 297 +++++++++
...nalArithmetic_compare_reg_return_reg_reg.c | 329 ++++++++++
.../riscv/zicond-primitiveSemantics.c | 49 ++
.../zicond-primitiveSemantics_compare_imm.c | 57 ++
...mitiveSemantics_compare_imm_return_0_imm.c | 73 +++
...tiveSemantics_compare_imm_return_imm_imm.c | 73 +++
...tiveSemantics_compare_imm_return_imm_reg.c | 65 ++
...tiveSemantics_compare_imm_return_reg_reg.c | 65 ++
.../zicond-primitiveSemantics_compare_reg.c | 65 ++
...mitiveSemantics_compare_reg_return_0_imm.c | 73 +++
...tiveSemantics_compare_reg_return_imm_imm.c | 73 +++
...tiveSemantics_compare_reg_return_imm_reg.c | 65 ++
...tiveSemantics_compare_reg_return_reg_reg.c | 77 +++
.../zicond-primitiveSemantics_return_0_imm.c | 65 ++
...zicond-primitiveSemantics_return_imm_imm.c | 73 +++
...zicond-primitiveSemantics_return_imm_reg.c | 65 ++
...zicond-primitiveSemantics_return_reg_reg.c | 65 ++
29 files changed, 3857 insertions(+), 1 deletion(-)
create mode 100644 gcc/config/riscv/zicond.md
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-20.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-21.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_reg_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_reg_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_reg_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_0_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_0_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c
--
2.17.1
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH 1/5] [RISC-V] Recognize Zicond extension
2023-07-19 10:11 [PATCH 0/5] Recognize Zicond extension Xiao Zeng
@ 2023-07-19 10:11 ` Xiao Zeng
2023-07-25 16:35 ` Jeff Law
2023-07-26 21:11 ` Jeff Law
2023-07-19 10:11 ` [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics Xiao Zeng
` (4 subsequent siblings)
5 siblings, 2 replies; 40+ messages in thread
From: Xiao Zeng @ 2023-07-19 10:11 UTC (permalink / raw)
To: gcc-patches
Cc: jeffreyalaw, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain, Xiao Zeng
This patch is the minimal support for Zicond extension, include
the extension name, mask and target defination.
gcc/ChangeLog:
* common/config/riscv/riscv-common.cc: New extension.
* config/riscv/riscv-opts.h (MASK_ZICOND): New mask.
(TARGET_ZICOND): New target.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/attribute-20.c: New test.
* gcc.target/riscv/attribute-21.c: New test.
---
gcc/common/config/riscv/riscv-common.cc | 3 +++
gcc/config/riscv/riscv-opts.h | 3 +++
gcc/testsuite/gcc.target/riscv/attribute-20.c | 6 ++++++
gcc/testsuite/gcc.target/riscv/attribute-21.c | 6 ++++++
4 files changed, 18 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-20.c
create mode 100644 gcc/testsuite/gcc.target/riscv/attribute-21.c
diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 6091d8f281b..8460d83b0f1 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -183,6 +183,8 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
{"zifencei", ISA_SPEC_CLASS_20191213, 2, 0},
{"zifencei", ISA_SPEC_CLASS_20190608, 2, 0},
+ {"zicond", ISA_SPEC_CLASS_NONE, 1, 0},
+
{"zawrs", ISA_SPEC_CLASS_NONE, 1, 0},
{"zba", ISA_SPEC_CLASS_NONE, 1, 0},
@@ -1243,6 +1245,7 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
{"zicsr", &gcc_options::x_riscv_zi_subext, MASK_ZICSR},
{"zifencei", &gcc_options::x_riscv_zi_subext, MASK_ZIFENCEI},
+ {"zicond", &gcc_options::x_riscv_zi_subext, MASK_ZICOND},
{"zawrs", &gcc_options::x_riscv_za_subext, MASK_ZAWRS},
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index cfcf608ea62..cecaee7d200 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -236,6 +236,9 @@ enum riscv_entity
#define TARGET_ZICBOM ((riscv_zicmo_subext & MASK_ZICBOM) != 0)
#define TARGET_ZICBOP ((riscv_zicmo_subext & MASK_ZICBOP) != 0)
+#define MASK_ZICOND (1 << 2)
+#define TARGET_ZICOND ((riscv_zi_subext & MASK_ZICOND) != 0)
+
#define MASK_ZFHMIN (1 << 0)
#define MASK_ZFH (1 << 1)
#define MASK_ZVFHMIN (1 << 2)
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-20.c b/gcc/testsuite/gcc.target/riscv/attribute-20.c
new file mode 100644
index 00000000000..b69c36cf4f1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-20.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-mriscv-attribute -march=rv32i_zicond -mabi=ilp32" } */
+
+void foo(){}
+
+/* { dg-final { scan-assembler ".attribute arch, \"rv32i2p1_zicond1p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/attribute-21.c b/gcc/testsuite/gcc.target/riscv/attribute-21.c
new file mode 100644
index 00000000000..160312a0d48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/attribute-21.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-mriscv-attribute -march=rv64i_zicond -mabi=lp64" } */
+
+void foo(){}
+
+/* { dg-final { scan-assembler ".attribute arch, \"rv64i2p1_zicond1p0\"" } } */
--
2.17.1
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics
2023-07-19 10:11 [PATCH 0/5] Recognize Zicond extension Xiao Zeng
2023-07-19 10:11 ` [PATCH 1/5] [RISC-V] " Xiao Zeng
@ 2023-07-19 10:11 ` Xiao Zeng
2023-07-25 16:35 ` Jeff Law
` (2 more replies)
2023-07-19 10:11 ` [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 Xiao Zeng
` (3 subsequent siblings)
5 siblings, 3 replies; 40+ messages in thread
From: Xiao Zeng @ 2023-07-19 10:11 UTC (permalink / raw)
To: gcc-patches
Cc: jeffreyalaw, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain, Xiao Zeng
This patch completes the recognition of the basic semantics
defined in the spec, namely:
Conditional zero, if condition is equal to zero
rd = (rs2 == 0) ? 0 : rs1
Conditional zero, if condition is non zero
rd = (rs2 != 0) ? 0 : rs1
gcc/ChangeLog:
* config/riscv/riscv.md: Include zicond.md
* config/riscv/zicond.md: New file.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/zicond-primitiveSemantics.c: New test.
---
gcc/config/riscv/riscv.md | 1 +
gcc/config/riscv/zicond.md | 84 +++++++++++++++++++
.../riscv/zicond-primitiveSemantics.c | 49 +++++++++++
3 files changed, 134 insertions(+)
create mode 100644 gcc/config/riscv/zicond.md
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics.c
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index d63b584a4c1..6b8c2e8e268 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3317,3 +3317,4 @@
(include "sifive-7.md")
(include "thead.md")
(include "vector.md")
+(include "zicond.md")
diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md
new file mode 100644
index 00000000000..1cf28589c87
--- /dev/null
+++ b/gcc/config/riscv/zicond.md
@@ -0,0 +1,84 @@
+;; Machine description for the RISC-V Zicond extension
+;; Copyright (C) 2022-23 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_code_iterator eq_or_ne [eq ne])
+(define_code_attr eqz [(eq "nez") (ne "eqz")])
+(define_code_attr nez [(eq "eqz") (ne "nez")])
+
+;; Zicond
+(define_insn "*czero.<eqz>.<GPR:mode><ANYI:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (eq_or_ne (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "r")
+ (const_int 0)))]
+ "TARGET_ZICOND"
+ "czero.<eqz>\t%0,%2,%1"
+)
+
+(define_insn "*czero.<nez>.<GPR:mode><ANYI:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (eq_or_ne (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (const_int 0)
+ (match_operand:GPR 2 "register_operand" "r")))]
+ "TARGET_ZICOND"
+ "czero.<nez>\t%0,%2,%1"
+)
+
+;; Special optimization under eq/ne in primitive semantics
+(define_insn "*czero.eqz.<GPR:mode><ANYI:mode>.opt1"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (eq (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "1")
+ (match_operand:GPR 3 "register_operand" "r")))]
+ "TARGET_ZICOND && operands[1] == operands[2]"
+ "czero.eqz\t%0,%3,%1"
+)
+
+(define_insn "*czero.eqz.<GPR:mode><ANYI:mode>.opt2"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (eq (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "r")
+ (match_operand:GPR 3 "register_operand" "1")))]
+ "TARGET_ZICOND && operands[1] == operands[3]"
+ "czero.nez\t%0,%2,%1"
+)
+
+(define_insn "*czero.nez.<GPR:mode><ANYI:mode>.opt3"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (ne (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "r")
+ (match_operand:GPR 3 "register_operand" "1")))]
+ "TARGET_ZICOND && operands[1] == operands[3]"
+ "czero.eqz\t%0,%2,%1"
+)
+
+(define_insn "*czero.nez.<GPR:mode><ANYI:mode>.opt4"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (ne (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "1")
+ (match_operand:GPR 3 "register_operand" "r")))]
+ "TARGET_ZICOND && operands[1] == operands[2]"
+ "czero.nez\t%0,%3,%1"
+)
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics.c
new file mode 100644
index 00000000000..76c5019a992
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0"} } */
+
+long primitiveSemantics_00(long a, long b) { return a == 0 ? 0 : b; }
+
+long primitiveSemantics_01(long a, long b) { return a != 0 ? 0 : b; }
+
+long primitiveSemantics_02(long a, long b) { return a == 0 ? b : 0; }
+
+long primitiveSemantics_03(long a, long b) { return a != 0 ? b : 0; }
+
+long primitiveSemantics_04(long a, long b) {
+ if (a)
+ b = 0;
+ return b;
+}
+
+long primitiveSemantics_05(long a, long b) {
+ if (!a)
+ b = 0;
+ return b;
+}
+
+int primitiveSemantics_06(int a, int b) { return a == 0 ? 0 : b; }
+
+int primitiveSemantics_07(int a, int b) { return a != 0 ? 0 : b; }
+
+int primitiveSemantics_08(int a, int b) { return a == 0 ? b : 0; }
+
+int primitiveSemantics_09(int a, int b) { return a != 0 ? b : 0; }
+
+int primitiveSemantics_10(int a, int b) {
+ if (a)
+ b = 0;
+ return b;
+}
+
+int primitiveSemantics_11(int a, int b) {
+ if (!a)
+ b = 0;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
--
2.17.1
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-19 10:11 [PATCH 0/5] Recognize Zicond extension Xiao Zeng
2023-07-19 10:11 ` [PATCH 1/5] [RISC-V] " Xiao Zeng
2023-07-19 10:11 ` [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics Xiao Zeng
@ 2023-07-19 10:11 ` Xiao Zeng
2023-07-25 17:32 ` Jeff Law
` (3 more replies)
2023-07-19 10:11 ` [PATCH 4/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to non-zero Xiao Zeng
` (2 subsequent siblings)
5 siblings, 4 replies; 40+ messages in thread
From: Xiao Zeng @ 2023-07-19 10:11 UTC (permalink / raw)
To: gcc-patches
Cc: jeffreyalaw, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain, Xiao Zeng
This patch completes the recognition of Zicond when the select pattern
with condition eq or neq to 0 (using equality as an example), namely:
1 rd = (rs2 == 0) ? non-imm : 0
2 rd = (rs2 == 0) ? non-imm : non-imm
3 rd = (rs2 == 0) ? reg : non-imm
4 rd = (rs2 == 0) ? reg : reg
gcc/ChangeLog:
* config/riscv/riscv.cc (riscv_rtx_costs): IF_THEN_ELSE costs in Zicond.
(riscv_expand_conditional_move): Recognize Zicond.
* config/riscv/riscv.md: Zicond patterns.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c: New test.
---
gcc/config/riscv/riscv.cc | 125 ++++++++++++++++++
gcc/config/riscv/riscv.md | 2 +-
.../zicond-primitiveSemantics_return_0_imm.c | 65 +++++++++
...zicond-primitiveSemantics_return_imm_imm.c | 73 ++++++++++
...zicond-primitiveSemantics_return_imm_reg.c | 65 +++++++++
...zicond-primitiveSemantics_return_reg_reg.c | 65 +++++++++
6 files changed, 394 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 38d8eb2fcf5..7e6b24bd232 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2448,6 +2448,17 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
*total = COSTS_N_INSNS (1);
return true;
}
+ else if (TARGET_ZICOND && outer_code == SET &&
+ ((GET_CODE (XEXP (x, 1)) == REG && XEXP (x, 2) == const0_rtx) ||
+ (GET_CODE (XEXP (x, 2)) == REG && XEXP (x, 1) == const0_rtx) ||
+ (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
+ XEXP (x, 1) == XEXP (XEXP (x, 0), 0)) ||
+ (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
+ XEXP (x, 2) == XEXP (XEXP (x, 0), 0))))
+ {
+ *total = 0;
+ return true;
+ }
else if (LABEL_REF_P (XEXP (x, 1)) && XEXP (x, 2) == pc_rtx)
{
if (equality_operator (XEXP (x, 0), mode)
@@ -3501,6 +3512,120 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
cond, cons, alt)));
return true;
}
+ else if (TARGET_ZICOND
+ && (code == EQ || code == NE)
+ && GET_MODE_CLASS (mode) == MODE_INT)
+ {
+ need_eq_ne_p = true;
+ /* 0 + imm */
+ if (GET_CODE (cons) == CONST_INT && cons == const0_rtx
+ && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
+ {
+ riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ alt = force_reg (mode, alt);
+ emit_insn (gen_rtx_SET (dest,
+ gen_rtx_IF_THEN_ELSE (mode, cond,
+ cons, alt)));
+ return true;
+ }
+ /* imm + imm */
+ else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
+ && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
+ {
+ riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ alt = force_reg (mode, alt);
+ rtx temp1 = gen_reg_rtx (mode);
+ rtx temp2 = GEN_INT(-1 * INTVAL (cons));
+ riscv_emit_binary(PLUS, temp1, alt, temp2);
+ emit_insn (gen_rtx_SET (dest,
+ gen_rtx_IF_THEN_ELSE (mode, cond,
+ const0_rtx, alt)));
+ riscv_emit_binary(PLUS, dest, dest, cons);
+ return true;
+ }
+ /* imm + reg */
+ else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
+ && GET_CODE (alt) == REG)
+ {
+ /* Optimize for register value of 0. */
+ if (op0 == alt && op1 == const0_rtx)
+ {
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ cons = force_reg (mode, cons);
+ emit_insn (gen_rtx_SET (dest,
+ gen_rtx_IF_THEN_ELSE (mode, cond,
+ cons, alt)));
+ return true;
+ }
+ riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ rtx temp1 = gen_reg_rtx (mode);
+ rtx temp2 = GEN_INT(-1 * INTVAL (cons));
+ riscv_emit_binary(PLUS, temp1, alt, temp2);
+ emit_insn (gen_rtx_SET (dest,
+ gen_rtx_IF_THEN_ELSE (mode, cond,
+ const0_rtx, alt)));
+ riscv_emit_binary(PLUS, dest, dest, cons);
+ return true;
+ }
+ /* imm + 0 */
+ else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
+ && GET_CODE (alt) == CONST_INT && alt == const0_rtx)
+ {
+ riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ cons = force_reg (mode, cons);
+ emit_insn (gen_rtx_SET (dest,
+ gen_rtx_IF_THEN_ELSE (mode, cond,
+ cons, alt)));
+ return true;
+ }
+ /* reg + imm */
+ else if (GET_CODE (cons) == REG
+ && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
+ {
+ /* Optimize for register value of 0. */
+ if (op0 == cons && op1 == const0_rtx)
+ {
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ alt = force_reg (mode, alt);
+ emit_insn (gen_rtx_SET (dest,
+ gen_rtx_IF_THEN_ELSE (mode, cond,
+ cons, alt)));
+ return true;
+ }
+ riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ rtx temp1 = gen_reg_rtx (mode);
+ rtx temp2 = GEN_INT(-1 * INTVAL (alt));
+ riscv_emit_binary(PLUS, temp1, cons, temp2);
+ emit_insn (gen_rtx_SET (dest,
+ gen_rtx_IF_THEN_ELSE (mode, cond,
+ temp1, const0_rtx)));
+ riscv_emit_binary(PLUS, dest, dest, alt);
+ return true;
+ }
+ /* reg + reg */
+ else if (GET_CODE (cons) == REG && GET_CODE (alt) == REG)
+ {
+ rtx reg1 = gen_reg_rtx (mode);
+ rtx reg2 = gen_reg_rtx (mode);
+ riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
+ rtx cond1 = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ rtx cond2 = gen_rtx_fmt_ee (code == NE ? EQ : NE,
+ GET_MODE (op0), op0, op1);
+ emit_insn (gen_rtx_SET (reg2,
+ gen_rtx_IF_THEN_ELSE (mode, cond2,
+ const0_rtx, cons)));
+ emit_insn (gen_rtx_SET (reg1,
+ gen_rtx_IF_THEN_ELSE (mode, cond1,
+ const0_rtx, alt)));
+ riscv_emit_binary(IOR, dest, reg1, reg2);
+ return true;
+ }
+ }
return false;
}
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 6b8c2e8e268..b4147c7a79c 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2484,7 +2484,7 @@
(if_then_else:GPR (match_operand 1 "comparison_operator")
(match_operand:GPR 2 "reg_or_0_operand")
(match_operand:GPR 3 "sfb_alu_operand")))]
- "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV"
+ "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND"
{
if (riscv_expand_conditional_move (operands[0], operands[1],
operands[2], operands[3]))
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c
new file mode 100644
index 00000000000..4948558a187
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0"} } */
+
+long primitiveSemantics_return_0_imm_00(long a, long b) {
+ return a == 0 ? 0 : 3;
+}
+
+long primitiveSemantics_return_0_imm_01(long a, long b) {
+ return a != 0 ? 0 : 3;
+}
+
+long primitiveSemantics_return_0_imm_02(long a, long b) {
+ return a == 0 ? 3 : 0;
+}
+
+long primitiveSemantics_return_0_imm_03(long a, long b) {
+ return a != 0 ? 3 : 0;
+}
+
+long primitiveSemantics_return_0_imm_04(long a, long b) {
+ if (a)
+ b = 0;
+ else
+ b = 3;
+ return b;
+}
+
+long primitiveSemantics_return_0_imm_05(long a, long b) {
+ if (!a)
+ b = 0;
+ else
+ b = 3;
+ return b;
+}
+
+int primitiveSemantics_return_0_imm_06(int a, int b) { return a == 0 ? 0 : 3; }
+
+int primitiveSemantics_return_0_imm_07(int a, int b) { return a != 0 ? 0 : 3; }
+
+int primitiveSemantics_return_0_imm_08(int a, int b) { return a == 0 ? 3 : 0; }
+
+int primitiveSemantics_return_0_imm_09(int a, int b) { return a != 0 ? 3 : 0; }
+
+int primitiveSemantics_return_0_imm_10(int a, int b) {
+ if (a)
+ b = 0;
+ else
+ b = 3;
+ return b;
+}
+
+int primitiveSemantics_return_0_imm_11(int a, int b) {
+ if (!a)
+ b = 0;
+ else
+ b = 3;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c
new file mode 100644
index 00000000000..ebdca521373
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c
@@ -0,0 +1,73 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_return_imm_imm_00(long a, long b) {
+ return a == 0 ? 4 : 6;
+}
+
+long primitiveSemantics_return_imm_imm_01(long a, long b) {
+ return a != 0 ? 4 : 6;
+}
+
+long primitiveSemantics_return_imm_imm_02(long a, long b) {
+ return a == 0 ? 6 : 4;
+}
+
+long primitiveSemantics_return_imm_imm_03(long a, long b) {
+ return a != 0 ? 6 : 4;
+}
+
+long primitiveSemantics_return_imm_imm_04(long a, long b) {
+ if (a)
+ b = 4;
+ else
+ b = 6;
+ return b;
+}
+
+long primitiveSemantics_return_imm_imm_05(long a, long b) {
+ if (!a)
+ b = 4;
+ else
+ b = 6;
+ return b;
+}
+
+int primitiveSemantics_return_imm_imm_06(int a, int b) {
+ return a == 0 ? 4 : 6;
+}
+
+int primitiveSemantics_return_imm_imm_07(int a, int b) {
+ return a != 0 ? 4 : 6;
+}
+
+int primitiveSemantics_return_imm_imm_08(int a, int b) {
+ return a == 0 ? 6 : 4;
+}
+
+int primitiveSemantics_return_imm_imm_09(int a, int b) {
+ return a != 0 ? 6 : 4;
+}
+
+int primitiveSemantics_return_imm_imm_10(int a, int b) {
+ if (a)
+ b = 4;
+ else
+ b = 6;
+ return b;
+}
+
+int primitiveSemantics_return_imm_imm_11(int a, int b) {
+ if (!a)
+ b = 4;
+ else
+ b = 6;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c
new file mode 100644
index 00000000000..12c351dbc16
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_return_imm_reg_00(long a, long b) {
+ return a == 0 ? 1 : b;
+}
+
+long primitiveSemantics_return_imm_reg_01(long a, long b) {
+ return a != 0 ? 1 : b;
+}
+
+long primitiveSemantics_return_imm_reg_02(long a, long b) {
+ return a == 0 ? b : 1;
+}
+
+long primitiveSemantics_return_imm_reg_03(long a, long b) {
+ return a != 0 ? b : 1;
+}
+
+long primitiveSemantics_return_imm_reg_04(long a, long b) {
+ if (a)
+ b = 1;
+ return b;
+}
+
+long primitiveSemantics_return_imm_reg_05(long a, long b) {
+ if (!a)
+ b = 1;
+ return b;
+}
+
+int primitiveSemantics_return_imm_reg_06(int a, int b) {
+ return a == 0 ? 1 : b;
+}
+
+int primitiveSemantics_return_imm_reg_07(int a, int b) {
+ return a != 0 ? 1 : b;
+}
+
+int primitiveSemantics_return_imm_reg_08(int a, int b) {
+ return a == 0 ? b : 1;
+}
+
+int primitiveSemantics_return_imm_reg_09(int a, int b) {
+ return a != 0 ? b : 1;
+}
+
+int primitiveSemantics_return_imm_reg_10(int a, int b) {
+ if (a)
+ b = 1;
+ return b;
+}
+
+int primitiveSemantics_return_imm_reg_11(int a, int b) {
+ if (!a)
+ b = 1;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c
new file mode 100644
index 00000000000..4708afa645b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_return_reg_reg_00(long a, long b, long c) {
+ return a == 0 ? c : b;
+}
+
+long primitiveSemantics_return_reg_reg_01(long a, long b, long c) {
+ return a != 0 ? c : b;
+}
+
+long primitiveSemantics_return_reg_reg_02(long a, long b, long c) {
+ return a == 0 ? b : c;
+}
+
+long primitiveSemantics_return_reg_reg_03(long a, long b, long c) {
+ return a != 0 ? b : c;
+}
+
+long primitiveSemantics_return_reg_reg_04(long a, long b, long c) {
+ if (a)
+ b = c;
+ return b;
+}
+
+long primitiveSemantics_return_reg_reg_05(long a, long b, long c) {
+ if (!a)
+ b = c;
+ return b;
+}
+
+int primitiveSemantics_return_reg_reg_06(int a, int b, int c) {
+ return a == 0 ? c : b;
+}
+
+int primitiveSemantics_return_reg_reg_07(int a, int b, int c) {
+ return a != 0 ? c : b;
+}
+
+int primitiveSemantics_return_reg_reg_08(int a, int b, int c) {
+ return a == 0 ? b : c;
+}
+
+int primitiveSemantics_return_reg_reg_09(int a, int b, int c) {
+ return a != 0 ? b : c;
+}
+
+int primitiveSemantics_return_reg_reg_10(int a, int b, int c) {
+ if (a)
+ b = c;
+ return b;
+}
+
+int primitiveSemantics_return_reg_reg_11(int a, int b, int c) {
+ if (!a)
+ b = c;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 12 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 12 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
--
2.17.1
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH 4/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to non-zero
2023-07-19 10:11 [PATCH 0/5] Recognize Zicond extension Xiao Zeng
` (2 preceding siblings ...)
2023-07-19 10:11 ` [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 Xiao Zeng
@ 2023-07-19 10:11 ` Xiao Zeng
2023-08-07 17:36 ` Jeff Law
2023-07-19 10:11 ` [PATCH 5/5] [RISC-V] Generate Zicond instruction for conditional execution Xiao Zeng
2023-07-25 17:51 ` [PATCH 0/5] Recognize Zicond extension Jeff Law
5 siblings, 1 reply; 40+ messages in thread
From: Xiao Zeng @ 2023-07-19 10:11 UTC (permalink / raw)
To: gcc-patches
Cc: jeffreyalaw, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain, Xiao Zeng
This patch completes the recognition of Zicond when the select pattern with
condition eq or neq to non-zero (using equality as an example), namely:
1 rd = (rs2 == non-imm) ? 0 : rs1
2 rd = (rs2 == reg) ? 0 : rs1
At the same time, more Zicond non basic semantic test cases have been added.
gcc/ChangeLog:
* config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize Zicond.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/zicond-primitiveSemantics_compare_imm.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_0_imm.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_compare_reg.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_0_imm.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c: New test.
* gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c: New test.
---
gcc/config/riscv/riscv.cc | 16 ++++
.../zicond-primitiveSemantics_compare_imm.c | 57 ++++++++++++++
...mitiveSemantics_compare_imm_return_0_imm.c | 73 ++++++++++++++++++
...tiveSemantics_compare_imm_return_imm_imm.c | 73 ++++++++++++++++++
...tiveSemantics_compare_imm_return_imm_reg.c | 65 ++++++++++++++++
...tiveSemantics_compare_imm_return_reg_reg.c | 65 ++++++++++++++++
.../zicond-primitiveSemantics_compare_reg.c | 65 ++++++++++++++++
...mitiveSemantics_compare_reg_return_0_imm.c | 73 ++++++++++++++++++
...tiveSemantics_compare_reg_return_imm_imm.c | 73 ++++++++++++++++++
...tiveSemantics_compare_reg_return_imm_reg.c | 65 ++++++++++++++++
...tiveSemantics_compare_reg_return_reg_reg.c | 77 +++++++++++++++++++
11 files changed, 702 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_0_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_0_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 7e6b24bd232..9450457e613 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3625,6 +3625,22 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
riscv_emit_binary(IOR, dest, reg1, reg2);
return true;
}
+ /* For complex semantics of comparison value.
+ reg + 0 or 0 + reg */
+ else if ((GET_CODE (cons) == REG &&
+ GET_CODE (alt) == CONST_INT &&
+ alt == const0_rtx)
+ || (GET_CODE (alt) == REG &&
+ GET_CODE (cons) == CONST_INT &&
+ cons == const0_rtx))
+ {
+ riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
+ rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
+ emit_insn (gen_rtx_SET (dest,
+ gen_rtx_IF_THEN_ELSE (mode, cond,
+ cons, alt)));
+ return true;
+ }
}
return false;
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm.c
new file mode 100644
index 00000000000..6de50039c31
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm.c
@@ -0,0 +1,57 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0"} } */
+
+long primitiveSemantics_compare_imm_00(long a, long b) {
+ return a == 2 ? 0 : b;
+}
+
+long primitiveSemantics_compare_imm_01(long a, long b) {
+ return a != 2 ? 0 : b;
+}
+
+long primitiveSemantics_compare_imm_02(long a, long b) {
+ return a == 2 ? b : 0;
+}
+
+long primitiveSemantics_compare_imm_03(long a, long b) {
+ return a != 2 ? b : 0;
+}
+
+long primitiveSemantics_compare_imm_04(long a, long b) {
+ if (a == 2)
+ b = 0;
+ return b;
+}
+
+long primitiveSemantics_compare_imm_05(long a, long b) {
+ if (!(a == 2))
+ b = 0;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_06(int a, int b) { return a == 2 ? 0 : b; }
+
+int primitiveSemantics_compare_imm_07(int a, int b) { return a != 2 ? 0 : b; }
+
+int primitiveSemantics_compare_imm_08(int a, int b) { return a == 2 ? b : 0; }
+
+int primitiveSemantics_compare_imm_09(int a, int b) { return a != 2 ? b : 0; }
+
+int primitiveSemantics_compare_imm_10(int a, int b) {
+ if ((a == 2))
+ b = 0;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_11(int a, int b) {
+ if (!(a == 2))
+ b = 0;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_0_imm.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_0_imm.c
new file mode 100644
index 00000000000..b1e7359e802
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_0_imm.c
@@ -0,0 +1,73 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_compare_imm_return_0_imm_00(long a, long b) {
+ return a == 2 ? 0 : 5;
+}
+
+long primitiveSemantics_compare_imm_return_0_imm_01(long a, long b) {
+ return a != 2 ? 0 : 5;
+}
+
+long primitiveSemantics_compare_imm_return_0_imm_02(long a, long b) {
+ return a == 2 ? 5 : 0;
+}
+
+long primitiveSemantics_compare_imm_return_0_imm_03(long a, long b) {
+ return a != 2 ? 5 : 0;
+}
+
+long primitiveSemantics_compare_imm_return_0_imm_04(long a, long b) {
+ if (a == 2)
+ b = 0;
+ else
+ b = 5;
+ return b;
+}
+
+long primitiveSemantics_compare_imm_return_0_imm_05(long a, long b) {
+ if (!(a == 2))
+ b = 0;
+ else
+ b = 5;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_return_0_imm_06(int a, int b) {
+ return a == 2 ? 0 : 5;
+}
+
+int primitiveSemantics_compare_imm_return_0_imm_07(int a, int b) {
+ return a != 2 ? 0 : 5;
+}
+
+int primitiveSemantics_compare_imm_return_0_imm_08(int a, int b) {
+ return a == 2 ? 5 : 0;
+}
+
+int primitiveSemantics_compare_imm_return_0_imm_09(int a, int b) {
+ return a != 2 ? 5 : 0;
+}
+
+int primitiveSemantics_compare_imm_return_0_imm_10(int a, int b) {
+ if ((a == 2))
+ b = 0;
+ else
+ b = 5;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_return_0_imm_11(int a, int b) {
+ if (!(a == 2))
+ b = 0;
+ else
+ b = 5;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c
new file mode 100644
index 00000000000..bc503e6eafb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_imm.c
@@ -0,0 +1,73 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_compare_imm_return_imm_imm_00(long a, long b) {
+ return a == 2 ? 7 : 4;
+}
+
+long primitiveSemantics_compare_imm_return_imm_imm_01(long a, long b) {
+ return a != 2 ? 7 : 4;
+}
+
+long primitiveSemantics_compare_imm_return_imm_imm_02(long a, long b) {
+ return a == 2 ? 7 : 4;
+}
+
+long primitiveSemantics_compare_imm_return_imm_imm_03(long a, long b) {
+ return a != 2 ? 7 : 4;
+}
+
+long primitiveSemantics_compare_imm_return_imm_imm_04(long a, long b) {
+ if (a == 2)
+ b = 7;
+ else
+ b = 4;
+ return b;
+}
+
+long primitiveSemantics_compare_imm_return_imm_imm_05(long a, long b) {
+ if (!(a == 2))
+ b = 7;
+ else
+ b = 4;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_return_imm_imm_06(int a, int b) {
+ return a == 2 ? 7 : 4;
+}
+
+int primitiveSemantics_compare_imm_return_imm_imm_07(int a, int b) {
+ return a != 2 ? 7 : 4;
+}
+
+int primitiveSemantics_compare_imm_return_imm_imm_08(int a, int b) {
+ return a == 2 ? 7 : 4;
+}
+
+int primitiveSemantics_compare_imm_return_imm_imm_09(int a, int b) {
+ return a != 2 ? 7 : 4;
+}
+
+int primitiveSemantics_compare_imm_return_imm_imm_10(int a, int b) {
+ if ((a == 2))
+ b = 7;
+ else
+ b = 4;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_return_imm_imm_11(int a, int b) {
+ if (!(a == 2))
+ b = 7;
+ else
+ b = 4;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c
new file mode 100644
index 00000000000..2bcad7a51d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_imm_reg.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_compare_imm_return_imm_reg_00(long a, long b) {
+ return a == 2 ? 3 : b;
+}
+
+long primitiveSemantics_compare_imm_return_imm_reg_01(long a, long b) {
+ return a != 2 ? 3 : b;
+}
+
+long primitiveSemantics_compare_imm_return_imm_reg_02(long a, long b) {
+ return a == 2 ? b : 3;
+}
+
+long primitiveSemantics_compare_imm_return_imm_reg_03(long a, long b) {
+ return a != 2 ? b : 3;
+}
+
+long primitiveSemantics_compare_imm_return_imm_reg_04(long a, long b) {
+ if (a == 2)
+ b = 3;
+ return b;
+}
+
+long primitiveSemantics_compare_imm_return_imm_reg_05(long a, long b) {
+ if (!(a == 2))
+ b = 3;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_return_imm_reg_06(int a, int b) {
+ return a == 2 ? 3 : b;
+}
+
+int primitiveSemantics_compare_imm_return_imm_reg_07(int a, int b) {
+ return a != 2 ? 3 : b;
+}
+
+int primitiveSemantics_compare_imm_return_imm_reg_08(int a, int b) {
+ return a == 2 ? b : 3;
+}
+
+int primitiveSemantics_compare_imm_return_imm_reg_09(int a, int b) {
+ return a != 2 ? b : 3;
+}
+
+int primitiveSemantics_compare_imm_return_imm_reg_10(int a, int b) {
+ if ((a == 2))
+ b = 3;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_return_imm_reg_11(int a, int b) {
+ if (!(a == 2))
+ b = 3;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c
new file mode 100644
index 00000000000..e5d12992dc7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_imm_return_reg_reg.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_compare_imm_return_reg_reg_00(long a, long b, long c) {
+ return a == 2 ? c : b;
+}
+
+long primitiveSemantics_compare_imm_return_reg_reg_01(long a, long b, long c) {
+ return a != 2 ? c : b;
+}
+
+long primitiveSemantics_compare_imm_return_reg_reg_02(long a, long b, long c) {
+ return a == 2 ? b : c;
+}
+
+long primitiveSemantics_compare_imm_return_reg_reg_03(long a, long b, long c) {
+ return a != 2 ? b : c;
+}
+
+long primitiveSemantics_compare_imm_return_reg_reg_04(long a, long b, long c) {
+ if (a == 2)
+ b = c;
+ return b;
+}
+
+long primitiveSemantics_compare_imm_return_reg_reg_05(long a, long b, long c) {
+ if (!(a == 2))
+ b = c;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_return_reg_reg_06(int a, int b, int c) {
+ return a == 2 ? c : b;
+}
+
+int primitiveSemantics_compare_imm_return_reg_reg_07(int a, int b, int c) {
+ return a != 2 ? c : b;
+}
+
+int primitiveSemantics_compare_imm_return_reg_reg_08(int a, int b, int c) {
+ return a == 2 ? b : c;
+}
+
+int primitiveSemantics_compare_imm_return_reg_reg_09(int a, int b, int c) {
+ return a != 2 ? b : c;
+}
+
+int primitiveSemantics_compare_imm_return_reg_reg_10(int a, int b, int c) {
+ if ((a == 2))
+ b = c;
+ return b;
+}
+
+int primitiveSemantics_compare_imm_return_reg_reg_11(int a, int b, int c) {
+ if (!(a == 2))
+ b = c;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 12 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 12 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg.c
new file mode 100644
index 00000000000..072ae2a26ba
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0"} } */
+
+long primitiveSemantics_compare_reg_00(long a, long b, long c) {
+ return a == c ? 0 : b;
+}
+
+long primitiveSemantics_compare_reg_01(long a, long b, long c) {
+ return a != c ? 0 : b;
+}
+
+long primitiveSemantics_compare_reg_02(long a, long b, long c) {
+ return a == c ? b : 0;
+}
+
+long primitiveSemantics_compare_reg_03(long a, long b, long c) {
+ return a != c ? b : 0;
+}
+
+long primitiveSemantics_compare_reg_04(long a, long b, long c) {
+ if (a == c)
+ b = 0;
+ return b;
+}
+
+long primitiveSemantics_compare_reg_05(long a, long b, long c) {
+ if (!(a == c))
+ b = 0;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_06(int a, int b, int c) {
+ return a == c ? 0 : b;
+}
+
+int primitiveSemantics_compare_reg_07(int a, int b, int c) {
+ return a != c ? 0 : b;
+}
+
+int primitiveSemantics_compare_reg_08(int a, int b, int c) {
+ return a == c ? b : 0;
+}
+
+int primitiveSemantics_compare_reg_09(int a, int b, int c) {
+ return a != c ? b : 0;
+}
+
+int primitiveSemantics_compare_reg_10(int a, int b, int c) {
+ if ((a == c))
+ b = 0;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_11(int a, int b, int c) {
+ if (!(a == c))
+ b = 0;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_0_imm.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_0_imm.c
new file mode 100644
index 00000000000..66c7bcb9067
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_0_imm.c
@@ -0,0 +1,73 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_compare_reg_return_0_imm_00(long a, long b, long c) {
+ return a == c ? 0 : 9;
+}
+
+long primitiveSemantics_compare_reg_return_0_imm_01(long a, long b, long c) {
+ return a != c ? 0 : 9;
+}
+
+long primitiveSemantics_compare_reg_return_0_imm_02(long a, long b, long c) {
+ return a == c ? 9 : 0;
+}
+
+long primitiveSemantics_compare_reg_return_0_imm_03(long a, long b, long c) {
+ return a != c ? 9 : 0;
+}
+
+long primitiveSemantics_compare_reg_return_0_imm_04(long a, long b, long c) {
+ if (a == c)
+ b = 0;
+ else
+ b = 9;
+ return b;
+}
+
+long primitiveSemantics_compare_reg_return_0_imm_05(long a, long b, long c) {
+ if (!(a == c))
+ b = 0;
+ else
+ b = 9;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_return_0_imm_06(int a, int b, int c) {
+ return a == c ? 0 : 9;
+}
+
+int primitiveSemantics_compare_reg_return_0_imm_07(int a, int b, int c) {
+ return a != c ? 0 : 9;
+}
+
+int primitiveSemantics_compare_reg_return_0_imm_08(int a, int b, int c) {
+ return a == c ? 9 : 0;
+}
+
+int primitiveSemantics_compare_reg_return_0_imm_09(int a, int b, int c) {
+ return a != c ? 9 : 0;
+}
+
+int primitiveSemantics_compare_reg_return_0_imm_10(int a, int b, int c) {
+ if ((a == c))
+ b = 0;
+ else
+ b = 9;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_return_0_imm_11(int a, int b, int c) {
+ if (!(a == c))
+ b = 0;
+ else
+ b = 9;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c
new file mode 100644
index 00000000000..055ca4833e9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_imm.c
@@ -0,0 +1,73 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_compare_reg_return_imm_imm_00(long a, long b, long c) {
+ return a == c ? 7 : 4;
+}
+
+long primitiveSemantics_compare_reg_return_imm_imm_01(long a, long b, long c) {
+ return a != c ? 7 : 4;
+}
+
+long primitiveSemantics_compare_reg_return_imm_imm_02(long a, long b, long c) {
+ return a == c ? 7 : 4;
+}
+
+long primitiveSemantics_compare_reg_return_imm_imm_03(long a, long b, long c) {
+ return a != c ? 7 : 4;
+}
+
+long primitiveSemantics_compare_reg_return_imm_imm_04(long a, long b, long c) {
+ if (a == c)
+ b = 7;
+ else
+ b = 4;
+ return b;
+}
+
+long primitiveSemantics_compare_reg_return_imm_imm_05(long a, long b, long c) {
+ if (!(a == c))
+ b = 7;
+ else
+ b = 4;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_return_imm_imm_06(int a, int b, int c) {
+ return a == c ? 7 : 4;
+}
+
+int primitiveSemantics_compare_reg_return_imm_imm_07(int a, int b, int c) {
+ return a != c ? 7 : 4;
+}
+
+int primitiveSemantics_compare_reg_return_imm_imm_08(int a, int b, int c) {
+ return a == c ? 7 : 4;
+}
+
+int primitiveSemantics_compare_reg_return_imm_imm_09(int a, int b, int c) {
+ return a != c ? 7 : 4;
+}
+
+int primitiveSemantics_compare_reg_return_imm_imm_10(int a, int b, int c) {
+ if ((a == c))
+ b = 7;
+ else
+ b = 4;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_return_imm_imm_11(int a, int b, int c) {
+ if (!(a == c))
+ b = 7;
+ else
+ b = 4;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c
new file mode 100644
index 00000000000..85a68bd946f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_imm_reg.c
@@ -0,0 +1,65 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_compare_reg_return_imm_reg_00(long a, long b, long c) {
+ return a == c ? 10 : b;
+}
+
+long primitiveSemantics_compare_reg_return_imm_reg_01(long a, long b, long c) {
+ return a != c ? 10 : b;
+}
+
+long primitiveSemantics_compare_reg_return_imm_reg_02(long a, long b, long c) {
+ return a == c ? b : 10;
+}
+
+long primitiveSemantics_compare_reg_return_imm_reg_03(long a, long b, long c) {
+ return a != c ? b : 10;
+}
+
+long primitiveSemantics_compare_reg_return_imm_reg_04(long a, long b, long c) {
+ if (a == c)
+ b = 10;
+ return b;
+}
+
+long primitiveSemantics_compare_reg_return_imm_reg_05(long a, long b, long c) {
+ if (!(a == c))
+ b = 10;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_return_imm_reg_06(int a, int b, int c) {
+ return a == c ? 10 : b;
+}
+
+int primitiveSemantics_compare_reg_return_imm_reg_07(int a, int b, int c) {
+ return a != c ? 10 : b;
+}
+
+int primitiveSemantics_compare_reg_return_imm_reg_08(int a, int b, int c) {
+ return a == c ? b : 10;
+}
+
+int primitiveSemantics_compare_reg_return_imm_reg_09(int a, int b, int c) {
+ return a != c ? b : 10;
+}
+
+int primitiveSemantics_compare_reg_return_imm_reg_10(int a, int b, int c) {
+ if ((a == c))
+ b = 10;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_return_imm_reg_11(int a, int b, int c) {
+ if (!(a == c))
+ b = 10;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c
new file mode 100644
index 00000000000..d6d5d9e7bfa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_compare_reg_return_reg_reg.c
@@ -0,0 +1,77 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-Os"} } */
+
+long primitiveSemantics_compare_reg_return_reg_reg_00(long a, long b, long c,
+ long d) {
+ return a == c ? d : b;
+}
+
+long primitiveSemantics_compare_reg_return_reg_reg_01(long a, long b, long c,
+ long d) {
+ return a != c ? d : b;
+}
+
+long primitiveSemantics_compare_reg_return_reg_reg_02(long a, long b, long c,
+ long d) {
+ return a == c ? b : d;
+}
+
+long primitiveSemantics_compare_reg_return_reg_reg_03(long a, long b, long c,
+ long d) {
+ return a != c ? b : d;
+}
+
+long primitiveSemantics_compare_reg_return_reg_reg_04(long a, long b, long c,
+ long d) {
+ if (a == c)
+ b = d;
+ return b;
+}
+
+long primitiveSemantics_compare_reg_return_reg_reg_05(long a, long b, long c,
+ long d) {
+ if (!(a == c))
+ b = d;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_return_reg_reg_06(int a, int b, int c,
+ int d) {
+ return a == c ? d : b;
+}
+
+int primitiveSemantics_compare_reg_return_reg_reg_07(int a, int b, int c,
+ int d) {
+ return a != c ? d : b;
+}
+
+int primitiveSemantics_compare_reg_return_reg_reg_08(int a, int b, int c,
+ int d) {
+ return a == c ? b : d;
+}
+
+int primitiveSemantics_compare_reg_return_reg_reg_09(int a, int b, int c,
+ int d) {
+ return a != c ? b : d;
+}
+
+int primitiveSemantics_compare_reg_return_reg_reg_10(int a, int b, int c,
+ int d) {
+ if ((a == c))
+ b = d;
+ return b;
+}
+
+int primitiveSemantics_compare_reg_return_reg_reg_11(int a, int b, int c,
+ int d) {
+ if (!(a == c))
+ b = d;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 12 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 12 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
--
2.17.1
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH 5/5] [RISC-V] Generate Zicond instruction for conditional execution
2023-07-19 10:11 [PATCH 0/5] Recognize Zicond extension Xiao Zeng
` (3 preceding siblings ...)
2023-07-19 10:11 ` [PATCH 4/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to non-zero Xiao Zeng
@ 2023-07-19 10:11 ` Xiao Zeng
2023-07-25 17:51 ` [PATCH 0/5] Recognize Zicond extension Jeff Law
5 siblings, 0 replies; 40+ messages in thread
From: Xiao Zeng @ 2023-07-19 10:11 UTC (permalink / raw)
To: gcc-patches
Cc: jeffreyalaw, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain, Xiao Zeng
This patch completes the recognition of conditional execution
(using equality as an example), namely:
1 rd = (rc == 0) ? (rs1 arith_op rs2) : rs1
Here, arith_op represents the arithmetic operation symbol, which has 8
possibilities: + - | ^ << >>(Shift Right Arithmetic) >>(Shift Right Logical) &
At the same time, more Zicond non basic conditional execution test cases have
also been added, namely:
2 rd = (rc == 0) ? (rs1 arith_op non-imm) : rs1
3 rd = (rc == non-imm) ? (rs1 arith_op rs2) : rs1
4 rd = (rc == non-imm) ? (rs1 arith_op non-imm) : rs1
5 rd = (rc == reg) ? (rs1 arith_op rs2) : rs1
6 rd = (rc == reg) ? (rs1 arith_op non-imm) : rs1
gcc/ChangeLog:
* ifcvt.cc (noce_emit_condzero_arith): Helper function for noce_emit_condzero_arith.
(noce_try_condzero_arith): Recognize Zicond patterns.
(noce_process_if_block): Add noce_try_condzero_arith function.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_imm_reg.c: New test.
* gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_reg_reg.c: New test.
* gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_imm_reg.c: New test.
* gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_reg_reg.c: New test.
* gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_imm_reg.c: New test.
* gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_reg_reg.c: New test.
---
gcc/ifcvt.cc | 251 ++++++++
...ionalArithmetic_compare_0_return_imm_reg.c | 553 +++++++++++++++++
...ionalArithmetic_compare_0_return_reg_reg.c | 585 ++++++++++++++++++
...nalArithmetic_compare_imm_return_imm_reg.c | 297 +++++++++
...nalArithmetic_compare_imm_return_reg_reg.c | 297 +++++++++
...nalArithmetic_compare_reg_return_imm_reg.c | 297 +++++++++
...nalArithmetic_compare_reg_return_reg_reg.c | 329 ++++++++++
7 files changed, 2609 insertions(+)
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_reg_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_reg_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_imm_reg.c
create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_reg_reg.c
diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 0b180b4568f..0261d2f1673 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -781,12 +781,15 @@ static int noce_try_store_flag_constants (struct noce_if_info *);
static int noce_try_store_flag_mask (struct noce_if_info *);
static rtx noce_emit_cmove (struct noce_if_info *, rtx, enum rtx_code, rtx,
rtx, rtx, rtx, rtx = NULL, rtx = NULL);
+static rtx noce_emit_condzero_arith (struct noce_if_info *, rtx, enum rtx_code, rtx,
+ rtx, rtx, rtx);
static int noce_try_cmove (struct noce_if_info *);
static int noce_try_cmove_arith (struct noce_if_info *);
static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx_insn **);
static int noce_try_minmax (struct noce_if_info *);
static int noce_try_abs (struct noce_if_info *);
static int noce_try_sign_mask (struct noce_if_info *);
+static int noce_try_condzero_arith (struct noce_if_info *);
/* Return the comparison code for reversed condition for IF_INFO,
or UNKNOWN if reversing the condition is not possible. */
@@ -1830,6 +1833,60 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
return NULL_RTX;
}
+/* Helper function for noce_emit_condzero_arith. */
+
+static rtx
+noce_emit_condzero_arith (struct noce_if_info *if_info, rtx x, enum rtx_code code,
+ rtx cmp_a, rtx cmp_b, rtx vfalse, rtx vtrue)
+{
+ rtx cond = NULL;
+
+ /* Standard form of conditional comparison. */
+ if (GET_CODE(cmp_a) == REG && cmp_b == const0_rtx)
+ cond = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), cmp_a, cmp_b);
+
+ /* Register and non-zero immediate comparison. */
+ else if (GET_CODE(cmp_a) == REG && GET_CODE(cmp_b) == CONST_INT &&
+ cmp_b != const0_rtx)
+ {
+ rtx temp1 = gen_reg_rtx (GET_MODE(cmp_a));
+ rtx temp2 = GEN_INT(-1 * INTVAL (cmp_b));
+ rtx src = gen_rtx_fmt_ee (PLUS, GET_MODE (cmp_a), cmp_a, temp2);
+ emit_insn (gen_rtx_SET (temp1, src));
+ cond = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), temp1, const0_rtx);
+ }
+
+ /* Register and Register comparison. */
+ else if (GET_CODE(cmp_a) == REG && GET_CODE(cmp_b) == REG)
+ {
+ rtx temp1 = gen_reg_rtx (GET_MODE(cmp_a));
+ rtx src = gen_rtx_fmt_ee (MINUS, GET_MODE (cmp_a), cmp_a, cmp_b);
+ emit_insn (gen_rtx_SET (temp1, src));
+ cond = gen_rtx_fmt_ee (code, GET_MODE (if_info->cond), temp1, const0_rtx);
+ }
+ else
+ return NULL_RTX;
+
+ rtx if_then_else = gen_rtx_IF_THEN_ELSE (GET_MODE (x), cond, vtrue, vfalse);
+ rtx set = gen_rtx_SET (x, if_then_else);
+
+ start_sequence ();
+ rtx_insn *insn = emit_insn (set);
+
+ if (recog_memoized (insn) >= 0)
+ {
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+ emit_insn (seq);
+
+ return x;
+ }
+
+ end_sequence ();
+
+ return NULL_RTX;
+}
+
/* Try only simple constants and registers here. More complex cases
are handled in noce_try_cmove_arith after noce_try_store_flag_arith
has had a go at it. */
@@ -2879,6 +2936,197 @@ noce_try_sign_mask (struct noce_if_info *if_info)
return TRUE;
}
+/* Convert "if (cond) x = x arith_code y; return x;" to a branchless
+ sequence using the canonical form for a conditional-zero. */
+
+static int
+noce_try_condzero_arith (struct noce_if_info *if_info)
+{
+ rtx target;
+ rtx_insn *seq;
+
+ rtx first_pattern = NULL;
+ rtx last_pattern = NULL;
+ rtx else_pattern = NULL;
+ rtx *arith, *ref_arith_op0, *ref_arith_op1;
+ rtx arith_op0, arith_op1;
+ rtx_code arith_code;
+ rtx_code cond_code = GET_CODE (if_info->cond);
+
+ machine_mode arith_mode = GET_MODE (if_info->a);
+ machine_mode cmp_mode = GET_MODE (XEXP(if_info->cond, 0));
+ if (GET_MODE_CLASS (arith_mode) != MODE_INT ||
+ GET_MODE_CLASS (cmp_mode) != MODE_INT)
+ return FALSE;
+
+ /* we shall create new pseudos. */
+ if (reload_completed)
+ return FALSE;
+
+ /* Check for cond_code. */
+ if (cond_code != EQ && cond_code != NE)
+ return FALSE;
+
+ /* Check for else_bb. */
+ if (if_info->else_bb &&
+ !(count_bb_insns(if_info->else_bb) == 1 &&
+ !JUMP_P (BB_END (if_info->then_bb)) &&
+ (else_pattern = single_set (first_active_insn (if_info->else_bb))) &&
+ GET_CODE (else_pattern) == SET &&
+ rtx_equal_p (if_info->x, XEXP(else_pattern, 0))))
+ return FALSE;
+
+ /* count_bb_insns ignores JUMP_INSN. */
+ if (JUMP_P (BB_END (if_info->then_bb)))
+ return FALSE;
+
+ if (count_bb_insns(if_info->then_bb) > 2)
+ return FALSE;
+
+ /* Optimize for sign-extension. */
+ if (count_bb_insns(if_info->then_bb) == 2)
+ {
+ last_pattern = copy_rtx (PATTERN (last_active_insn (if_info->then_bb,
+ FALSE)));
+ /* Just processing SET insn, not including other situations
+ in the single_set function. */
+ if (GET_CODE (last_pattern) != SET)
+ return FALSE;
+
+ rtx_code last_code = GET_CODE (XEXP (last_pattern, 1));
+
+ if (last_code != SIGN_EXTEND && last_code != REG)
+ return FALSE;
+ }
+
+ first_pattern = copy_rtx (PATTERN (first_active_insn (if_info->then_bb)));
+ if (GET_CODE (first_pattern) != SET)
+ return FALSE;
+
+ arith = &XEXP (first_pattern, 1);
+ arith_code = GET_CODE (*arith);
+
+ if (arith_code == SIGN_EXTEND)
+ {
+ arith = &XEXP (*arith, 0);
+ arith_code = GET_CODE (*arith);
+ }
+ /* When shift right logical a non-zero immediate to unsigned integer,
+ zero_extend and sign_extend are equal.
+ In risc-v, using zero_extend to represent shift right logical is
+ a non-canonical form, as shown in riscv.md. */
+ else if (arith_code == ZERO_EXTEND)
+ {
+ rtx *temp = arith;
+ arith = &XEXP (*arith, 0);
+ arith_code = GET_CODE (*arith);
+ if (arith_code != LSHIFTRT)
+ return FALSE;
+ /* Modify the code to sign_extend for easy subsequent recognition. */
+ PUT_CODE(*temp, SIGN_EXTEND);
+ }
+
+ if (arith_code != PLUS && arith_code != MINUS && arith_code != IOR &&
+ arith_code != XOR && arith_code != AND && arith_code != ASHIFTRT &&
+ arith_code != LSHIFTRT && arith_code != ASHIFT)
+ return FALSE;
+
+ /* Obtain the arithmetic calculation components: arith_op0 and arith_op1. */
+ arith_op0 = XEXP (*arith, 0);
+ arith_op1 = XEXP (*arith, 1);
+ ref_arith_op0 = &XEXP (*arith, 0);
+ ref_arith_op1 = &XEXP (*arith, 1);
+
+ if (GET_CODE (arith_op0) == SUBREG)
+ arith_op0 = SUBREG_REG(arith_op0);
+ if (GET_CODE (arith_op1) == SUBREG)
+ arith_op1 = SUBREG_REG(arith_op1);
+
+ /* The arithmetic calculation pattern that can only be processed
+ in insn pattern are as follows:
+ (set (reg/v:DI 137 [ rs1 ])
+ (ashiftrt:DI (reg/v:DI 137 [ rs1 ])
+ (subreg:QI (reg/v:DI 138 [ rs2 ]) 0))) */
+ if (!else_pattern && !rtx_equal_p (if_info->x, arith_op0))
+ return FALSE;
+
+ /* If else_bb is not empty. */
+ if (else_pattern && !rtx_equal_p (if_info->x, XEXP(first_pattern, 0)) &&
+ !rtx_equal_p (arith_op0, XEXP(else_pattern, 1)))
+ return FALSE;
+
+ start_sequence ();
+
+ if (arith_code == AND)
+ {
+ rtx reg1 = gen_reg_rtx (arith_mode);
+ rtx temp = gen_rtx_fmt_ee (arith_code, arith_mode, arith_op0, arith_op1);
+ emit_insn (gen_rtx_SET (reg1, temp));
+
+ rtx reg2 = gen_reg_rtx (arith_mode);
+ target = noce_emit_condzero_arith (if_info, reg2, cond_code,
+ XEXP (if_info->cond, 0),
+ XEXP (if_info->cond, 1),
+ const0_rtx, arith_op0);
+ if (!target)
+ {
+ end_sequence ();
+ return FALSE;
+ }
+ rtx ior = gen_rtx_fmt_ee (IOR, arith_mode, reg1, target);
+ emit_insn (gen_rtx_SET (if_info->x, ior));
+ }
+ else
+ {
+ /* In CONST_INT case, force arith_op1 to register. */
+ if (GET_CODE(arith_op1) == CONST_INT)
+ {
+ rtx reg = gen_reg_rtx (arith_mode);
+ emit_insn (gen_rtx_SET (reg, arith_op1));
+ arith_op1 = reg;
+ }
+
+ /* Apply for a reg as the return register for condezero. */
+ rtx reg = gen_reg_rtx (arith_mode);
+ target = noce_emit_condzero_arith (if_info, reg, cond_code,
+ XEXP (if_info->cond, 0),
+ XEXP (if_info->cond, 1),
+ arith_op1, const0_rtx);
+ if (!target)
+ {
+ end_sequence ();
+ return FALSE;
+ }
+
+ /* Update arithmetic operand in first_pattern. */
+
+ /* Shift a register. */
+ if (arith_code == ASHIFT || arith_code == ASHIFTRT ||
+ arith_code == LSHIFTRT)
+ *ref_arith_op1 = gen_rtx_SUBREG (E_QImode, target, 0);
+ else if (GET_CODE (*ref_arith_op0) == SUBREG)
+ *ref_arith_op1 = gen_rtx_SUBREG (GET_MODE (*ref_arith_op0), target, 0);
+ else
+ *ref_arith_op1 = target;
+
+ emit_insn (first_pattern);
+
+ /* Adding last_pattern to the insn chain. */
+ if (last_pattern)
+ emit_insn (last_pattern);
+ }
+
+ seq = end_ifcvt_sequence (if_info);
+
+ if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
+ return FALSE;
+
+ emit_insn_before_setloc (seq, if_info->jump,
+ INSN_LOCATION (if_info->insn_a));
+ if_info->transform_name = "noce_try_condzero_arith";
+
+ return TRUE;
+}
/* Optimize away "if (x & C) x |= C" and similar bit manipulation
transformations. */
@@ -3973,6 +4221,9 @@ noce_process_if_block (struct noce_if_info *if_info)
goto success;
if (noce_try_store_flag_mask (if_info))
goto success;
+ if (HAVE_conditional_move
+ && noce_try_condzero_arith(if_info))
+ goto success;
if (HAVE_conditional_move
&& noce_try_cmove_arith (if_info))
goto success;
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_imm_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_imm_reg.c
new file mode 100644
index 00000000000..282e8a8e492
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_imm_reg.c
@@ -0,0 +1,553 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os"} } */
+
+long conditionalArithmetic_compare_0_return_imm_reg_00(long rd, long rs1,
+ long rc) {
+ if (rc == 0)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_01(long rd, long rs1,
+ long rc) {
+ if (rc != 0)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_02(long rd, long rs1,
+ long rc) {
+ if (rc)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_03(long rd, long rs1,
+ long rc) {
+ if (!rc)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_04(long rd, long rs1,
+ long rc) {
+ if (rc == 0)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_05(long rd, long rs1,
+ long rc) {
+ if (rc != 0)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_06(long rd, long rs1,
+ long rc) {
+ if (rc)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_07(long rd, long rs1,
+ long rc) {
+ if (!rc)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_08(long rd, long rs1,
+ long rc) {
+ if (rc == 0)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_09(long rd, long rs1,
+ long rc) {
+ if (rc != 0)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_10(long rd, long rs1,
+ long rc) {
+ if (rc)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_11(long rd, long rs1,
+ long rc) {
+ if (!rc)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_12(long rd, long rs1,
+ long rc) {
+ if (rc == 0)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_13(long rd, long rs1,
+ long rc) {
+ if (rc != 0)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_14(long rd, long rs1,
+ long rc) {
+ if (rc)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_15(long rd, long rs1,
+ long rc) {
+ if (!rc)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_16(long rd, long rs1,
+ long rc) {
+ if (rc == 0)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_17(long rd, long rs1,
+ long rc) {
+ if (rc != 0)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_18(long rd, long rs1,
+ long rc) {
+ if (rc)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_19(long rd, long rs1,
+ long rc) {
+ if (!rc)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_20(long rd, long rs1,
+ long rc) {
+ if (rc == 0)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_21(long rd, long rs1,
+ long rc) {
+ if (rc != 0)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_22(long rd, long rs1,
+ long rc) {
+ if (rc)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_23(long rd, long rs1,
+ long rc) {
+ if (!rc)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_24(long rd, long rs1,
+ long rc) {
+ if (rc == 0)
+ rd = ((unsigned long)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_25(long rd, long rs1,
+ long rc) {
+ if (rc != 0)
+ rd = ((unsigned long)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_26(long rd, long rs1,
+ long rc) {
+ if (rc)
+ rd = ((unsigned long)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_27(long rd, long rs1,
+ long rc) {
+ if (!rc)
+ rd = ((unsigned long)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_28(long rd, long rs1,
+ long rc) {
+ if (rc == 0)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_29(long rd, long rs1,
+ long rc) {
+ if (rc != 0)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_30(long rd, long rs1,
+ long rc) {
+ if (rc)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_imm_reg_31(long rd, long rs1,
+ long rc) {
+ if (!rc)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_32(int rd, int rs1, int rc) {
+ if (rc == 0)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_33(int rd, int rs1, int rc) {
+ if (rc != 0)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_34(int rd, int rs1, int rc) {
+ if (rc)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_35(int rd, int rs1, int rc) {
+ if (!rc)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_36(int rd, int rs1, int rc) {
+ if (rc == 0)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_37(int rd, int rs1, int rc) {
+ if (rc != 0)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_38(int rd, int rs1, int rc) {
+ if (rc)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_39(int rd, int rs1, int rc) {
+ if (!rc)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_40(int rd, int rs1, int rc) {
+ if (rc == 0)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_41(int rd, int rs1, int rc) {
+ if (rc != 0)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_42(int rd, int rs1, int rc) {
+ if (rc)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_43(int rd, int rs1, int rc) {
+ if (!rc)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_44(int rd, int rs1, int rc) {
+ if (rc == 0)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_45(int rd, int rs1, int rc) {
+ if (rc != 0)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_46(int rd, int rs1, int rc) {
+ if (rc)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_47(int rd, int rs1, int rc) {
+ if (!rc)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_48(int rd, int rs1, int rc) {
+ if (rc == 0)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_49(int rd, int rs1, int rc) {
+ if (rc != 0)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_50(int rd, int rs1, int rc) {
+ if (rc)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_51(int rd, int rs1, int rc) {
+ if (!rc)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_52(int rd, int rs1, int rc) {
+ if (rc == 0)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_53(int rd, int rs1, int rc) {
+ if (rc != 0)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_54(int rd, int rs1, int rc) {
+ if (rc)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_55(int rd, int rs1, int rc) {
+ if (!rc)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_56(int rd, int rs1, int rc) {
+ if (rc == 0)
+ rd = ((unsigned int)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_57(int rd, int rs1, int rc) {
+ if (rc != 0)
+ rd = ((unsigned int)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_58(int rd, int rs1, int rc) {
+ if (rc)
+ rd = ((unsigned int)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_59(int rd, int rs1, int rc) {
+ if (!rc)
+ rd = ((unsigned int)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_60(int rd, int rs1, int rc) {
+ if (rc == 0)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_61(int rd, int rs1, int rc) {
+ if (rc != 0)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_62(int rd, int rs1, int rc) {
+ if (rc)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_imm_reg_63(int rd, int rs1, int rc) {
+ if (!rc)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 32 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 32 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_reg_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_reg_reg.c
new file mode 100644
index 00000000000..15efcf538e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_0_return_reg_reg.c
@@ -0,0 +1,585 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os"} } */
+
+long conditionalArithmetic_compare_0_return_reg_reg_00(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 0)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_01(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 0)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_02(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_03(long rd, long rs1,
+ long rs2, long rc) {
+ if (!rc)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_04(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 0)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_05(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 0)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_06(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_07(long rd, long rs1,
+ long rs2, long rc) {
+ if (!rc)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_08(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 0)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_09(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 0)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_10(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_11(long rd, long rs1,
+ long rs2, long rc) {
+ if (!rc)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_12(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 0)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_13(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 0)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_14(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_15(long rd, long rs1,
+ long rs2, long rc) {
+ if (!rc)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_16(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 0)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_17(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 0)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_18(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_19(long rd, long rs1,
+ long rs2, long rc) {
+ if (!rc)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_20(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 0)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_21(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 0)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_22(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_23(long rd, long rs1,
+ long rs2, long rc) {
+ if (!rc)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_24(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 0)
+ rd = ((unsigned long)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_25(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 0)
+ rd = ((unsigned long)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_26(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc)
+ rd = ((unsigned long)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_27(long rd, long rs1,
+ long rs2, long rc) {
+ if (!rc)
+ rd = ((unsigned long)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_28(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 0)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_29(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 0)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_30(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_0_return_reg_reg_31(long rd, long rs1,
+ long rs2, long rc) {
+ if (!rc)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_32(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc == 0)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_33(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc != 0)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_34(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_35(int rd, int rs1, int rs2,
+ int rc) {
+ if (!rc)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_36(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc == 0)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_37(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc != 0)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_38(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_39(int rd, int rs1, int rs2,
+ int rc) {
+ if (!rc)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_40(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc == 0)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_41(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc != 0)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_42(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_43(int rd, int rs1, int rs2,
+ int rc) {
+ if (!rc)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_44(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc == 0)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_45(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc != 0)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_46(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_47(int rd, int rs1, int rs2,
+ int rc) {
+ if (!rc)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_48(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc == 0)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_49(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc != 0)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_50(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_51(int rd, int rs1, int rs2,
+ int rc) {
+ if (!rc)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_52(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc == 0)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_53(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc != 0)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_54(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_55(int rd, int rs1, int rs2,
+ int rc) {
+ if (!rc)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_56(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc == 0)
+ rd = ((unsigned int)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_57(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc != 0)
+ rd = ((unsigned int)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_58(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc)
+ rd = ((unsigned int)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_59(int rd, int rs1, int rs2,
+ int rc) {
+ if (!rc)
+ rd = ((unsigned int)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_60(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc == 0)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_61(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc != 0)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_62(int rd, int rs1, int rs2,
+ int rc) {
+ if (rc)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_0_return_reg_reg_63(int rd, int rs1, int rs2,
+ int rc) {
+ if (!rc)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 32 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 32 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_imm_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_imm_reg.c
new file mode 100644
index 00000000000..6647640acf8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_imm_reg.c
@@ -0,0 +1,297 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os"} } */
+
+long conditionalArithmetic_compare_imm_return_imm_reg_00(long rd, long rs1,
+ long rc) {
+ if (rc == 10)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_01(long rd, long rs1,
+ long rc) {
+ if (rc != 10)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_02(long rd, long rs1,
+ long rc) {
+ if (rc == 10)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_03(long rd, long rs1,
+ long rc) {
+ if (rc != 10)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_04(long rd, long rs1,
+ long rc) {
+ if (rc == 10)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_05(long rd, long rs1,
+ long rc) {
+ if (rc != 10)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_06(long rd, long rs1,
+ long rc) {
+ if (rc == 10)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_07(long rd, long rs1,
+ long rc) {
+ if (rc != 10)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_08(long rd, long rs1,
+ long rc) {
+ if (rc == 10)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_09(long rd, long rs1,
+ long rc) {
+ if (rc != 10)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_10(long rd, long rs1,
+ long rc) {
+ if (rc == 10)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_11(long rd, long rs1,
+ long rc) {
+ if (rc != 10)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_12(long rd, long rs1,
+ long rc) {
+ if (rc == 10)
+ rd = ((unsigned long)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_13(long rd, long rs1,
+ long rc) {
+ if (rc != 10)
+ rd = ((unsigned long)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_14(long rd, long rs1,
+ long rc) {
+ if (rc == 10)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_imm_reg_15(long rd, long rs1,
+ long rc) {
+ if (rc != 10)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_16(int rd, int rs1,
+ int rc) {
+ if (rc == 10)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_17(int rd, int rs1,
+ int rc) {
+ if (rc != 10)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_18(int rd, int rs1,
+ int rc) {
+ if (rc == 10)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_19(int rd, int rs1,
+ int rc) {
+ if (rc != 10)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_20(int rd, int rs1,
+ int rc) {
+ if (rc == 10)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_21(int rd, int rs1,
+ int rc) {
+ if (rc != 10)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_22(int rd, int rs1,
+ int rc) {
+ if (rc == 10)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_23(int rd, int rs1,
+ int rc) {
+ if (rc != 10)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_24(int rd, int rs1,
+ int rc) {
+ if (rc == 10)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_25(int rd, int rs1,
+ int rc) {
+ if (rc != 10)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_26(int rd, int rs1,
+ int rc) {
+ if (rc == 10)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_27(int rd, int rs1,
+ int rc) {
+ if (rc != 10)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_28(int rd, int rs1,
+ int rc) {
+ if (rc == 10)
+ rd = ((unsigned int)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_29(int rd, int rs1,
+ int rc) {
+ if (rc != 10)
+ rd = ((unsigned int)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_30(int rd, int rs1,
+ int rc) {
+ if (rc == 10)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_imm_reg_31(int rd, int rs1,
+ int rc) {
+ if (rc != 10)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 16 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 16 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_reg_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_reg_reg.c
new file mode 100644
index 00000000000..859639c1676
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_imm_return_reg_reg.c
@@ -0,0 +1,297 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os"} } */
+
+long conditionalArithmetic_compare_imm_return_reg_reg_00(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 10)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_01(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 10)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_02(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 10)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_03(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 10)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_04(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 10)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_05(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 10)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_06(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 10)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_07(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 10)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_08(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 10)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_09(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 10)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_10(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 10)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_11(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 10)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_12(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 10)
+ rd = ((unsigned long)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_13(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 10)
+ rd = ((unsigned long)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_14(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc == 10)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_imm_return_reg_reg_15(long rd, long rs1,
+ long rs2, long rc) {
+ if (rc != 10)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_16(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc == 10)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_17(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc != 10)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_18(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc == 10)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_19(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc != 10)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_20(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc == 10)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_21(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc != 10)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_22(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc == 10)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_23(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc != 10)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_24(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc == 10)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_25(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc != 10)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_26(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc == 10)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_27(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc != 10)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_28(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc == 10)
+ rd = ((unsigned int)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_29(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc != 10)
+ rd = ((unsigned int)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_30(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc == 10)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_imm_return_reg_reg_31(int rd, int rs1,
+ int rs2, int rc) {
+ if (rc != 10)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 16 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 16 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_imm_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_imm_reg.c
new file mode 100644
index 00000000000..7affe1d9baa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_imm_reg.c
@@ -0,0 +1,297 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os"} } */
+
+long conditionalArithmetic_compare_reg_return_imm_reg_00(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_01(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_02(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_03(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_04(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_05(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_06(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_07(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_08(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_09(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_10(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_11(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_12(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 == rc2)
+ rd = ((unsigned long)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_13(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 != rc2)
+ rd = ((unsigned long)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_14(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_imm_reg_15(long rd, long rs1,
+ long rc1, long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_16(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_17(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 + 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_18(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_19(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 - 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_20(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_21(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 | 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_22(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_23(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 ^ 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_24(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_25(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 << 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_26(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_27(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_28(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 == rc2)
+ rd = ((unsigned int)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_29(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 != rc2)
+ rd = ((unsigned int)rs1) >> 2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_30(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_imm_reg_31(int rd, int rs1,
+ int rc1, int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 & 20;
+ else
+ rd = rs1;
+ return rd;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 16 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 16 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_reg_reg.c b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_reg_reg.c
new file mode 100644
index 00000000000..8b0959e534b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-conditionalArithmetic_compare_reg_return_reg_reg.c
@@ -0,0 +1,329 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os"} } */
+
+long conditionalArithmetic_compare_reg_return_reg_reg_00(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_01(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_02(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_03(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_04(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_05(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_06(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_07(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_08(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_09(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_10(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_11(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_12(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 == rc2)
+ rd = ((unsigned long)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_13(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 != rc2)
+ rd = ((unsigned long)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_14(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 == rc2)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+long conditionalArithmetic_compare_reg_return_reg_reg_15(long rd, long rs1,
+ long rs2, long rc1,
+ long rc2) {
+ if (rc1 != rc2)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_16(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_17(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 + rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_18(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_19(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 - rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_20(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_21(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 | rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_22(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_23(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 ^ rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_24(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_25(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 << rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_26(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_27(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_28(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 == rc2)
+ rd = ((unsigned int)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_29(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 != rc2)
+ rd = ((unsigned int)rs1) >> rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_30(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 == rc2)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+int conditionalArithmetic_compare_reg_return_reg_reg_31(int rd, int rs1,
+ int rs2, int rc1,
+ int rc2) {
+ if (rc1 != rc2)
+ rd = rs1 & rs2;
+ else
+ rd = rs1;
+ return rd;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 16 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 16 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
--
2.17.1
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics
2023-07-19 10:11 ` [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics Xiao Zeng
@ 2023-07-25 16:35 ` Jeff Law
2023-07-26 17:53 ` Jeff Law
2023-07-26 21:14 ` Jeff Law
2 siblings, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-07-25 16:35 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/19/23 04:11, Xiao Zeng wrote:
> This patch completes the recognition of the basic semantics
> defined in the spec, namely:
>
> Conditional zero, if condition is equal to zero
> rd = (rs2 == 0) ? 0 : rs1
> Conditional zero, if condition is non zero
> rd = (rs2 != 0) ? 0 : rs1
>
> gcc/ChangeLog:
>
> * config/riscv/riscv.md: Include zicond.md
> * config/riscv/zicond.md: New file.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/riscv/zicond-primitiveSemantics.c: New test.
> ---
> gcc/config/riscv/riscv.md | 1 +
> gcc/config/riscv/zicond.md | 84 +++++++++++++++++++
> .../riscv/zicond-primitiveSemantics.c | 49 +++++++++++
> 3 files changed, 134 insertions(+)
> create mode 100644 gcc/config/riscv/zicond.md
> create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics.c
>
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index d63b584a4c1..6b8c2e8e268 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -3317,3 +3317,4 @@
> (include "sifive-7.md")
> (include "thead.md")
> (include "vector.md")
> +(include "zicond.md")
> diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md
> new file mode 100644
> index 00000000000..1cf28589c87
> --- /dev/null
> +++ b/gcc/config/riscv/zicond.md
> @@ -0,0 +1,84 @@
> +;; Machine description for the RISC-V Zicond extension
> +;; Copyright (C) 2022-23 Free Software Foundation, Inc.
> +
> +;; This file is part of GCC.
> +
> +;; GCC is free software; you can redistribute it and/or modify
> +;; it under the terms of the GNU General Public License as published by
> +;; the Free Software Foundation; either version 3, or (at your option)
> +;; any later version.
> +
> +;; GCC is distributed in the hope that it will be useful,
> +;; but WITHOUT ANY WARRANTY; without even the implied warranty of
> +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +;; GNU General Public License for more details.
> +
> +;; You should have received a copy of the GNU General Public License
> +;; along with GCC; see the file COPYING3. If not see
> +;; <http://www.gnu.org/licenses/>.
> +
> +(define_code_iterator eq_or_ne [eq ne])
> +(define_code_attr eqz [(eq "nez") (ne "eqz")])
> +(define_code_attr nez [(eq "eqz") (ne "nez")])
> +
> +
> +;; Special optimization under eq/ne in primitive semantics
> +(define_insn "*czero.eqz.<GPR:mode><ANYI:mode>.opt1"
> + [(set (match_operand:GPR 0 "register_operand" "=r")
> + (if_then_else:GPR (eq (match_operand:ANYI 1 "register_operand" "r")
> + (const_int 0))
> + (match_operand:GPR 2 "register_operand" "1")
> + (match_operand:GPR 3 "register_operand" "r")))]
> + "TARGET_ZICOND && operands[1] == operands[2]"
> + "czero.eqz\t%0,%3,%1"
Interesting. We didn't have this pattern internally, though it's
clever. I'm curious how often it triggered.
Why did you need the operands[1] == operands[2] condition. I would
hazard a guess the idea was to reject cases that weren't going to be
profitable if LRA/reload needed to insert copies to satisfy the matching
constraint?
It may have been better to replace operand 2 with (match_dup 1). If
that isn't viable, then the right check in the condition would have been
REGNO (operands[1]) == REGNO (operands[2]).
You need to be very careful comparing REG expressions for equality like
you did. It probably works in this case, but it's pretty fragile in
general. The problem while you can compare two pseudos using pointer
equality, you can't necessarily do that for hard registers.
What happens under the hood is you can have two distinct pseudos which
get allocated to the same hard reg. At assignment time we just replace
the underlying register # without going back and fixing all the REG
expressions. Meaning that you can have:
(reg:XX 12) and (reg:XX 12)
Which are at distinct memory locations. Meaning that while the RTX
expresssions look the same, they will fail the pointer equality check.
So again, it probably works on your example, but I'd rather look for
ways to bullet proof this better. The (match_dup) approach is probably
the most preferred.
Similarly for the other 3 patterns that have pointer equality tests for
two operands in the insn condition.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 1/5] [RISC-V] Recognize Zicond extension
2023-07-19 10:11 ` [PATCH 1/5] [RISC-V] " Xiao Zeng
@ 2023-07-25 16:35 ` Jeff Law
2023-07-26 21:11 ` Jeff Law
1 sibling, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-07-25 16:35 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/19/23 04:11, Xiao Zeng wrote:
> This patch is the minimal support for Zicond extension, include
> the extension name, mask and target defination.
>
> gcc/ChangeLog:
>
> * common/config/riscv/riscv-common.cc: New extension.
> * config/riscv/riscv-opts.h (MASK_ZICOND): New mask.
> (TARGET_ZICOND): New target.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/riscv/attribute-20.c: New test.
> * gcc.target/riscv/attribute-21.c: New test.
This is OK. Though I don't think we should install until the follow-on
patches are ready to go.
jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-19 10:11 ` [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 Xiao Zeng
@ 2023-07-25 17:32 ` Jeff Law
2023-07-25 17:55 ` Andreas Schwab
` (2 subsequent siblings)
3 siblings, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-07-25 17:32 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/19/23 04:11, Xiao Zeng wrote:
> This patch completes the recognition of Zicond when the select pattern
> with condition eq or neq to 0 (using equality as an example), namely:
>
> 1 rd = (rs2 == 0) ? non-imm : 0
> 2 rd = (rs2 == 0) ? non-imm : non-imm
> 3 rd = (rs2 == 0) ? reg : non-imm
> 4 rd = (rs2 == 0) ? reg : reg
>
> gcc/ChangeLog:
>
> * config/riscv/riscv.cc (riscv_rtx_costs): IF_THEN_ELSE costs in Zicond.
> (riscv_expand_conditional_move): Recognize Zicond.
> * config/riscv/riscv.md: Zicond patterns.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c: New test.
> * gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c: New test.
> * gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c: New test.
> * gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c: New test.
> ---
> gcc/config/riscv/riscv.cc | 125 ++++++++++++++++++
> gcc/config/riscv/riscv.md | 2 +-
> .../zicond-primitiveSemantics_return_0_imm.c | 65 +++++++++
> ...zicond-primitiveSemantics_return_imm_imm.c | 73 ++++++++++
> ...zicond-primitiveSemantics_return_imm_reg.c | 65 +++++++++
> ...zicond-primitiveSemantics_return_reg_reg.c | 65 +++++++++
> 6 files changed, 394 insertions(+), 1 deletion(-)
> create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c
> create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c
> create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c
> create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c
>
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 38d8eb2fcf5..7e6b24bd232 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -2448,6 +2448,17 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
> *total = COSTS_N_INSNS (1);
> return true;
> }
> + else if (TARGET_ZICOND && outer_code == SET &&
> + ((GET_CODE (XEXP (x, 1)) == REG && XEXP (x, 2) == const0_rtx) ||
> + (GET_CODE (XEXP (x, 2)) == REG && XEXP (x, 1) == const0_rtx) ||
> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
> + XEXP (x, 1) == XEXP (XEXP (x, 0), 0)) ||
> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
> + XEXP (x, 2) == XEXP (XEXP (x, 0), 0))))
> + {
> + *total = 0;
> + return true;
> + }
So why *total = 0. I would have expected *total = COSTS_N_INSNS (1).
I'm not entirely sure the changes to riscv_expand_conditional_move are
desirable -- these are likely better done in the generic if-conversion
pass.
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index 6b8c2e8e268..b4147c7a79c 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -2484,7 +2484,7 @@
> (if_then_else:GPR (match_operand 1 "comparison_operator")
> (match_operand:GPR 2 "reg_or_0_operand")
> (match_operand:GPR 3 "sfb_alu_operand")))]
> - "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV"
> + "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND"
> {
> if (riscv_expand_conditional_move (operands[0], operands[1],
> operands[2], operands[3]))
We had to do more than just slap on a TARGET_ZICOND. I'm a bit
surprised this worked as-is. Though we also have bits to handle
conditions other than eq/ne by first emitting an sCC style insn which
might be adding complication or cases you hadn't encountered.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 0/5] Recognize Zicond extension
2023-07-19 10:11 [PATCH 0/5] Recognize Zicond extension Xiao Zeng
` (4 preceding siblings ...)
2023-07-19 10:11 ` [PATCH 5/5] [RISC-V] Generate Zicond instruction for conditional execution Xiao Zeng
@ 2023-07-25 17:51 ` Jeff Law
2023-07-27 8:43 ` Xiao Zeng
5 siblings, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-07-25 17:51 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/19/23 04:11, Xiao Zeng wrote:
> Hi all RISC-V folks:
>
> This series of patches completes support for the riscv architecture's
> Zicond standard extension instruction set.
>
> Currently, Zicond is in a frozen state.
>
> See the Zicond specification for details:
> https://github.com/riscv/riscv-zicond/releases/download/v1.0-rc2/riscv-zicond-v1.0-rc2.pdf
>
> Prior to this, other community members have also done related work, as shown in:
> https://gcc.gnu.org/pipermail/gcc-patches/2023-February/611767.html
> https://sourceware.org/pipermail/binutils/2023-January/125773.html
>
> Xiao Zeng (5):
> [RISC-V] Recognize Zicond extension
> [RISC-V] Generate Zicond instruction for basic semantics
> [RISC-V] Generate Zicond instruction for select pattern with condition
> eq or neq to 0
> [RISC-V] Generate Zicond instruction for select pattern with condition
> eq or neq to non-zero
> [RISC-V] Generate Zicond instruction for conditional execution
[ ... ]
So what I'm thinking for the overall kit is to stage it in a bit
differently given we have some bits which clearly can go forward as-is
or with very minor changes and others that are going to need some
iteration/refinement.
So I'm going to suggest a few changes so that bits which are non
controversial can move forward immediately.
1/5 looked fine as-is.
I would split 2/5. The first two patterns you added are
non-controversial and could go in immediately. The other 4 patterns
(which require some operand matching) will likely need at least one
round of iteration and should be a distinct patch.
I would split 3/5 as well. 3a would be the costing which I think just
needs to use COSTS_N_INSNS (1) rather than 0 for the cost of a
conditional move and could then move forward immediately. The bits to
wire everything up into the conditional move pattern would be a distinct
patch. We did something similar internally in Ventana and I'd like to
take the time to make sure the issues we ran into are addressed in your
version then do an evaluation of the two approaches.
I think patch 4 is probably going to need some work too. I *think* what
we did internally at Ventana will work better (utilizing scc for a
non-trivial condition).
Let's defer patch #5 initially as well. It's going to get tangled up in
a whole bunch of changes I think we need to make to ifcvt.cc.
The point being that with the bits from #1, #2 and #3 we can get some
initial support in immediately. eswincomputing and ventana can both
reduce our divergence from the trunk and work together on the rest of
the bits.
Does that work for you?
jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-19 10:11 ` [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 Xiao Zeng
2023-07-25 17:32 ` Jeff Law
@ 2023-07-25 17:55 ` Andreas Schwab
2023-07-27 5:44 ` Xiao Zeng
2023-07-28 15:09 ` Jeff Law
2023-07-28 20:59 ` Jeff Law
2023-08-02 6:34 ` Jeff Law
3 siblings, 2 replies; 40+ messages in thread
From: Andreas Schwab @ 2023-07-25 17:55 UTC (permalink / raw)
To: Xiao Zeng
Cc: gcc-patches, jeffreyalaw, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain
On Jul 19 2023, Xiao Zeng wrote:
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 38d8eb2fcf5..7e6b24bd232 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -2448,6 +2448,17 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
> *total = COSTS_N_INSNS (1);
> return true;
> }
> + else if (TARGET_ZICOND && outer_code == SET &&
> + ((GET_CODE (XEXP (x, 1)) == REG && XEXP (x, 2) == const0_rtx) ||
> + (GET_CODE (XEXP (x, 2)) == REG && XEXP (x, 1) == const0_rtx) ||
> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
> + XEXP (x, 1) == XEXP (XEXP (x, 0), 0)) ||
> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
> + XEXP (x, 2) == XEXP (XEXP (x, 0), 0))))
Line breaks before the operator, not after.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics
2023-07-19 10:11 ` [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics Xiao Zeng
2023-07-25 16:35 ` Jeff Law
@ 2023-07-26 17:53 ` Jeff Law
2023-08-01 11:18 ` Richard Sandiford
2023-07-26 21:14 ` Jeff Law
2 siblings, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-07-26 17:53 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/19/23 04:11, Xiao Zeng wrote:
> This patch completes the recognition of the basic semantics
> defined in the spec, namely:
>
> Conditional zero, if condition is equal to zero
> rd = (rs2 == 0) ? 0 : rs1
> Conditional zero, if condition is non zero
> rd = (rs2 != 0) ? 0 : rs1
>
> gcc/ChangeLog:
>
> * config/riscv/riscv.md: Include zicond.md
> * config/riscv/zicond.md: New file.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/riscv/zicond-primitiveSemantics.c: New test.
So I played with this a bit today. I originally thought that using
match_dup was the right way to go for those 4 secondary patterns. But
after further pondering it's not ideal.
match_dup will require pointer equality within the RTL structure. That
could inhibit detection in two cases. First, SUBREGs. SUBREGs are not
shared. So we'd never match if we had a SUBREG expression.
Second, post register allocation we can have the same looking RTX, but
it may not be pointer equal.
The SUBREG issue also means that we don't want to use a REGNO (x) ==
REGNO (y) style check because those macros are only valid on REG
expressions. We could strip the SUBREG, but that's usually awkward to
do in a pattern's condition.
The net result is we probably should use rtx_equal_p which I was hoping
to avoid. I'm testing with that change to the 4 secondary patterns
right now. Assuming that passes (and I have no reason to think it
won't) then I'll go ahead and commit #1 and #2 from this series which is
all I have time for today.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 1/5] [RISC-V] Recognize Zicond extension
2023-07-19 10:11 ` [PATCH 1/5] [RISC-V] " Xiao Zeng
2023-07-25 16:35 ` Jeff Law
@ 2023-07-26 21:11 ` Jeff Law
1 sibling, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-07-26 21:11 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/19/23 04:11, Xiao Zeng wrote:
> This patch is the minimal support for Zicond extension, include
> the extension name, mask and target defination.
>
> gcc/ChangeLog:
>
> * common/config/riscv/riscv-common.cc: New extension.
> * config/riscv/riscv-opts.h (MASK_ZICOND): New mask.
> (TARGET_ZICOND): New target.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/riscv/attribute-20.c: New test.
> * gcc.target/riscv/attribute-21.c: New test.
I've pushed this to the trunk.
jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics
2023-07-19 10:11 ` [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics Xiao Zeng
2023-07-25 16:35 ` Jeff Law
2023-07-26 17:53 ` Jeff Law
@ 2023-07-26 21:14 ` Jeff Law
2 siblings, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-07-26 21:14 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
[-- Attachment #1: Type: text/plain, Size: 790 bytes --]
On 7/19/23 04:11, Xiao Zeng wrote:
> This patch completes the recognition of the basic semantics
> defined in the spec, namely:
>
> Conditional zero, if condition is equal to zero
> rd = (rs2 == 0) ? 0 : rs1
> Conditional zero, if condition is non zero
> rd = (rs2 != 0) ? 0 : rs1
>
> gcc/ChangeLog:
>
> * config/riscv/riscv.md: Include zicond.md
> * config/riscv/zicond.md: New file.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/riscv/zicond-primitiveSemantics.c: New test.
So as I mentioned earlier today, adjusting the insn condition to use
rtx_equal_p seems to be the right way to go. Attached is a V2 of this
patch that implements that. It was trivial enough to do that there's no
need to break this patch down further.
I've pushed V2 to the trunk.
Thanks,
Jeff
[-- Attachment #2: P --]
[-- Type: text/plain, Size: 6868 bytes --]
commit 74290c664d1d4c067a996253fe505555ec671668
Author: Xiao Zeng <zengxiao@eswincomputing.com>
Date: Wed Jul 26 11:59:59 2023 -0600
[PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics
This patch completes the recognition of the basic semantics
defined in the spec, namely:
Conditional zero, if condition is equal to zero
rd = (rs2 == 0) ? 0 : rs1
Conditional zero, if condition is non zero
rd = (rs2 != 0) ? 0 : rs1
gcc/ChangeLog:
* config/riscv/riscv.md: Include zicond.md
* config/riscv/zicond.md: New file.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/zicond-primitiveSemantics.c: New test.
Co-authored-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
Co-authored-by: Raphael Zinsly <rzinsly@ventanamicro.com>
Co-authored-by: Jeff Law <jlaw@ventanamicro.com>
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 24515bcf706..8d8fc93bb14 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -3319,3 +3319,4 @@ (define_expand "msubhisi4"
(include "sifive-7.md")
(include "thead.md")
(include "vector.md")
+(include "zicond.md")
diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md
new file mode 100644
index 00000000000..723a22422e1
--- /dev/null
+++ b/gcc/config/riscv/zicond.md
@@ -0,0 +1,84 @@
+;; Machine description for the RISC-V Zicond extension
+;; Copyright (C) 2022-23 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3. If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_code_iterator eq_or_ne [eq ne])
+(define_code_attr eqz [(eq "nez") (ne "eqz")])
+(define_code_attr nez [(eq "eqz") (ne "nez")])
+
+;; Zicond
+(define_insn "*czero.<eqz>.<GPR:mode><ANYI:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (eq_or_ne (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "r")
+ (const_int 0)))]
+ "TARGET_ZICOND"
+ "czero.<eqz>\t%0,%2,%1"
+)
+
+(define_insn "*czero.<nez>.<GPR:mode><ANYI:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (eq_or_ne (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (const_int 0)
+ (match_operand:GPR 2 "register_operand" "r")))]
+ "TARGET_ZICOND"
+ "czero.<nez>\t%0,%2,%1"
+)
+
+;; Special optimization under eq/ne in primitive semantics
+(define_insn "*czero.eqz.<GPR:mode><ANYI:mode>.opt1"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (eq (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "1")
+ (match_operand:GPR 3 "register_operand" "r")))]
+ "TARGET_ZICOND && rtx_equal_p (operands[1], operands[2])"
+ "czero.eqz\t%0,%3,%1"
+)
+
+(define_insn "*czero.eqz.<GPR:mode><ANYI:mode>.opt2"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (eq (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "r")
+ (match_operand:GPR 3 "register_operand" "1")))]
+ "TARGET_ZICOND && rtx_equal_p (operands[1], operands[3])"
+ "czero.nez\t%0,%2,%1"
+)
+
+(define_insn "*czero.nez.<GPR:mode><ANYI:mode>.opt3"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (ne (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "r")
+ (match_operand:GPR 3 "register_operand" "1")))]
+ "TARGET_ZICOND && rtx_equal_p (operands[1], operands[3])"
+ "czero.eqz\t%0,%2,%1"
+)
+
+(define_insn "*czero.nez.<GPR:mode><ANYI:mode>.opt4"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (if_then_else:GPR (ne (match_operand:ANYI 1 "register_operand" "r")
+ (const_int 0))
+ (match_operand:GPR 2 "register_operand" "1")
+ (match_operand:GPR 3 "register_operand" "r")))]
+ "TARGET_ZICOND && rtx_equal_p (operands[1], operands[2])"
+ "czero.nez\t%0,%3,%1"
+)
diff --git a/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics.c b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics.c
new file mode 100644
index 00000000000..76c5019a992
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } {"-O0"} } */
+
+long primitiveSemantics_00(long a, long b) { return a == 0 ? 0 : b; }
+
+long primitiveSemantics_01(long a, long b) { return a != 0 ? 0 : b; }
+
+long primitiveSemantics_02(long a, long b) { return a == 0 ? b : 0; }
+
+long primitiveSemantics_03(long a, long b) { return a != 0 ? b : 0; }
+
+long primitiveSemantics_04(long a, long b) {
+ if (a)
+ b = 0;
+ return b;
+}
+
+long primitiveSemantics_05(long a, long b) {
+ if (!a)
+ b = 0;
+ return b;
+}
+
+int primitiveSemantics_06(int a, int b) { return a == 0 ? 0 : b; }
+
+int primitiveSemantics_07(int a, int b) { return a != 0 ? 0 : b; }
+
+int primitiveSemantics_08(int a, int b) { return a == 0 ? b : 0; }
+
+int primitiveSemantics_09(int a, int b) { return a != 0 ? b : 0; }
+
+int primitiveSemantics_10(int a, int b) {
+ if (a)
+ b = 0;
+ return b;
+}
+
+int primitiveSemantics_11(int a, int b) {
+ if (!a)
+ b = 0;
+ return b;
+}
+
+/* { dg-final { scan-assembler-times "czero.eqz" 6 } } */
+/* { dg-final { scan-assembler-times "czero.nez" 6 } } */
+/* { dg-final { scan-assembler-not "beq" } } */
+/* { dg-final { scan-assembler-not "bne" } } */
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-25 17:55 ` Andreas Schwab
@ 2023-07-27 5:44 ` Xiao Zeng
2023-07-28 15:09 ` Jeff Law
1 sibling, 0 replies; 40+ messages in thread
From: Xiao Zeng @ 2023-07-27 5:44 UTC (permalink / raw)
To: Andreas Schwab
Cc: gcc-patches, jeffreyalaw, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain
On Wed, Jul 26, 2023 at 01:55:00 AM Andreas Schwab <schwab@linux-m68k.org> wrote:
>
>On Jul 19 2023, Xiao Zeng wrote:
>
>> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
>> index 38d8eb2fcf5..7e6b24bd232 100644
>> --- a/gcc/config/riscv/riscv.cc
>> +++ b/gcc/config/riscv/riscv.cc
>> @@ -2448,6 +2448,17 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
>> *total = COSTS_N_INSNS (1);
>> return true;
>> }
>> + else if (TARGET_ZICOND && outer_code == SET &&
>> + ((GET_CODE (XEXP (x, 1)) == REG && XEXP (x, 2) == const0_rtx) ||
>> + (GET_CODE (XEXP (x, 2)) == REG && XEXP (x, 1) == const0_rtx) ||
>> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
>> + XEXP (x, 1) == XEXP (XEXP (x, 0), 0)) ||
>> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
>> + XEXP (x, 2) == XEXP (XEXP (x, 0), 0))))
>
>Line breaks before the operator, not after.
>
>--
>Andreas Schwab, schwab@linux-m68k.org
>GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
>"And now for something completely different."
Thank you for pointing out the code format issue. I will fix it in the future patch.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: Re: [PATCH 0/5] Recognize Zicond extension
2023-07-25 17:51 ` [PATCH 0/5] Recognize Zicond extension Jeff Law
@ 2023-07-27 8:43 ` Xiao Zeng
2023-07-27 14:43 ` Jeff Law
0 siblings, 1 reply; 40+ messages in thread
From: Xiao Zeng @ 2023-07-27 8:43 UTC (permalink / raw)
To: jeffreyalaw, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On Wed, Jul 26, 2023 at 01:51:00 AM Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
>On 7/19/23 04:11, Xiao Zeng wrote:
>> Hi all RISC-V folks:
>>
>> This series of patches completes support for the riscv architecture's
>> Zicond standard extension instruction set.
>>
>> Currently, Zicond is in a frozen state.
>>
>> See the Zicond specification for details:
>> https://github.com/riscv/riscv-zicond/releases/download/v1.0-rc2/riscv-zicond-v1.0-rc2.pdf
>>
>> Prior to this, other community members have also done related work, as shown in:
>> https://gcc.gnu.org/pipermail/gcc-patches/2023-February/611767.html
>> https://sourceware.org/pipermail/binutils/2023-January/125773.html
>>
>> Xiao Zeng (5):
>> [RISC-V] Recognize Zicond extension
>> [RISC-V] Generate Zicond instruction for basic semantics
>> [RISC-V] Generate Zicond instruction for select pattern with condition
>> eq or neq to 0
>> [RISC-V] Generate Zicond instruction for select pattern with condition
>> eq or neq to non-zero
>> [RISC-V] Generate Zicond instruction for conditional execution
>[ ... ]
>So what I'm thinking for the overall kit is to stage it in a bit
>differently given we have some bits which clearly can go forward as-is
>or with very minor changes and others that are going to need some
>iteration/refinement.
>
>So I'm going to suggest a few changes so that bits which are non
>controversial can move forward immediately.
>
>1/5 looked fine as-is.
>
>I would split 2/5. The first two patterns you added are
>non-controversial and could go in immediately. The other 4 patterns
>(which require some operand matching) will likely need at least one
>round of iteration and should be a distinct patch.
>
>
>I would split 3/5 as well. 3a would be the costing which I think just
>needs to use COSTS_N_INSNS (1) rather than 0 for the cost of a
>conditional move and could then move forward immediately. The bits to
>wire everything up into the conditional move pattern would be a distinct
>patch. We did something similar internally in Ventana and I'd like to
>take the time to make sure the issues we ran into are addressed in your
>version then do an evaluation of the two approaches.
>
>I think patch 4 is probably going to need some work too. I *think* what
>we did internally at Ventana will work better (utilizing scc for a
>non-trivial condition).
>
>Let's defer patch #5 initially as well. It's going to get tangled up in
>a whole bunch of changes I think we need to make to ifcvt.cc.
>
>The point being that with the bits from #1, #2 and #3 we can get some
>initial support in immediately. eswincomputing and ventana can both
>reduce our divergence from the trunk and work together on the rest of
>the bits.
>
>Does that work for you?
>
>jeff
1 Thanks Jeff for your code review feedback.
2. According to your opinions, I have modified the code, but out of caution
for upstream, I conducted a complete regression tests on patch V2, which took
some time. I was unable to reply to emails and upload patch V2 in a timely manner.
3 After you and other maintainers made minor modifications to my patch[1/5]
and patch[2/5], it has been merged into the master, so I will no longer upload patch V2.
4 patch[1/5] and patch[2/5], which have been merged into the master, have only
completed basic support for Zicond, and further optimization work needs to be
completed. These further optimization reactions are reflected in my patch[3/5]
patch[4/5] and patch[5/5].
5 As you mentioned in your previous email https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625427.html
"eswincomputing and ventana can both reduce our divergence from the trunk
and work together on the rest of the bits...". I will reorganize patch[3/5] patch[4/5]
and patch[5/5], provide more detailed explanations, and submit them as an alternative
solution for further optimization of Zicond.
Does that work for you?
Xiao Zeng
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 0/5] Recognize Zicond extension
2023-07-27 8:43 ` Xiao Zeng
@ 2023-07-27 14:43 ` Jeff Law
2023-07-28 6:34 ` Xiao Zeng
0 siblings, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-07-27 14:43 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/27/23 02:43, Xiao Zeng wrote:
>
> 2. According to your opinions, I have modified the code, but out of caution
> for upstream, I conducted a complete regression tests on patch V2, which took
> some time. I was unable to reply to emails and upload patch V2 in a timely manner.
Sorry to have wasted your time -- zicond/xventanacondops has lingered
for quite a while and I had a bit of free time yesterday. I felt it was
most useful to try and move this stuff forward.
>
> 3 After you and other maintainers made minor modifications to my patch[1/5]
> and patch[2/5], it has been merged into the master, so I will no longer upload patch V2.
Agreed.
>
> 4 patch[1/5] and patch[2/5], which have been merged into the master, have only
> completed basic support for Zicond, and further optimization work needs to be
> completed. These further optimization reactions are reflected in my patch[3/5]
> patch[4/5] and patch[5/5].
Agreed.
>
> 5 As you mentioned in your previous email https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625427.html
> "eswincomputing and ventana can both reduce our divergence from the trunk
> and work together on the rest of the bits...". I will reorganize patch[3/5] patch[4/5]
> and patch[5/5], provide more detailed explanations, and submit them as an alternative
> solution for further optimization of Zicond.
>
> Does that work for you?
I'm going to look at 3/5 today pretty closely. Exposing zicond to
mov<node>cc is something we had implemented inside Ventana and I want to
compare/contrast your work with ours.
What I like about yours is it keeps all the logic in riscv.cc rather
than scattering it across riscv.cc and riscv.md. What I like about the
internal Ventana bits is its ability to support arbitrary comparisons by
utilizing sCC if the original is not an eq/ne comparison.
Ideally we'll be able to get the best of both.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: Re: [PATCH 0/5] Recognize Zicond extension
2023-07-27 14:43 ` Jeff Law
@ 2023-07-28 6:34 ` Xiao Zeng
2023-07-28 15:03 ` Jeff Law
2023-08-03 2:59 ` Jeff Law
0 siblings, 2 replies; 40+ messages in thread
From: Xiao Zeng @ 2023-07-28 6:34 UTC (permalink / raw)
To: jeffreyalaw, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On Thu, Jul 27, 2023 at 10:43:00 PM Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
>On 7/27/23 02:43, Xiao Zeng wrote:
>
>>
>> 2. According to your opinions, I have modified the code, but out of caution
>> for upstream, I conducted a complete regression tests on patch V2, which took
>> some time. I was unable to reply to emails and upload patch V2 in a timely manner.
>Sorry to have wasted your time
It's okay
I am very willing to accept opinions from the gcc community.
>-- zicond/xventanacondops has lingered
>for quite a while and I had a bit of free time yesterday. I felt it was
>most useful to try and move this stuff forward.
>
>
>
>>
>> 3 After you and other maintainers made minor modifications to my patch[1/5]
>> and patch[2/5], it has been merged into the master, so I will no longer upload patch V2.
>Agreed.
>
>>
>> 4 patch[1/5] and patch[2/5], which have been merged into the master, have only
>> completed basic support for Zicond, and further optimization work needs to be
>> completed. These further optimization reactions are reflected in my patch[3/5]
>> patch[4/5] and patch[5/5].
>Agreed.
>
>>
>> 5 As you mentioned in your previous email https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625427.html
>> "eswincomputing and ventana can both reduce our divergence from the trunk
>> and work together on the rest of the bits...". I will reorganize patch[3/5] patch[4/5]
>> and patch[5/5], provide more detailed explanations, and submit them as an alternative
>> solution for further optimization of Zicond.
>>
>> Does that work for you?
>I'm going to look at 3/5 today pretty closely. Exposing zicond to
>mov<node>cc is something we had implemented inside Ventana and I want to
>compare/contrast your work with ours.
What a coincidence!
>
>What I like about yours is it keeps all the logic in riscv.cc rather
>than scattering it across riscv.cc and riscv.md.
Yes, when I use enough test cases, I cannot find a concise way to optimize
all test cases. When I enumerated all possible cases in the mov<mode>cc
function of the RISC-V backend, I found a method that satisfied me, which
is the method in patch [3/5].
>What I like about the
>internal Ventana bits is its ability to support arbitrary comparisons by
>utilizing sCC if the original is not an eq/ne comparison.
>
If it's just for the Zicond instruction set, is it necessary to make judgments
outside of eq/ne? After all, it does not support comparison actions other
than eq/ne. Of course, it is also possible to use a special technique to use
Zicond in non eq/ne comparisons.
>Ideally we'll be able to get the best of both.
Of course, it is best to unify all situations in one framework.
>
>Jeff
Now that the code on the master has preliminary support for
Zicond, I will still submit the optimization patches for Zicond to
the community for the convenience of finding the ideal method.
Thanks
Xiao Zeng
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 0/5] Recognize Zicond extension
2023-07-28 6:34 ` Xiao Zeng
@ 2023-07-28 15:03 ` Jeff Law
2023-07-29 10:01 ` Xiao Zeng
2023-08-03 2:59 ` Jeff Law
1 sibling, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-07-28 15:03 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/28/23 00:34, Xiao Zeng wrote:
>>>
>>> Does that work for you?
>> I'm going to look at 3/5 today pretty closely. Exposing zicond to
>> mov<node>cc is something we had implemented inside Ventana and I want to
>> compare/contrast your work with ours.
>
> What a coincidence!
Zicond is a direct descendant of xventanacondops. The only notable
difference is in their encodings.
>
>>
>> What I like about yours is it keeps all the logic in riscv.cc rather
>> than scattering it across riscv.cc and riscv.md.
>
> Yes, when I use enough test cases, I cannot find a concise way to optimize
> all test cases. When I enumerated all possible cases in the mov<mode>cc
> function of the RISC-V backend, I found a method that satisfied me, which
> is the method in patch [3/5].
I got pulled away to another task yesterday, so didn't get as far as I
wanted. The biggest inight from yesterday was determining that some of
the cases you're handling in riscv_expand_conditional_move were things
we were doing inside ifcvt.cc.
The difference is likely because the initial work on zicond here was
primarily driven by changes to ifcvt. It was only after evaluating that
initial implementation that we started to the effort to use zicond at
RTL expansion time.
I could make a case for either approach, but the more I ponder them the
more I'm inclined to go with something like yours. We want to capture
the cases implementable as a conditional move as early as possible in
the RTL pipeline rather than relying on ifcvt to catch it later. It
also avoids polluting ifcvt with transformations that are only likely
needed on risc-v.
>>
>
> If it's just for the Zicond instruction set, is it necessary to make judgments
> outside of eq/ne? After all, it does not support comparison actions other
> than eq/ne. Of course, it is also possible to use a special technique to use
> Zicond in non eq/ne comparisons.
It's not necessary, but it's definitely helpful to cover the other
conditions. In fact, we can even cover a variety of fp conditions by
utilizing the sCC type insns.
So what I'm looking at for patch #3 is to split out the costing bits
into its own patch which can go forward immediately. THen continue
evaluating the best way to handle unifying the expander/canonicalization
code. Your testcases in patch #3 are particularly helpful to make sure
we're not missing cases.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-25 17:55 ` Andreas Schwab
2023-07-27 5:44 ` Xiao Zeng
@ 2023-07-28 15:09 ` Jeff Law
2023-07-29 9:48 ` Xiao Zeng
1 sibling, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-07-28 15:09 UTC (permalink / raw)
To: Andreas Schwab, Xiao Zeng
Cc: gcc-patches, research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/25/23 11:55, Andreas Schwab wrote:
> On Jul 19 2023, Xiao Zeng wrote:
>
>> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
>> index 38d8eb2fcf5..7e6b24bd232 100644
>> --- a/gcc/config/riscv/riscv.cc
>> +++ b/gcc/config/riscv/riscv.cc
>> @@ -2448,6 +2448,17 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
>> *total = COSTS_N_INSNS (1);
>> return true;
>> }
>> + else if (TARGET_ZICOND && outer_code == SET &&
>> + ((GET_CODE (XEXP (x, 1)) == REG && XEXP (x, 2) == const0_rtx) ||
>> + (GET_CODE (XEXP (x, 2)) == REG && XEXP (x, 1) == const0_rtx) ||
>> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
>> + XEXP (x, 1) == XEXP (XEXP (x, 0), 0)) ||
>> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
>> + XEXP (x, 2) == XEXP (XEXP (x, 0), 0))))
>
> Line breaks before the operator, not after.
Also note that && GET_CODE (XEXP (x, 2)) && that appears twice.
That just verifies the code isn't RTX_UNKNOWN which I suspect isn't what
the author intended. It probably needs to be adjusted for SUBREGs and
the pointer equality issues with REGs after reload.
I'll take care of these goofs since the costing ought to be able to move
forward independently of the improvements Xiao made to generating
conditional move sequences.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-19 10:11 ` [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 Xiao Zeng
2023-07-25 17:32 ` Jeff Law
2023-07-25 17:55 ` Andreas Schwab
@ 2023-07-28 20:59 ` Jeff Law
2023-07-29 9:14 ` Xiao Zeng
2023-08-02 6:34 ` Jeff Law
3 siblings, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-07-28 20:59 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/19/23 04:11, Xiao Zeng wrote:
> + else if (TARGET_ZICOND
> + && (code == EQ || code == NE)
> + && GET_MODE_CLASS (mode) == MODE_INT)
> + {
> + need_eq_ne_p = true;
> + /* 0 + imm */
> + if (GET_CODE (cons) == CONST_INT && cons == const0_rtx
> + && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
> + {
> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> + alt = force_reg (mode, alt);
> + emit_insn (gen_rtx_SET (dest,
> + gen_rtx_IF_THEN_ELSE (mode, cond,
> + cons, alt)));
> + return true;
> + }
> + /* imm + imm */
> + else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
> + && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
> + {
> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> + alt = force_reg (mode, alt);
> + rtx temp1 = gen_reg_rtx (mode);
> + rtx temp2 = GEN_INT(-1 * INTVAL (cons));
> + riscv_emit_binary(PLUS, temp1, alt, temp2);
So in this sequence you're just computing a constant since both ALT and
CONS are constants. It's better to just form the constant directly,
then force that into a register because it'll make the costing more
correct, particularly if the resulting constant needs more than one
instruction to synthesize.
And a nit. There should always be a space between a function name and
its argument list.
> + emit_insn (gen_rtx_SET (dest,
> + gen_rtx_IF_THEN_ELSE (mode, cond,
> + const0_rtx, alt)));
> + riscv_emit_binary(PLUS, dest, dest, cons);
> + return true;
I don't see how this can be correct from a code generation standpoint.
You compute ALT-CONS into TEMP1 earlier. But you never use TEMP1 after
that. I think you meant to use TEMP1 instead of ALT as the false arm if
the IF-THEN-ELSE you constructed.
In general you should be using CONST0_RTX (mode) rather than const0_rtx.
> + }
> + /* imm + reg */
> + else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
> + && GET_CODE (alt) == REG)
> + {
> + /* Optimize for register value of 0. */
> + if (op0 == alt && op1 == const0_rtx)
> + {
> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> + cons = force_reg (mode, cons);
> + emit_insn (gen_rtx_SET (dest,
> + gen_rtx_IF_THEN_ELSE (mode, cond,
> + cons, alt)));
> + return true;
> + }
> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> + rtx temp1 = gen_reg_rtx (mode);
> + rtx temp2 = GEN_INT(-1 * INTVAL (cons));
> + riscv_emit_binary(PLUS, temp1, alt, temp2);
Here you have to be careful if CONS is -2048. You negate it resulting
in +2048 which can't be used in an addi. This will cause the entire
sequence to fail due to an unrecognized insn. It would be better to
handle that scenario directly so the generated sequence is still valid.
By generating recognizable code in that case we let the costing model
determine if the conditional move sequence is better than the branching
sequence.
> + emit_insn (gen_rtx_SET (dest,
> + gen_rtx_IF_THEN_ELSE (mode, cond,
> + const0_rtx, alt)));
I think we have the same problem with the use of ALT here rather than
TEMP1 that we had in the previous case.
> + /* reg + imm */
> + else if (GET_CODE (cons) == REG
> + && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
> + {
> + /* Optimize for register value of 0. */
> + if (op0 == cons && op1 == const0_rtx)
> + {
> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> + alt = force_reg (mode, alt);
> + emit_insn (gen_rtx_SET (dest,
> + gen_rtx_IF_THEN_ELSE (mode, cond,
> + cons, alt)));
> + return true;
> + }
> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> + rtx temp1 = gen_reg_rtx (mode);
> + rtx temp2 = GEN_INT(-1 * INTVAL (alt));
> + riscv_emit_binary(PLUS, temp1, cons, temp2);
> + emit_insn (gen_rtx_SET (dest,
> + gen_rtx_IF_THEN_ELSE (mode, cond,
> + temp1, const0_rtx)));
> + riscv_emit_binary(PLUS, dest, dest, alt);
> + return true;
This has basically the same issues as the imm + reg case.
> + }
> + /* reg + reg */
> + else if (GET_CODE (cons) == REG && GET_CODE (alt) == REG)
> + {
> + rtx reg1 = gen_reg_rtx (mode);
> + rtx reg2 = gen_reg_rtx (mode);
> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
> + rtx cond1 = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
> + rtx cond2 = gen_rtx_fmt_ee (code == NE ? EQ : NE,
> + GET_MODE (op0), op0, op1);
> + emit_insn (gen_rtx_SET (reg2,
> + gen_rtx_IF_THEN_ELSE (mode, cond2,
> + const0_rtx, cons)));
> + emit_insn (gen_rtx_SET (reg1,
> + gen_rtx_IF_THEN_ELSE (mode, cond1,
> + const0_rtx, alt)));
> + riscv_emit_binary(IOR, dest, reg1, reg2);
> + return true;
This probably should detect the case where alt or cons is the same as
op0. Otherwise I would expect the costing model to reject some cases
that are actually profitable.
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index 6b8c2e8e268..b4147c7a79c 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -2484,7 +2484,7 @@
> (if_then_else:GPR (match_operand 1 "comparison_operator")
> (match_operand:GPR 2 "reg_or_0_operand")
> (match_operand:GPR 3 "sfb_alu_operand")))
> - "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV"
> + "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND"
Note the predicate for operand2 will reject all constants except 0.
Anyway, I'm still cleaning this up and adding the bits from Ventana
which handle the relational conditions as well as FP conditionals.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-28 20:59 ` Jeff Law
@ 2023-07-29 9:14 ` Xiao Zeng
2023-08-03 4:59 ` Jeff Law
0 siblings, 1 reply; 40+ messages in thread
From: Xiao Zeng @ 2023-07-29 9:14 UTC (permalink / raw)
To: jeffreyalaw, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On Sat, Jul 29, 2023 at 04:59:00 AM Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
>On 7/19/23 04:11, Xiao Zeng wrote:
>
>> + else if (TARGET_ZICOND
>> + && (code == EQ || code == NE)
>> + && GET_MODE_CLASS (mode) == MODE_INT)
>> + {
>> + need_eq_ne_p = true;
>> + /* 0 + imm */
>> + if (GET_CODE (cons) == CONST_INT && cons == const0_rtx
>> + && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
>> + {
>> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
>> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
>> + alt = force_reg (mode, alt);
>> + emit_insn (gen_rtx_SET (dest,
>> + gen_rtx_IF_THEN_ELSE (mode, cond,
>> + cons, alt)));
>> + return true;
>> + }
>> + /* imm + imm */
>> + else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
>> + && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
>> + {
>> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
>> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
>> + alt = force_reg (mode, alt);
>> + rtx temp1 = gen_reg_rtx (mode);
>> + rtx temp2 = GEN_INT(-1 * INTVAL (cons));
>> + riscv_emit_binary(PLUS, temp1, alt, temp2);
>So in this sequence you're just computing a constant since both ALT and
>CONS are constants. It's better to just form the constant directly,
>then force that into a register because it'll make the costing more
>correct, particularly if the resulting constant needs more than one
>instruction to synthesize.
Fixed
>
>And a nit. There should always be a space between a function name and
>its argument list.
Fixed
>
>
>
>> + emit_insn (gen_rtx_SET (dest,
>> + gen_rtx_IF_THEN_ELSE (mode, cond,
>> + const0_rtx, alt)));
>> + riscv_emit_binary(PLUS, dest, dest, cons);
>> + return true;
>I don't see how this can be correct from a code generation standpoint.
>You compute ALT-CONS into TEMP1 earlier. But you never use TEMP1 after
>that. I think you meant to use TEMP1 instead of ALT as the false arm if
>the IF-THEN-ELSE you constructed.
Fixed
>
>In general you should be using CONST0_RTX (mode) rather than const0_rtx.
>
Fixed
>> + }
>> + /* imm + reg */
>> + else if (GET_CODE (cons) == CONST_INT && cons != const0_rtx
>> + && GET_CODE (alt) == REG)
>> + {
>> + /* Optimize for register value of 0. */
>> + if (op0 == alt && op1 == const0_rtx)
>> + {
>> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
>> + cons = force_reg (mode, cons);
>> + emit_insn (gen_rtx_SET (dest,
>> + gen_rtx_IF_THEN_ELSE (mode, cond,
>> + cons, alt)));
>> + return true;
>> + }
>> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
>> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
>> + rtx temp1 = gen_reg_rtx (mode);
>> + rtx temp2 = GEN_INT(-1 * INTVAL (cons));
>> + riscv_emit_binary(PLUS, temp1, alt, temp2);
>Here you have to be careful if CONS is -2048. You negate it resulting
>in +2048 which can't be used in an addi. This will cause the entire
>sequence to fail due to an unrecognized insn. It would be better to
>handle that scenario directly so the generated sequence is still valid.
>
>By generating recognizable code in that case we let the costing model
>determine if the conditional move sequence is better than the branching
>sequence.
Thank you for pointing out this special situation, it has been fixed
>
>
>> + emit_insn (gen_rtx_SET (dest,
>> + gen_rtx_IF_THEN_ELSE (mode, cond,
>> + const0_rtx, alt)));
>I think we have the same problem with the use of ALT here rather than
>TEMP1 that we had in the previous case.
Fixed
>
>
>
>> + /* reg + imm */
>> + else if (GET_CODE (cons) == REG
>> + && GET_CODE (alt) == CONST_INT && alt != const0_rtx)
>> + {
>> + /* Optimize for register value of 0. */
>> + if (op0 == cons && op1 == const0_rtx)
>> + {
>> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
>> + alt = force_reg (mode, alt);
>> + emit_insn (gen_rtx_SET (dest,
>> + gen_rtx_IF_THEN_ELSE (mode, cond,
>> + cons, alt)));
>> + return true;
>> + }
>> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
>> + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
>> + rtx temp1 = gen_reg_rtx (mode);
>> + rtx temp2 = GEN_INT(-1 * INTVAL (alt));
>> + riscv_emit_binary(PLUS, temp1, cons, temp2);
>> + emit_insn (gen_rtx_SET (dest,
>> + gen_rtx_IF_THEN_ELSE (mode, cond,
>> + temp1, const0_rtx)));
>> + riscv_emit_binary(PLUS, dest, dest, alt);
>> + return true;
>This has basically the same issues as the imm + reg case.
Fixed
>
>
>> + }
>> + /* reg + reg */
>> + else if (GET_CODE (cons) == REG && GET_CODE (alt) == REG)
>> + {
>> + rtx reg1 = gen_reg_rtx (mode);
>> + rtx reg2 = gen_reg_rtx (mode);
>> + riscv_emit_int_compare (&code, &op0, &op1, need_eq_ne_p);
>> + rtx cond1 = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1);
>> + rtx cond2 = gen_rtx_fmt_ee (code == NE ? EQ : NE,
>> + GET_MODE (op0), op0, op1);
>> + emit_insn (gen_rtx_SET (reg2,
>> + gen_rtx_IF_THEN_ELSE (mode, cond2,
>> + const0_rtx, cons)));
>> + emit_insn (gen_rtx_SET (reg1,
>> + gen_rtx_IF_THEN_ELSE (mode, cond1,
>> + const0_rtx, alt)));
>> + riscv_emit_binary(IOR, dest, reg1, reg2);
>> + return true;
>This probably should detect the case where alt or cons is the same as
>op0. Otherwise I would expect the costing model to reject some cases
>that are actually profitable.
>
Fixed
>
>> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
>> index 6b8c2e8e268..b4147c7a79c 100644
>> --- a/gcc/config/riscv/riscv.md
>> +++ b/gcc/config/riscv/riscv.md
>> @@ -2484,7 +2484,7 @@
>> (if_then_else:GPR (match_operand 1 "comparison_operator")
>> (match_operand:GPR 2 "reg_or_0_operand")
>> (match_operand:GPR 3 "sfb_alu_operand")))
>> - "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV"
>> + "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND"
>Note the predicate for operand2 will reject all constants except 0.
>
>Anyway, I'm still cleaning this up and adding the bits from Ventana
>which handle the relational conditions as well as FP conditionals.
>
>Jeff
1 Thank you for Jeff's code review comments. I have made the modifications
and submitted the V2-patch[3/5].
2 For the calculation method of cost, I hope to submit a separate patch[cost]
after the V2-patch[3/5] merged into master, which will focus on explaining
the reasons for calculating cost in the same way as in patch[4/5].
3 At the same time, I realized that for Zicond's series of patches, it would be
better to split them into separate patches and submit them to the community
code review. Therefore, I plan to submit:
V2-patch[3/5]
patch[cost]
V2-patch[4/5]
V2-patch[5/5]
I will only submit subsequent patches after the previous patch enters the master.
4. In V2-patch[3/5], Zicond's cost calculation is not involved, therefore, all test
cases are skipped with "- O0" and "- Os". I will remove the "- Os" constraint from
the test case in patch[cost].
5 The address for V2-patch[3/5] is: https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625781.html
Thanks
Xiao Zeng
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-28 15:09 ` Jeff Law
@ 2023-07-29 9:48 ` Xiao Zeng
0 siblings, 0 replies; 40+ messages in thread
From: Xiao Zeng @ 2023-07-29 9:48 UTC (permalink / raw)
To: jeffreyalaw, Andreas Schwab
Cc: gcc-patches, research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On Fri, Jul 28, 2023 at 11:09:00 PM Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
>On 7/25/23 11:55, Andreas Schwab wrote:
>> On Jul 19 2023, Xiao Zeng wrote:
>>
>>> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
>>> index 38d8eb2fcf5..7e6b24bd232 100644
>>> --- a/gcc/config/riscv/riscv.cc
>>> +++ b/gcc/config/riscv/riscv.cc
>>> @@ -2448,6 +2448,17 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
>>> *total = COSTS_N_INSNS (1);
>>> return true;
>>> }
>>> + else if (TARGET_ZICOND && outer_code == SET &&
>>> + ((GET_CODE (XEXP (x, 1)) == REG && XEXP (x, 2) == const0_rtx) ||
>>> + (GET_CODE (XEXP (x, 2)) == REG && XEXP (x, 1) == const0_rtx) ||
>>> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
>>> + XEXP (x, 1) == XEXP (XEXP (x, 0), 0)) ||
>>> + (GET_CODE (XEXP (x, 1)) == REG && GET_CODE (XEXP (x, 2)) &&
>>> + XEXP (x, 2) == XEXP (XEXP (x, 0), 0))))
>>
>> Line breaks before the operator, not after.
>Also note that && GET_CODE (XEXP (x, 2)) && that appears twice.
This is an error that I will fix in patch[cost] and provide a detailed explanation.
>
>That just verifies the code isn't RTX_UNKNOWN which I suspect isn't what
>the author intended. It probably needs to be adjusted for SUBREGs and
>the pointer equality issues with REGs after reload.
>
>I'll take care of these goofs since the costing ought to be able to move
>forward independently of the improvements Xiao made to generating
>conditional move sequences.
>
>Jeff
After V2-patch[3/5] is accepted, a patch[cost] will be submitted to provide detailed
explanation of this issue. Of course, as Jeff mentioned, some issues will also be fixed.
Thanks
Xiao Zeng
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: Re: [PATCH 0/5] Recognize Zicond extension
2023-07-28 15:03 ` Jeff Law
@ 2023-07-29 10:01 ` Xiao Zeng
0 siblings, 0 replies; 40+ messages in thread
From: Xiao Zeng @ 2023-07-29 10:01 UTC (permalink / raw)
To: jeffreyalaw, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On Fri, Jul 28, 2023 at 11:03:00 PM Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
>On 7/28/23 00:34, Xiao Zeng wrote:
>
>>>>
>>>> Does that work for you?
>>> I'm going to look at 3/5 today pretty closely. Exposing zicond to
>>> mov<node>cc is something we had implemented inside Ventana and I want to
>>> compare/contrast your work with ours.
>>
>> What a coincidence!
>Zicond is a direct descendant of xventanacondops. The only notable
>difference is in their encodings.
It explains the matter.
>
>>
>>>
>>> What I like about yours is it keeps all the logic in riscv.cc rather
>>> than scattering it across riscv.cc and riscv.md.
>>
>> Yes, when I use enough test cases, I cannot find a concise way to optimize
>> all test cases. When I enumerated all possible cases in the mov<mode>cc
>> function of the RISC-V backend, I found a method that satisfied me, which
>> is the method in patch [3/5].
>I got pulled away to another task yesterday, so didn't get as far as I
>wanted. The biggest inight from yesterday was determining that some of
>the cases you're handling in riscv_expand_conditional_move were things
>we were doing inside ifcvt.cc.
>
>The difference is likely because the initial work on zicond here was
>primarily driven by changes to ifcvt. It was only after evaluating that
>initial implementation that we started to the effort to use zicond at
>RTL expansion time.
>
>I could make a case for either approach, but the more I ponder them the
>more I'm inclined to go with something like yours.
>We want to capture
>the cases implementable as a conditional move as early as possible in
>the RTL pipeline rather than relying on ifcvt to catch it later. It
>also avoids polluting ifcvt with transformations that are only likely
>needed on risc-v.
That's why I did this optimization in riscv.cc riscv_expand_conditional_move.
>
>
>>>
>>
>> If it's just for the Zicond instruction set, is it necessary to make judgments
>> outside of eq/ne? After all, it does not support comparison actions other
>> than eq/ne. Of course, it is also possible to use a special technique to use
>> Zicond in non eq/ne comparisons.
>It's not necessary, but it's definitely helpful to cover the other
>conditions. In fact, we can even cover a variety of fp conditions by
>utilizing the sCC type insns.
It would be great if we could do this.
>
>
>So what I'm looking at for patch #3 is to split out the costing bits
>into its own patch which can go forward immediately.
As you expected, V2-patch[3/5] has arrived,
and its address is: https://gcc.gnu.org/pipermail/gcc-patches/2023-July/625781.html
>THen continue
>evaluating the best way to handle unifying the expander/canonicalization
>code.
That's nice.
>Your testcases in patch #3 are particularly helpful to make sure
>we're not missing cases.
Yes, I have always believed that test cases can be redundant, but they cannot
be omitted. As we all know, the compiler will always make some magical changes
without our knowledge, which may not be what we expect. And test cases
can help us stay away from this risk.
>
>Jeff
Thanks
Xiao Zeng
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics
2023-07-26 17:53 ` Jeff Law
@ 2023-08-01 11:18 ` Richard Sandiford
2023-08-02 6:22 ` Jeff Law
0 siblings, 1 reply; 40+ messages in thread
From: Richard Sandiford @ 2023-08-01 11:18 UTC (permalink / raw)
To: Jeff Law via Gcc-patches
Cc: Xiao Zeng, Jeff Law, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain
Jeff Law via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> On 7/19/23 04:11, Xiao Zeng wrote:
>> This patch completes the recognition of the basic semantics
>> defined in the spec, namely:
>>
>> Conditional zero, if condition is equal to zero
>> rd = (rs2 == 0) ? 0 : rs1
>> Conditional zero, if condition is non zero
>> rd = (rs2 != 0) ? 0 : rs1
>>
>> gcc/ChangeLog:
>>
>> * config/riscv/riscv.md: Include zicond.md
>> * config/riscv/zicond.md: New file.
>>
>> gcc/testsuite/ChangeLog:
>>
>> * gcc.target/riscv/zicond-primitiveSemantics.c: New test.
> So I played with this a bit today. I originally thought that using
> match_dup was the right way to go for those 4 secondary patterns. But
> after further pondering it's not ideal.
>
> match_dup will require pointer equality within the RTL structure. That
> could inhibit detection in two cases. First, SUBREGs. SUBREGs are not
> shared. So we'd never match if we had a SUBREG expression.
>
> Second, post register allocation we can have the same looking RTX, but
> it may not be pointer equal.
Where were you seeing the requirement for pointer equality? genrecog.cc
at least uses rtx_equal_p, and I think it has to. E.g. some patterns
use (match_dup ...) to match output and input mems, and mem rtxes
shouldn't be shared.
I'd always understood using matching constraints against other inputs
to be a no-no, since the RA doesn't (and can't reasonably be expected to)
make two non-identical inputs match. So AIUI, using "1" won't lead to
different code generation compared to "r". Both are relying on the RA
happening to do the right thing. But "1" would presumably trigger an
ICE if something goes wrong.
Thanks,
Richard
> The SUBREG issue also means that we don't want to use a REGNO (x) ==
> REGNO (y) style check because those macros are only valid on REG
> expressions. We could strip the SUBREG, but that's usually awkward to
> do in a pattern's condition.
>
> The net result is we probably should use rtx_equal_p which I was hoping
> to avoid. I'm testing with that change to the 4 secondary patterns
> right now. Assuming that passes (and I have no reason to think it
> won't) then I'll go ahead and commit #1 and #2 from this series which is
> all I have time for today.
>
>
>
> Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics
2023-08-01 11:18 ` Richard Sandiford
@ 2023-08-02 6:22 ` Jeff Law
2023-08-02 10:05 ` Richard Sandiford
0 siblings, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-08-02 6:22 UTC (permalink / raw)
To: Jeff Law via Gcc-patches, Xiao Zeng, research_trasio, kito.cheng,
zhengyu, eri-sw-toolchain, richard.sandiford
On 8/1/23 05:18, Richard Sandiford wrote:
>
> Where were you seeing the requirement for pointer equality? genrecog.cc
> at least uses rtx_equal_p, and I think it has to. E.g. some patterns
> use (match_dup ...) to match output and input mems, and mem rtxes
> shouldn't be shared.
It's a general concern due to the way we handle transforming pseudos
into hard registers after allocation is complete. We can end up with
two REG expressions that will compare equal according to rtx_equal_p,
but which are not pointer equal.
For this kit I think the worst that would happen would be a failure to
optimize cases post-reload. But it's still good RTL hygene IMHO.
>
> I'd always understood using matching constraints against other inputs
> to be a no-no, since the RA doesn't (and can't reasonably be expected to)
> make two non-identical inputs match. So AIUI, using "1" won't lead to
> different code generation compared to "r". Both are relying on the RA
> happening to do the right thing. But "1" would presumably trigger an
> ICE if something goes wrong.
Yea, I think you're right. The constraint isn't terribly important for
these patterns -- the condition is really the enforcement mechanism.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-19 10:11 ` [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 Xiao Zeng
` (2 preceding siblings ...)
2023-07-28 20:59 ` Jeff Law
@ 2023-08-02 6:34 ` Jeff Law
3 siblings, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-08-02 6:34 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
[-- Attachment #1: Type: text/plain, Size: 495 bytes --]
On 7/19/23 04:11, Xiao Zeng wrote:
> This patch completes the recognition of Zicond when the select pattern
> with condition eq or neq to 0 (using equality as an example), namely:
[ ... ]
I've committed the attached patch which implements a simple cost model
for using Zicond to implement conditional moves.
I've changed it to give the proper cost (COSTS_N_INSNS (1) and removed
the extraneous GET_CODE (object) tests adjusted the ChangeLog a bit and
pushed it to the trunk.
Thanks!
Jeff
[-- Attachment #2: P --]
[-- Type: text/plain, Size: 1852 bytes --]
commit 5b501863ac7da57858fdd464dfb7a776143f22a2
Author: Xiao Zeng <zengxiao@eswincomputing.com>
Date: Wed Aug 2 00:17:12 2023 -0600
[PATCH 3/5] [RISC-V] Cost model for Zicond.
This patch implements a reasonable cost model for using Zicond to
implement conditional moves. Essentially the Zicond insns are always
COSTS_N_INSNS (1).
Note there is still a problem with the costing model in general that
results in failure to if-convert as often as we should. In simplest
terms the insn costing model sums the cost of the SET_SRC and the
cost of the SET_DEST. Thus the conditional move is considered twice
as costly as it should be. That will have to be addressed separately.
gcc/
* config/riscv/riscv.cc (riscv_rtx_costs): Add costing for
using Zicond to implement some conditional moves.
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 8c474503080..785e09c76ce 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2518,6 +2518,20 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
*total = COSTS_N_INSNS (1);
return true;
}
+ else if (TARGET_ZICOND
+ && outer_code == SET
+ && ((GET_CODE (XEXP (x, 1)) == REG
+ && XEXP (x, 2) == CONST0_RTX (GET_MODE (XEXP (x, 1))))
+ || (GET_CODE (XEXP (x, 2)) == REG
+ && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 2))))
+ || (GET_CODE (XEXP (x, 1)) == REG
+ && rtx_equal_p (XEXP (x, 1), XEXP (XEXP (x, 0), 0)))
+ || (GET_CODE (XEXP (x, 1)) == REG
+ && rtx_equal_p (XEXP (x, 2), XEXP (XEXP (x, 0), 0)))))
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
else if (LABEL_REF_P (XEXP (x, 1)) && XEXP (x, 2) == pc_rtx)
{
if (equality_operator (XEXP (x, 0), mode)
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics
2023-08-02 6:22 ` Jeff Law
@ 2023-08-02 10:05 ` Richard Sandiford
2023-08-02 16:56 ` Jeff Law
0 siblings, 1 reply; 40+ messages in thread
From: Richard Sandiford @ 2023-08-02 10:05 UTC (permalink / raw)
To: Jeff Law via Gcc-patches
Cc: Xiao Zeng, research_trasio, kito.cheng, zhengyu,
eri-sw-toolchain, Jeff Law
Jeff Law via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> On 8/1/23 05:18, Richard Sandiford wrote:
>>
>> Where were you seeing the requirement for pointer equality? genrecog.cc
>> at least uses rtx_equal_p, and I think it has to. E.g. some patterns
>> use (match_dup ...) to match output and input mems, and mem rtxes
>> shouldn't be shared.
> It's a general concern due to the way we handle transforming pseudos
> into hard registers after allocation is complete. We can end up with
> two REG expressions that will compare equal according to rtx_equal_p,
> but which are not pointer equal.
But isn't that OK? I don't think there's a requirement for match_dup
pointer equality either before or after RA. Or at least, there
shouldn't be. If something happens to rely on pointer equality
for match_dups then I think we should fix it.
So IMO, like you said originally, match_dup would be the right way to
handle this kind of pattern.
The reason I'm interested is that AArch64 makes pretty extensive use
of match_dup for this purpose. E.g.:
(define_insn "aarch64_<su>abd<mode><vczle><vczbe>"
[(set (match_operand:VDQ_BHSI 0 "register_operand" "=w")
(minus:VDQ_BHSI
(USMAX:VDQ_BHSI
(match_operand:VDQ_BHSI 1 "register_operand" "w")
(match_operand:VDQ_BHSI 2 "register_operand" "w"))
(<max_opp>:VDQ_BHSI
(match_dup 1)
(match_dup 2))))]
So if this isn't working correctly for subregs (or for anythine else),
then I'd be keen to do something about it :)
I don't want to labour the point though.
Thanks,
Richard
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics
2023-08-02 10:05 ` Richard Sandiford
@ 2023-08-02 16:56 ` Jeff Law
0 siblings, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-08-02 16:56 UTC (permalink / raw)
To: Jeff Law via Gcc-patches, Xiao Zeng, research_trasio, kito.cheng,
zhengyu, eri-sw-toolchain, richard.sandiford
On 8/2/23 04:05, Richard Sandiford wrote:
> Jeff Law via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>> On 8/1/23 05:18, Richard Sandiford wrote:
>>>
>>> Where were you seeing the requirement for pointer equality? genrecog.cc
>>> at least uses rtx_equal_p, and I think it has to. E.g. some patterns
>>> use (match_dup ...) to match output and input mems, and mem rtxes
>>> shouldn't be shared.
>> It's a general concern due to the way we handle transforming pseudos
>> into hard registers after allocation is complete. We can end up with
>> two REG expressions that will compare equal according to rtx_equal_p,
>> but which are not pointer equal.
>
> But isn't that OK? I don't think there's a requirement for match_dup
> pointer equality either before or after RA. Or at least, there
> shouldn't be. If something happens to rely on pointer equality
> for match_dups then I think we should fix it.
>
> So IMO, like you said originally, match_dup would be the right way to
> handle this kind of pattern.
I'd assumed that match_dup required pointer equality. If it doesn't,
then great, we can adjust the pattern to use match_dup. I'm about to
submit some bits to simplify/correct a bit of zicond.md, then I can do
some testing with match_dup in place now that things seem to be more
stable on the code generation correctness side.
>
> I don't want to labour the point though.
No worries about that on my end! I probably don't say it enough, but
when you raise an issue, it's worth the time to make sure I understand
your point thoroughly.
In this case I'd assumed that match_dup relied on pointer equality which
doesn't seem to be the case. 30+ years into this codebase and I'm still
learning new stuff!
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 0/5] Recognize Zicond extension
2023-07-28 6:34 ` Xiao Zeng
2023-07-28 15:03 ` Jeff Law
@ 2023-08-03 2:59 ` Jeff Law
1 sibling, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-08-03 2:59 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/28/23 00:34, Xiao Zeng wrote:
>
>>
>> What I like about yours is it keeps all the logic in riscv.cc rather
>> than scattering it across riscv.cc and riscv.md.
>
> Yes, when I use enough test cases, I cannot find a concise way to optimize
> all test cases. When I enumerated all possible cases in the mov<mode>cc
> function of the RISC-V backend, I found a method that satisfied me, which
> is the method in patch [3/5].
I continue to work with the riscv_expand_conditional_move improvements.
Given the deeper problems we have with costing, I'm considering starting
to push some of the riscv_expand_conditional_move work you've done
without the testcases since those testcases depend on fixing the costing
problems.
The expansion changes still have value without the costing changes.
When we expand a COND_EXPR from gimple, we will attempt to use the
conditional move pattern first, without regard for costing.
>
> If it's just for the Zicond instruction set, is it necessary to make judgments
> outside of eq/ne? After all, it does not support comparison actions other
> than eq/ne. Of course, it is also possible to use a special technique to use
> Zicond in non eq/ne comparisons.
It's not necessary, but it's certainly helpful to utilize sCC insns in
conjuction with zicond to if-convert other conditional branches. It's
conceptually pretty simple.
If the incoming code is not EQ/NE or we're not comparing a register
against 0, then we can emit an scc insn to get the comparison result
into a temporary, then use the standard zicond expansions.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-07-29 9:14 ` Xiao Zeng
@ 2023-08-03 4:59 ` Jeff Law
0 siblings, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-08-03 4:59 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/29/23 03:14, Xiao Zeng wrote:
>
> 1 Thank you for Jeff's code review comments. I have made the modifications
> and submitted the V2-patch[3/5].
Yea. I'm adjusting my tree based on those updates. For testing I've
actually got my compiler generating zicond by default and qemu allowing
zicond by default. I can then run the execute.exp tests which validate
code correctness to a reasonable degree.
>
> 2 For the calculation method of cost, I hope to submit a separate patch[cost]
> after the V2-patch[3/5] merged into master, which will focus on explaining
> the reasons for calculating cost in the same way as in patch[4/5].
I think the costing problem is going to require its own little
subproject. GCC's approach to costing is a bit crazy with multiple APIs
that behave differently and in some cases do some rather surprising
things. It's a long standing design flaw.
The point being that I think we'll probably move forward with the
functional bits, perhaps initially without the basic functionality
tests. That allows folks to start utilizing the core functionality
while we audit and likely adjust the risc-v cost hook implementation.
>
> 4. In V2-patch[3/5], Zicond's cost calculation is not involved, therefore, all test
> cases are skipped with "- O0" and "- Os". I will remove the "- Os" constraint from
> the test case in patch[cost].
We may need to avoid for -Og as well. I've got that change here
locally, but I wanted to go back and review that as well.
jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 4/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to non-zero
2023-07-19 10:11 ` [PATCH 4/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to non-zero Xiao Zeng
@ 2023-08-07 17:36 ` Jeff Law
0 siblings, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-08-07 17:36 UTC (permalink / raw)
To: Xiao Zeng, gcc-patches
Cc: research_trasio, kito.cheng, zhengyu, eri-sw-toolchain
On 7/19/23 04:11, Xiao Zeng wrote:
> This patch completes the recognition of Zicond when the select pattern with
> condition eq or neq to non-zero (using equality as an example), namely:
>
> 1 rd = (rs2 == non-imm) ? 0 : rs1
> 2 rd = (rs2 == reg) ? 0 : rs1
>
> At the same time, more Zicond non basic semantic test cases have been added.
>
> gcc/ChangeLog:
>
> * config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize Zicond.
I think this is handled by the changes from Raphael I just committed.
But I do think we should take the testsuite work to verify the cases all
work as expected.
Given the testcases from 3/5 are also on hold pending fixing the costing
issues, I'm thinking to roll all the testsuite changes into a distinct
patch, with the failing tests xfailed until we fix the costing work.
But I definitely don't want to lose the tests.
jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-08-03 14:56 ` Kito Cheng
@ 2023-08-03 15:09 ` Jeff Law
0 siblings, 0 replies; 40+ messages in thread
From: Jeff Law @ 2023-08-03 15:09 UTC (permalink / raw)
To: Kito Cheng
Cc: Robin Dapp, gcc-patches, kito.cheng, zengxiao, 钟居哲
On 8/3/23 08:56, Kito Cheng wrote:
>>>> That'll be the first thing to look at. THe costing change was supposed
>>>> only affect if-then-else constructs, not sets in general.
>>>
>>>
>>> If so, I think the most simple fix is adding more checks on the set
>>> cost - only check the SET_SRC is if-then-else?
>> No, the simple fix is to just remove the errant part of the commit :-0
>> My tests aren't done, but that does seem to dramatically help. Given it
>> wasn't supposed to go in as-is and it's causing major problems, I'll
>> probably just rip it out even though my testing isn't done.
>
> OK, so I'm going to retreat from there, I've another lld issue that
> needs to be fixed before the LLVM 17 release :)
Reversion of errant hunk has been pushed. Sorry for the problems folks.
Had I known it was going to have this kind of fallout, I would have
slammed a coke and fixed it last night before doing to sleep :-0
And yes, focusing on the lld issue seems wise given what I'm hearing in
the LLVM meeting.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-08-03 14:41 ` Jeff Law
@ 2023-08-03 14:56 ` Kito Cheng
2023-08-03 15:09 ` Jeff Law
0 siblings, 1 reply; 40+ messages in thread
From: Kito Cheng @ 2023-08-03 14:56 UTC (permalink / raw)
To: Jeff Law
Cc: Robin Dapp, gcc-patches, kito.cheng, zengxiao, 钟居哲
> >> That'll be the first thing to look at. THe costing change was supposed
> >> only affect if-then-else constructs, not sets in general.
> >
> >
> > If so, I think the most simple fix is adding more checks on the set
> > cost - only check the SET_SRC is if-then-else?
> No, the simple fix is to just remove the errant part of the commit :-0
> My tests aren't done, but that does seem to dramatically help. Given it
> wasn't supposed to go in as-is and it's causing major problems, I'll
> probably just rip it out even though my testing isn't done.
OK, so I'm going to retreat from there, I've another lld issue that
needs to be fixed before the LLVM 17 release :)
>
> >
> > Let me run the regression to see if that works - although the current
> > vsetvli cost is too high (4x~5x), but I think it should be fixed later
> > with a more complete expermantal.
> Exactly. I think we need to do a full audit of the costing paths. I've
> been slowly devising a way to do that and I'll probably give it to
> Raphael or Jivan once I've fleshed it out a bit more in my head.
>
> The goal is to make sure the costs are sensible and consistent across
> the different interfaces. A cost failure is actually a bit hard to find
> because all that happens is you get the wrong set of transformations --
> but the code still works correctly, it's just not as efficient as it
> should be. It doesn't have to be perfect, but we've clearly got a problem.
>
> WRT vsetvli costing. That may ultimately be something that's uarch
> dependent. We're working on the assumption that vsetvlis are common in
> the code stream and they need to be very efficient from the hardware
> standpoint (think as cheap or cheaper than any simple ALU instruction).
> I probably can't say what we're doing, but I bet it wouldn't be a
> surprise to others doing a high performance V implementation.
Yeah, it should be cheap, but might be expensive on some HW implementation,
anyway our cost model really needs to be tidy up at some point...:P
> jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-08-03 14:31 ` Kito Cheng
@ 2023-08-03 14:41 ` Jeff Law
2023-08-03 14:56 ` Kito Cheng
0 siblings, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-08-03 14:41 UTC (permalink / raw)
To: Kito Cheng
Cc: Robin Dapp, gcc-patches, kito.cheng, zengxiao, 钟居哲
On 8/3/23 08:31, Kito Cheng wrote:
>>> I am working on that, it seems the cost of vsetvli instruction become 0
>>> due to this change, then loop invariant motion won't hoist vsetvli longer.
>> I haven't looked yet (generating baseline rvv.exp data right now). But
>> before I went to bed last night I was worried that a change snuck
>> through that shouldn't have (changing the toplevel INSN/SET cost
>> handling -- that wasn't supposed to be in the commit). I was too tired
>> to verify and correct without possibly mucking it up further.
>>
>> That'll be the first thing to look at. THe costing change was supposed
>> only affect if-then-else constructs, not sets in general.
>
>
> If so, I think the most simple fix is adding more checks on the set
> cost - only check the SET_SRC is if-then-else?
No, the simple fix is to just remove the errant part of the commit :-0
My tests aren't done, but that does seem to dramatically help. Given it
wasn't supposed to go in as-is and it's causing major problems, I'll
probably just rip it out even though my testing isn't done.
>
> Let me run the regression to see if that works - although the current
> vsetvli cost is too high (4x~5x), but I think it should be fixed later
> with a more complete expermantal.
Exactly. I think we need to do a full audit of the costing paths. I've
been slowly devising a way to do that and I'll probably give it to
Raphael or Jivan once I've fleshed it out a bit more in my head.
The goal is to make sure the costs are sensible and consistent across
the different interfaces. A cost failure is actually a bit hard to find
because all that happens is you get the wrong set of transformations --
but the code still works correctly, it's just not as efficient as it
should be. It doesn't have to be perfect, but we've clearly got a problem.
WRT vsetvli costing. That may ultimately be something that's uarch
dependent. We're working on the assumption that vsetvlis are common in
the code stream and they need to be very efficient from the hardware
standpoint (think as cheap or cheaper than any simple ALU instruction).
I probably can't say what we're doing, but I bet it wouldn't be a
surprise to others doing a high performance V implementation.
jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-08-03 14:08 ` Jeff Law
@ 2023-08-03 14:31 ` Kito Cheng
2023-08-03 14:41 ` Jeff Law
0 siblings, 1 reply; 40+ messages in thread
From: Kito Cheng @ 2023-08-03 14:31 UTC (permalink / raw)
To: Jeff Law
Cc: Robin Dapp, gcc-patches, kito.cheng, zengxiao, 钟居哲
> > I am working on that, it seems the cost of vsetvli instruction become 0
> > due to this change, then loop invariant motion won't hoist vsetvli longer.
> I haven't looked yet (generating baseline rvv.exp data right now). But
> before I went to bed last night I was worried that a change snuck
> through that shouldn't have (changing the toplevel INSN/SET cost
> handling -- that wasn't supposed to be in the commit). I was too tired
> to verify and correct without possibly mucking it up further.
>
> That'll be the first thing to look at. THe costing change was supposed
> only affect if-then-else constructs, not sets in general.
If so, I think the most simple fix is adding more checks on the set
cost - only check the SET_SRC is if-then-else?
Let me run the regression to see if that works - although the current
vsetvli cost is too high (4x~5x), but I think it should be fixed later
with a more complete expermantal.
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-08-03 13:56 ` Kito Cheng
@ 2023-08-03 14:08 ` Jeff Law
2023-08-03 14:31 ` Kito Cheng
0 siblings, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-08-03 14:08 UTC (permalink / raw)
To: Kito Cheng
Cc: 钟居哲, gcc-patches, kito.cheng, Robin Dapp, zengxiao
On 8/3/23 07:56, Kito Cheng wrote:
> I am working on that, it seems the cost of vsetvli instruction become 0
> due to this change, then loop invariant motion won't hoist vsetvli longer.
I haven't looked yet (generating baseline rvv.exp data right now). But
before I went to bed last night I was worried that a change snuck
through that shouldn't have (changing the toplevel INSN/SET cost
handling -- that wasn't supposed to be in the commit). I was too tired
to verify and correct without possibly mucking it up further.
That'll be the first thing to look at. THe costing change was supposed
only affect if-then-else constructs, not sets in general.
Jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-08-03 13:49 ` Jeff Law
@ 2023-08-03 13:56 ` Kito Cheng
2023-08-03 14:08 ` Jeff Law
0 siblings, 1 reply; 40+ messages in thread
From: Kito Cheng @ 2023-08-03 13:56 UTC (permalink / raw)
To: Jeff Law
Cc: 钟居哲, gcc-patches, kito.cheng, Robin Dapp, zengxiao
[-- Attachment #1: Type: text/plain, Size: 771 bytes --]
I am working on that, it seems the cost of vsetvli instruction become 0 due
to this change, then loop invariant motion won't hoist vsetvli longer.
Jeff Law <jeffreyalaw@gmail.com> 於 2023年8月3日 週四 21:49 寫道:
>
>
> On 8/3/23 03:27, juzhe.zhong@rivai.ai wrote:
> >
> https://github.com/gcc-mirror/gcc/commit/e15d0b6680d10d7666195e9db65581364ad5e5df
> <
> https://github.com/gcc-mirror/gcc/commit/e15d0b6680d10d7666195e9db65581364ad5e5df
> >
> >
> > This patch causes so many fails in the regression:
> Mine. I'll take care of it. Probably something slipping through the
> expander that shouldn't. I've been primarily focused on the execute.exp
> part of the suite to find code correctness issues with the original patch.
>
> jeff
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
2023-08-03 9:27 [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 juzhe.zhong
@ 2023-08-03 13:49 ` Jeff Law
2023-08-03 13:56 ` Kito Cheng
0 siblings, 1 reply; 40+ messages in thread
From: Jeff Law @ 2023-08-03 13:49 UTC (permalink / raw)
To: juzhe.zhong, gcc-patches; +Cc: Kito.cheng, kito.cheng, Robin Dapp, zengxiao
On 8/3/23 03:27, juzhe.zhong@rivai.ai wrote:
> https://github.com/gcc-mirror/gcc/commit/e15d0b6680d10d7666195e9db65581364ad5e5df <https://github.com/gcc-mirror/gcc/commit/e15d0b6680d10d7666195e9db65581364ad5e5df>
>
> This patch causes so many fails in the regression:
Mine. I'll take care of it. Probably something slipping through the
expander that shouldn't. I've been primarily focused on the execute.exp
part of the suite to find code correctness issues with the original patch.
jeff
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
@ 2023-08-03 9:27 juzhe.zhong
2023-08-03 13:49 ` Jeff Law
0 siblings, 1 reply; 40+ messages in thread
From: juzhe.zhong @ 2023-08-03 9:27 UTC (permalink / raw)
To: gcc-patches; +Cc: Kito.cheng, kito.cheng, Robin Dapp, zengxiao, jeffreyalaw
[-- Attachment #1: Type: text/plain, Size: 16504 bytes --]
https://github.com/gcc-mirror/gcc/commit/e15d0b6680d10d7666195e9db65581364ad5e5df
This patch causes so many fails in the regression:
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O1 scan-assembler-times vsetvli 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-40.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf2,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O2 scan-assembler-times vsetvli 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+j\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/avl_single-79.c -Os scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e32,\\s*mf2,\\s*tu,\\s*mu 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-40.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf2,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+j\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-40.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf2,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/imm_loop_invariant-5.c -Os scan-assembler-times \\.L[0-9]+\\:\\s+vle64\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 8
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-2.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+j\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/avl_multiple-10.c -O1 scan-assembler-times \\.L[0-9]+\\:\\s+add\\s+\\s*[a-x0-9]+,\\s*[a-x0-9]+,\\s*[a-x0-9]+\\s+vle8\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-41.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf2,\\s*t[au],\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-41.c -O2 scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-3.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf8,\\s*t[au],\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-3.c -O2 scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-41.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf2,\\s*t[au],\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-41.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-3.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf8,\\s*t[au],\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-3.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-41.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf2,\\s*t[au],\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-41.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvlmax-2.c -Os scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-3.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf8,\\s*t[au],\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-3.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/imm_loop_invariant-6.c -Os scan-assembler-times \\.L[0-9]+\\:\\s+vle64\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 4
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-4.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-4.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]:+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-4.c -O2 scan-assembler-times vsetvli 5
FAIL: gcc.target/riscv/rvv/vsetvl/avl_single-80.c -Os scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e32,\\s*mf2,\\s*tu,\\s*mu 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-4.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-4.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]:+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-4.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 5
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-4.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-4.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]:+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-4.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 5
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-5.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 4
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-5.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]:+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-5.c -O2 scan-assembler-times vsetvli 7
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-5.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 4
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-5.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]:+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-5.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 7
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-5.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 4
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-5.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]:+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-5.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 7
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvlmax-3.c -Os scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e32,\\s*m1,\\s*tu,\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/avl_single-72.c -Os scan-assembler-times vsetvli\\s+zero,\\s*[a-x0-9]+,\\s*e32,\\s*mf2,\\s*tu,\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/avl_single-72.c -Os scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvlmax-4.c -Os scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e32,\\s*m1,\\s*tu,\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvlmax-4.c -Os scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-45.c -O2 scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-7.c -O2 scan-assembler-times vsetvli 4
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-7.c -O2 scan-assembler-times j\\s+\\.L[0-9]+\\s+\\.L[0-9]+:\\s+vlm\\.v 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-7.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 3
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvlmax-5.c -O1 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e32,\\s*m1,\\s*tu,\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvlmax-5.c -O1 scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-7.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 4
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-7.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times j\\s+\\.L[0-9]+\\s+\\.L[0-9]+:\\s+vlm\\.v 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-7.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-45.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-7.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 4
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-7.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times j\\s+\\.L[0-9]+\\s+\\.L[0-9]+:\\s+vlm\\.v 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-7.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_back_prop-45.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvlmax-5.c -Os scan-assembler-times vsetvli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-8.c -O2 scan-assembler-times vsetvli 5
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-8.c -O2 scan-assembler-times j\\s+\\.L[0-9]+\\s+\\.L[0-9]+:\\s+vlm\\.v 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-8.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 3
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvl-6.c -O1 scan-assembler-times \\.L[0-9]+\\:\\s+vle32\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 2
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-8.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 5
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-8.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times j\\s+\\.L[0-9]+\\s+\\.L[0-9]+:\\s+vlm\\.v 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-8.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 3
FAIL: gcc.target/riscv/rvv/autovec/conversions/vncvt-run.c (internal compiler error: internal consistency failure)
FAIL: gcc.target/riscv/rvv/autovec/conversions/vncvt-run.c (test for excess errors)
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-8.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 5
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-8.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times j\\s+\\.L[0-9]+\\s+\\.L[0-9]+:\\s+vlm\\.v 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-8.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*m8,\\s*t[au],\\s*m[au] 3
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvlmax-6.c -Os scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e32,\\s*m1,\\s*tu,\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-9.c -O2 scan-assembler-times vsetvli 7
FAIL: gcc.target/riscv/rvv/autovec/conversions/vzext-run.c (internal compiler error: internal consistency failure)
FAIL: gcc.target/riscv/rvv/autovec/conversions/vzext-run.c (test for excess errors)
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-9.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 7
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-9.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 7
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvl-7.c -Os scan-assembler-times vsetvli\\s+zero,\\s*[a-x0-9]+,\\s*e32,\\s*m1,\\s*tu,\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/imm_loop_invariant-2.c -Os scan-assembler-times \\.L[0-9]+\\:\\s+vle16\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 12
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvl-8.c -O1 scan-assembler-times \\.L[0-9]+\\:\\s+vle32\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 2
FAIL: gcc.target/riscv/rvv/vsetvl/avl_single-40.c -Os scan-assembler-times \\.L[0-9]+\\:\\s+vsetvli\\s+zero,\\s*[a-x0-9]+,\\s*e8,\\s*mf8,\\s*tu,\\s*m[au]\\s+vle8\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 1
FAIL: gcc.target/riscv/rvv/vsetvl/vsetvl-8.c -Os scan-assembler-times vsetvli\\s+zero,\\s*[a-x0-9]+,\\s*e32,\\s*m1,\\s*tu,\\s*m[au] 1
FAIL: gcc.target/riscv/rvv/vsetvl/avl_multiple-9.c -O1 scan-assembler-times \\.L[0-9]+\\:\\s+add\\s+\\s*[a-x0-9]+,\\s*[a-x0-9]+,\\s*[a-x0-9]+\\s+vle8\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O1 scan-assembler-times vsetvli 3
FAIL: gcc.target/riscv/rvv/vsetvl/imm_loop_invariant-1.c -Os scan-assembler-times \\.L[0-9]+\\:\\s+vle8\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 14
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O2 scan-assembler-times vsetvli 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]+\\: 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O2 scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf8,\\s*t[au],\\s*m[au]\\s+j\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/imm_loop_invariant-3.c -Os scan-assembler-times \\.L[0-9]+\\:\\s+vle32\\.v\\s+v[0-9]+,\\s*0\\s*\\([a-x0-9]+\\) 10
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]+\\: 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O2 -flto -fno-use-linker-plugin -flto-partition=none scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf8,\\s*t[au],\\s*m[au]\\s+j\\s+\\.L[0-9]+ 1
FAIL: gcc.target/riscv/rvv/vsetvl/avl_single-78.c -Os scan-assembler-times vsetivli\\s+zero,\\s*4,\\s*e32,\\s*mf2,\\s*tu,\\s*mu 1
FAIL: gcc.target/riscv/rvv/vsetvl/avl_single-78.c -Os scan-assembler-times vsetivli 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli 3
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf8,\\s*t[au],\\s*m[au]\\s+\\.L[0-9]+\\: 1
FAIL: gcc.target/riscv/rvv/vsetvl/vlmax_conflict-1.c -O2 -flto -fuse-linker-plugin -fno-fat-lto-objects scan-assembler-times vsetvli\\s+[a-x0-9]+,\\s*zero,\\s*e8,\\s*mf8,\\s*t[au],\\s*m[au]\\s+j\\s+\\.L[
juzhe.zhong@rivai.ai
^ permalink raw reply [flat|nested] 40+ messages in thread
end of thread, other threads:[~2023-08-07 17:36 UTC | newest]
Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-19 10:11 [PATCH 0/5] Recognize Zicond extension Xiao Zeng
2023-07-19 10:11 ` [PATCH 1/5] [RISC-V] " Xiao Zeng
2023-07-25 16:35 ` Jeff Law
2023-07-26 21:11 ` Jeff Law
2023-07-19 10:11 ` [PATCH 2/5] [RISC-V] Generate Zicond instruction for basic semantics Xiao Zeng
2023-07-25 16:35 ` Jeff Law
2023-07-26 17:53 ` Jeff Law
2023-08-01 11:18 ` Richard Sandiford
2023-08-02 6:22 ` Jeff Law
2023-08-02 10:05 ` Richard Sandiford
2023-08-02 16:56 ` Jeff Law
2023-07-26 21:14 ` Jeff Law
2023-07-19 10:11 ` [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 Xiao Zeng
2023-07-25 17:32 ` Jeff Law
2023-07-25 17:55 ` Andreas Schwab
2023-07-27 5:44 ` Xiao Zeng
2023-07-28 15:09 ` Jeff Law
2023-07-29 9:48 ` Xiao Zeng
2023-07-28 20:59 ` Jeff Law
2023-07-29 9:14 ` Xiao Zeng
2023-08-03 4:59 ` Jeff Law
2023-08-02 6:34 ` Jeff Law
2023-07-19 10:11 ` [PATCH 4/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to non-zero Xiao Zeng
2023-08-07 17:36 ` Jeff Law
2023-07-19 10:11 ` [PATCH 5/5] [RISC-V] Generate Zicond instruction for conditional execution Xiao Zeng
2023-07-25 17:51 ` [PATCH 0/5] Recognize Zicond extension Jeff Law
2023-07-27 8:43 ` Xiao Zeng
2023-07-27 14:43 ` Jeff Law
2023-07-28 6:34 ` Xiao Zeng
2023-07-28 15:03 ` Jeff Law
2023-07-29 10:01 ` Xiao Zeng
2023-08-03 2:59 ` Jeff Law
2023-08-03 9:27 [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 juzhe.zhong
2023-08-03 13:49 ` Jeff Law
2023-08-03 13:56 ` Kito Cheng
2023-08-03 14:08 ` Jeff Law
2023-08-03 14:31 ` Kito Cheng
2023-08-03 14:41 ` Jeff Law
2023-08-03 14:56 ` Kito Cheng
2023-08-03 15:09 ` Jeff Law
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).