https://gcc.gnu.org/g:b93d8873cda88f0892c7782b274904fa8d3751fb
commit r16-1392-gb93d8873cda88f0892c7782b274904fa8d3751fb Author: Jeff Law <j...@ventanamicro.com> Date: Tue Jun 10 06:38:52 2025 -0600 [RISC-V] Fix ICE due to splitter emitting constant loads directly This is a fix for a bug found internally in Ventana using the cf3 testsuite. cf3 looks to be dead as a project and likely subsumed by modern fuzzers. In fact internally we tripped another issue with cf3 that had already been reported by Edwin with the fuzzer he runs. Anyway, the splitter in question blindly emits the 2nd adjusted constant into a register, that's not valid if the constant requires any kind of synthesis -- and it well could since we're mostly focused on the first constant turning into something that can be loaded via LUI without increasing the cost of the second constant. Instead of using the split RTL template, this just emits the code we want directly, using riscv_move_insn to synthesize the constant into the provided temporary register. Tested in my system. Waiting on upstream CI's verdict before moving forward. gcc/ * config/riscv/riscv.md (lui-constraint<X:mode>and_to_or): Do not use the RTL template for split code. Emit it directly taking care to avoid emitting a constant load that needed synthesis. Fix formatting. gcc/testsuite/ * gcc.target/riscv/ventana-16122.c: New test. Diff: --- gcc/config/riscv/riscv.md | 18 +++++++++++++----- gcc/testsuite/gcc.target/riscv/ventana-16122.c | 19 +++++++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 6d3c80a04c74..3aed25c25880 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -884,7 +884,7 @@ ;; Where C1 is not a LUI operand, but ~C1 is a LUI operand (define_insn_and_split "*lui_constraint<X:mode>_and_to_or" - [(set (match_operand:X 0 "register_operand" "=r") + [(set (match_operand:X 0 "register_operand" "=r") (plus:X (and:X (match_operand:X 1 "register_operand" "r") (match_operand 2 "const_int_operand")) (match_operand 3 "const_int_operand"))) @@ -898,13 +898,21 @@ <= riscv_const_insns (operands[3], false)))" "#" "&& reload_completed" - [(set (match_dup 4) (match_dup 5)) - (set (match_dup 0) (ior:X (match_dup 1) (match_dup 4))) - (set (match_dup 4) (match_dup 6)) - (set (match_dup 0) (minus:X (match_dup 0) (match_dup 4)))] + [(const_int 0)] { operands[5] = GEN_INT (~INTVAL (operands[2])); operands[6] = GEN_INT ((~INTVAL (operands[2])) | (-INTVAL (operands[3]))); + + /* This is always a LUI operand, so it's safe to just emit. */ + emit_move_insn (operands[4], operands[5]); + + rtx x = gen_rtx_IOR (word_mode, operands[1], operands[4]); + emit_move_insn (operands[0], x); + + /* This may require multiple steps to synthesize. */ + riscv_emit_move (operands[4], operands[6]); + x = gen_rtx_MINUS (word_mode, operands[0], operands[4]); + emit_move_insn (operands[0], x); } [(set_attr "type" "arith")]) diff --git a/gcc/testsuite/gcc.target/riscv/ventana-16122.c b/gcc/testsuite/gcc.target/riscv/ventana-16122.c new file mode 100644 index 000000000000..59e6467b57c0 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/ventana-16122.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target { rv64 } } } */ + +extern void NG (void); +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +void f74(void) { + int16_t x309 = 0x7fff; + volatile int32_t x310 = 0x7fffffff; + int8_t x311 = 59; + int16_t x312 = -0x8000; + static volatile int32_t t74 = 614992577; + + t74 = (x309==((x310^x311)%x312)); + + if (t74 != 0) { NG(); } else { ; } + +} +