https://gcc.gnu.org/g:ccd787ce79a0ed6ee2c0881821076773048dd334
commit r17-4465-gccd787ce79a0ed6ee2c0881821076773048dd334 Author: Milan Tripkovic <[email protected]> Date: Sat Sep 19 10:56:04 2026 -0600 [PATCH] RISC-V: PR target/127374 - Zicond improvement for RISC-V Fix a missed optimization where conditional zeroes based on less-than-or-equal and greater-than comparisons against immediates generate redundant Immediate loads. Add define_split patterns to optimize these if_then_else operations. Introduce the gt_to_le code attribute to map greater-than conditions to Less-than-or-equal. This enables the patterns to utilize the sle_operand predicate, safely splitting the operations into slti or sltiu evaluations followed by czero.nez or czero.eqz Instructions. ASM Before: li a5,100 sgt a0,a0,a5 // sgtu a0,a0,a5 czero.nez a0,a1,a0 // czero.eqz a0,a1,a0 ASM after: slti a0,a0,101 // sltiu a0,a0,101 czero.eqz a0,a1,a0 // czero.nez a0,a1,a0 Also, add a new regression test to cover this optimization and update an existing test to prevent false alarms due to the new instruction sequence. PR target/127374 gcc/ChangeLog: * config/riscv/iterators.md (leu): Map gt to le * config/riscv/zicond.md: Add define_split patterns gcc/testsuite/ChangeLog: * gcc.target/riscv/czero-bext.c: Change scan assembler * gcc.target/riscv/pr127374.c: New test. Diff: --- gcc/config/riscv/iterators.md | 3 +++ gcc/config/riscv/zicond.md | 34 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/riscv/czero-bext.c | 4 ++-- gcc/testsuite/gcc.target/riscv/pr127374.c | 20 +++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index dc25dfd2e99d..d8869810de76 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -268,6 +268,9 @@ (define_code_iterator any_le [le leu]) (define_code_iterator any_eq [eq ne]) +;; Maps GT/GTU to LE/LE. +(define_code_attr gt_to_le [(gt "le") (gtu "leu")]) + ;; Iterators for conditions we can emit a sCC against 0 or a reg directly (define_code_iterator scc_0 [any_eq any_gt any_lt]) diff --git a/gcc/config/riscv/zicond.md b/gcc/config/riscv/zicond.md index b0152cb773f4..a69f55e82d18 100644 --- a/gcc/config/riscv/zicond.md +++ b/gcc/config/riscv/zicond.md @@ -487,3 +487,37 @@ [(set (match_dup 4) (any_le:X (match_dup 1) (match_dup 2))) (set (match_dup 0) (ashift:X (match_dup 4) (match_dup 5)))] { operands[5] = GEN_INT (exact_log2 (INTVAL (operands[3]))); }) + +(define_split + [(set (match_operand:GPR 0 "register_operand") + (if_then_else:GPR + (any_le:X (match_operand:X 1 "register_operand") + (match_operand:X 2 "sle<u>_operand")) + (match_operand:GPR 3 "register_operand") + (const_int 0)))] + "TARGET_ZICOND_LIKE && can_create_pseudo_p ()" + [(set (match_dup 4) (any_le:X (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (if_then_else:GPR (ne:X (match_dup 4) (const_int 0)) + (match_dup 3) + (const_int 0)))] +{ + operands[4] = gen_reg_rtx (<X:MODE>mode); +}) + +(define_split + [(set (match_operand:GPR 0 "register_operand") + (if_then_else:GPR + (any_gt:X (match_operand:X 1 "register_operand") + (match_operand:X 2 "sle<u>_operand")) + (match_operand:GPR 3 "register_operand") + (const_int 0)))] + "TARGET_ZICOND_LIKE && can_create_pseudo_p ()" + [(set (match_dup 4) (<gt_to_le>:X (match_dup 1) (match_dup 2))) + (set (match_dup 0) + (if_then_else:GPR (eq:X (match_dup 4) (const_int 0)) + (match_dup 3) + (const_int 0)))] +{ + operands[4] = gen_reg_rtx (<X:MODE>mode); +}) diff --git a/gcc/testsuite/gcc.target/riscv/czero-bext.c b/gcc/testsuite/gcc.target/riscv/czero-bext.c index 54a6d6f175f9..8ffeb4263329 100644 --- a/gcc/testsuite/gcc.target/riscv/czero-bext.c +++ b/gcc/testsuite/gcc.target/riscv/czero-bext.c @@ -11,7 +11,7 @@ bool isValidAncestorType(int type) { -/* { dg-final { scan-assembler "czero.nez\t" } } */ -/* { dg-final { scan-assembler "sgtu\t" } } */ +/* { dg-final { scan-assembler "czero.eqz\t" } } */ +/* { dg-final { scan-assembler "sltiu\t" } } */ /* { dg-final { scan-assembler-not "bgtu\t" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/pr127374.c b/gcc/testsuite/gcc.target/riscv/pr127374.c new file mode 100644 index 000000000000..ccb93cdff122 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr127374.c @@ -0,0 +1,20 @@ +/* PR target/127374 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv64gcb_zicond -mabi=lp64d" { target { rv64 } } } */ +/* { dg-options "-O2 -march=rv32gcb_zicond -mabi=ilp32d" { target { rv32 } } } */ + +int sel_le_s (int x, int y) { return x <= 100 ? y : 0; } +int sel_gt_s (int x, int y) { return x > 100 ? y : 0; } +int sel_le_u (unsigned x, int y) { return x <= 100 ? y : 0; } +int sel_gt_u (unsigned x, int y) { return x > 100 ? y : 0; } + +int clr_le_s (int x, int y) { return x <= 100 ? 0 : y; } +int clr_gt_s (int x, int y) { return x > 100 ? 0 : y; } +int clr_le_u (unsigned x, int y) { return x <= 100 ? 0 : y; } +int clr_gt_u (unsigned x, int y) { return x > 100 ? 0 : y; } + +/* { dg-final { scan-assembler-times {\mslti\s+\w+,\w+,101\M} 4 } } */ +/* { dg-final { scan-assembler-times {\msltiu\s+\w+,\w+,101\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mczero\.eqz\M} 4 } } */ +/* { dg-final { scan-assembler-times {\mczero\.nez\M} 4 } } */ +/* { dg-final { scan-assembler-not {\mli\M} } } */
