This was tripping up gcc.c-torture/execute/pr60003.c at -O1 since in failing case, pattern's asm czero.nez gets both rs2 and rs1 as non zero.
We start with the following src code snippet: if (a == 0) return 0; else return x; } which is equivalent to: "x = (a != 0) ? x : a" where x is NOT 0. ^^^^^^^^^^^^^^^^ and matches define_insn "*czero.nez.<GPR:mode><X:mode>.opt2" | (insn 41 20 38 3 (set (reg/v:DI 136 [ x ]) | (if_then_else:DI (ne (reg/v:DI 134 [ a ]) | (const_int 0 [0])) | (reg/v:DI 136 [ x ]) | (reg/v:DI 134 [ a ]))) {*czero.nez.didi.opt2} The corresponding asm pattern generates czero.nez x, x, a ; %0, %2, %1 which implies "x = (a != 0) ? 0 : a" clearly not what the pattern wants to do. Essentially "(a != 0) ? x : a" cannot be expressed with CZERO.nez if X is not guaranteed to be 0. However this can be fixed with a small tweak "x = (a != 0) ? x : a" is same as "x = (a == 0) ? a : x" since middle operand is 0 when a == 0. which can be expressed with CZERO.eqz before fix after fix ----------------- ----------------- li a5,1 li a5,1 ld a4,8(sp) ld a4,8(sp) # a4 is runtime non zero czero.nez a0,a4,a5 # a0=0 NOK czero.eqz a0,a4,a5 # a0=a4!=0 OK The issue only happens at -O1 as at higher optimization levels, the whole conditional move gets optimized away. This fixes 4 testsuite failues in a zicond build: FAIL: gcc.c-torture/execute/pr60003.c -O1 execution test FAIL: gcc.dg/setjmp-3.c execution test FAIL: gcc.dg/torture/stackalign/setjmp-3.c -O1 execution test FAIL: gcc.dg/torture/stackalign/setjmp-3.c -O1 -fpic execution test gcc/ChangeLog: * config/riscv/zicond.md: Fix op2 pattern. Fixes: 1d5bc3285e8a ("[committed][RISC-V] Fix 20010221-1.c with zicond") Signed-off-by: Vineet Gupta <vine...@rivosinc.com> --- changes since v1 - instead of discarding opt2 pattern, fix the asm --- gcc/config/riscv/zicond.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md index 4619220ef8ac..1721e1011ea8 100644 --- a/gcc/config/riscv/zicond.md +++ b/gcc/config/riscv/zicond.md @@ -60,7 +60,7 @@ (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" + "czero.eqz\t%0,%2,%1" ) ;; Combine creates this form in some cases (particularly the coremark -- 2.34.1