diff options
author | Artemiy Volkov <Artemiy.Volkov@synopsys.com> | 2024-06-23 14:54:00 -0600 |
---|---|---|
committer | Jeff Law <jlaw@ventanamicro.com> | 2024-06-23 14:54:56 -0600 |
commit | eb647daa87b466d0a71246fad302cd81bfce9be5 (patch) | |
tree | 7b35d1941e1744e83c2a5f098341704e8b42714f /gcc | |
parent | fd536b8412d4dae42aa04739c06f99a915be6261 (diff) | |
download | gcc-eb647daa87b466d0a71246fad302cd81bfce9be5.zip gcc-eb647daa87b466d0a71246fad302cd81bfce9be5.tar.gz gcc-eb647daa87b466d0a71246fad302cd81bfce9be5.tar.bz2 |
[PATCH] RISC-V: Fix unrecognizable pattern in riscv_expand_conditional_move()
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-5.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/riscv/riscv.cc | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/riscv/zicond-ice-5.c | 11 |
2 files changed, 13 insertions, 1 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 5c758b9..cca7ffd 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -5111,8 +5111,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); alt = force_reg (mode, alt); diff --git a/gcc/testsuite/gcc.target/riscv/zicond-ice-5.c b/gcc/testsuite/gcc.target/riscv/zicond-ice-5.c new file mode 100644 index 0000000..ac6049c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zicond-ice-5.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; +} |