Message ID | 20240621144612.122744-1-artemiy@synopsys.com |
---|---|
State | New |
Headers | show |
Series | RISC-V: Fix unrecognizable pattern in riscv_expand_conditional_move() | expand |
On 6/21/24 8:46 AM, Artemiy Volkov wrote: > Presently, the code fragment: > > int x[5]; > > void > d(int a, int b, int c) { > for (int i = 0; i < 5; i++) > x[i] = (a != b) ? c : a; > } > > causes an ICE when compiled with -O2 -march=rv32i_zicond: > > test.c: In function 'd': > test.c: error: unrecognizable insn: > 11 | } > | ^ > (insn 8 5 9 2 (set (reg:SI 139 [ iftmp.0_2 ]) > (if_then_else:SI (ne:SI (reg/v:SI 136 [ a ]) > (reg/v:SI 137 [ b ])) > (reg/v:SI 136 [ a ]) > (reg/v:SI 138 [ c ]))) -1 > (nil)) > during RTL pass: vregs > > This happens because, as part of one of the optimizations in > riscv_expand_conditional_move(), an if_then_else is generated with both > comparands being register operands, resulting in an unmatchable insn since > Zicond patterns require constant 0 as the second comparand. Fix this by adding > a extra check before performing this optimization. > > The code snippet mentioned above is also included in this patch as a new Zicond > testcase. > > gcc/ChangeLog: > > * config/riscv/riscv.cc (riscv_expand_conditional_move): Add a > CONST0_RTX check. > > gcc/testsuite/ChangeLog: > > * gcc.target/riscv/zicond-ice-3.c: New test. I've pushed this to the trunk. Thanks Artemiy! Jeff
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 029c80b21cf..6c58687b5e5 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -4674,8 +4674,9 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt) /* reg, reg */ else if (REG_P (cons) && REG_P (alt)) { - if ((code == EQ && rtx_equal_p (cons, op0)) + if (((code == EQ && rtx_equal_p (cons, op0)) || (code == NE && rtx_equal_p (alt, op0))) + && op1 == CONST0_RTX (mode)) { rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); if (!rtx_equal_p (cons, op0)) diff --git a/gcc/testsuite/gcc.target/riscv/zicond-ice-3.c b/gcc/testsuite/gcc.target/riscv/zicond-ice-3.c new file mode 100644 index 00000000000..ac6049c9ae5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zicond-ice-3.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_zicond -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mabi=ilp32f" { target { rv32 } } } */ + +int x[5]; + +void +d(int a, int b, int c) { + for (int i = 0; i < 5; i++) + x[i] = (a != b) ? c : a; +}
Presently, the code fragment: int x[5]; void d(int a, int b, int c) { for (int i = 0; i < 5; i++) x[i] = (a != b) ? c : a; } causes an ICE when compiled with -O2 -march=rv32i_zicond: test.c: In function 'd': test.c: error: unrecognizable insn: 11 | } | ^ (insn 8 5 9 2 (set (reg:SI 139 [ iftmp.0_2 ]) (if_then_else:SI (ne:SI (reg/v:SI 136 [ a ]) (reg/v:SI 137 [ b ])) (reg/v:SI 136 [ a ]) (reg/v:SI 138 [ c ]))) -1 (nil)) during RTL pass: vregs This happens because, as part of one of the optimizations in riscv_expand_conditional_move(), an if_then_else is generated with both comparands being register operands, resulting in an unmatchable insn since Zicond patterns require constant 0 as the second comparand. Fix this by adding a extra check before performing this optimization. The code snippet mentioned above is also included in this patch as a new Zicond testcase. gcc/ChangeLog: * config/riscv/riscv.cc (riscv_expand_conditional_move): Add a CONST0_RTX check. gcc/testsuite/ChangeLog: * gcc.target/riscv/zicond-ice-3.c: New test. Signed-off-by: Artemiy Volkov <artemiy@synopsys.com> --- gcc/config/riscv/riscv.cc | 3 ++- gcc/testsuite/gcc.target/riscv/zicond-ice-3.c | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-ice-3.c