[llvm] [RISCV] Add HasConditionalMoveFusion Zibi patterns. (PR #216452)
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 14 20:56:32 PDT 2026
https://github.com/topperc created https://github.com/llvm/llvm-project/pull/216452
Stacked on #216449
>From fea862f722d05844933d600e361d05528b50fc96 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 14 Aug 2026 19:57:58 -0700
Subject: [PATCH 1/2] [RISCV] Simplify the Zibi SFB patterns. NFC
Use a PatLeaf to match the valid condition codes instead of using
separate patterns for each.
---
llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td | 23 ++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
index 409aeb4c86546..79d17ace73b75 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
@@ -261,15 +261,18 @@ def PseudoCCLWU : SFBLoad;
def PseudoCCLD : SFBLoad;
}
+def ZibiCond : PatLeaf<(cond), [{
+ switch (N->get()) {
+ default:
+ return false;
+ case ISD::SETEQ:
+ case ISD::SETNE:
+ return true;
+ }
+}]>;
+
// Zibi: select with immediate comparison folded into SFB.
// imm5_zibi is defined in RISCVInstrInfoZibi.td (included before this file).
-class SelectZibiSFB<CondCode Cond>
- : Pat<(riscv_selectcc (XLenVT GPR:$lhs), imm5_zibi:$cimm, Cond:$cc,
- (XLenVT GPR:$truev), GPR:$falsev),
- (PseudoCCMOVGPR GPR:$falsev, GPR:$truev, (CCtoZibiBCC $cc), GPR:$lhs,
- imm5_zibi:$cimm)>;
-
-let Predicates = [HasStdExtZibi, HasShortForwardBranchImm] in {
- def : SelectZibiSFB<SETEQ>;
- def : SelectZibiSFB<SETNE>;
-} // Predicates = [HasStdExtZibi, HasShortForwardBranchImm]
+let Predicates = [HasStdExtZibi, HasShortForwardBranchImm] in
+def : Pat<(riscv_selectcc (XLenVT GPR:$lhs), imm5_zibi:$cimm, ZibiCond:$cc, (XLenVT GPR:$truev), GPR:$falsev),
+ (PseudoCCMOVGPR GPR:$falsev, GPR:$truev, (CCtoZibiBCC $cc), GPR:$lhs, imm5_zibi:$cimm)>;
>From d25c247aecb24b6f5df867661aaafea8082885a2 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 14 Aug 2026 20:54:34 -0700
Subject: [PATCH 2/2] [RISCV] Add HasConditionalMoveFusion Zibi patterns.
---
llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td | 4 +
.../RISCV/short-forward-branch-opt-zibi.ll | 240 ++++++++++++++++++
2 files changed, 244 insertions(+)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
index 79d17ace73b75..54031f44ea858 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoSFB.td
@@ -276,3 +276,7 @@ def ZibiCond : PatLeaf<(cond), [{
let Predicates = [HasStdExtZibi, HasShortForwardBranchImm] in
def : Pat<(riscv_selectcc (XLenVT GPR:$lhs), imm5_zibi:$cimm, ZibiCond:$cc, (XLenVT GPR:$truev), GPR:$falsev),
(PseudoCCMOVGPR GPR:$falsev, GPR:$truev, (CCtoZibiBCC $cc), GPR:$lhs, imm5_zibi:$cimm)>;
+
+let Predicates = [HasStdExtZibi, HasConditionalMoveFusion, NoShortForwardBranch] in
+def : Pat<(riscv_selectcc (XLenVT GPR:$lhs), imm5_zibi:$cimm, ZibiCond:$cc, (XLenVT GPRNoX0:$truev), GPRNoX0:$falsev),
+ (PseudoCCMOVGPRNoX0 GPRNoX0:$falsev, GPRNoX0:$truev, (CCtoZibiBCC $cc), GPR:$lhs, imm5_zibi:$cimm)>;
diff --git a/llvm/test/CodeGen/RISCV/short-forward-branch-opt-zibi.ll b/llvm/test/CodeGen/RISCV/short-forward-branch-opt-zibi.ll
index 1e5c313da73cc..dbf99f4445282 100644
--- a/llvm/test/CodeGen/RISCV/short-forward-branch-opt-zibi.ll
+++ b/llvm/test/CodeGen/RISCV/short-forward-branch-opt-zibi.ll
@@ -7,6 +7,10 @@
; RUN: | FileCheck %s --check-prefixes=RV64
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zibi,+short-forward-branch-ialu,+short-forward-branch-imm -verify-machineinstrs < %s \
; RUN: | FileCheck %s --check-prefixes=RV64-SFB
+; RUN: llc -mtriple=riscv32 -mattr=+experimental-zibi,+zca,+conditional-cmv-fusion -verify-machineinstrs < %s \
+; RUN: | FileCheck %s --check-prefixes=RV32-CMOV
+; RUN: llc -mtriple=riscv64 -mattr=+experimental-zibi,+zca,+conditional-cmv-fusion -verify-machineinstrs < %s \
+; RUN: | FileCheck %s --check-prefixes=RV64-CMOV
; Basic select eq with Zibi immediate: should use bnei+mv SFB pattern when SFB enabled.
define i32 @select_eq(i32 %a, i32 %b, i32 %c) {
@@ -48,6 +52,25 @@ define i32 @select_eq(i32 %a, i32 %b, i32 %c) {
; RV64-SFB-NEXT: .LBB0_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_eq:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: beqi a0, 5, .LBB0_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a1, a2
+; RV32-CMOV-NEXT: .LBB0_2:
+; RV32-CMOV-NEXT: mv a0, a1
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_eq:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: beqi a0, 5, .LBB0_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a1, a2
+; RV64-CMOV-NEXT: .LBB0_2:
+; RV64-CMOV-NEXT: mv a0, a1
+; RV64-CMOV-NEXT: ret
%tst = icmp eq i32 %a, 5
%ret = select i1 %tst, i32 %b, i32 %c
ret i32 %ret
@@ -93,6 +116,25 @@ define i32 @select_ne(i32 %a, i32 %b, i32 %c) {
; RV64-SFB-NEXT: .LBB1_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_ne:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: bnei a0, 5, .LBB1_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a1, a2
+; RV32-CMOV-NEXT: .LBB1_2:
+; RV32-CMOV-NEXT: mv a0, a1
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_ne:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: bnei a0, 5, .LBB1_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a1, a2
+; RV64-CMOV-NEXT: .LBB1_2:
+; RV64-CMOV-NEXT: mv a0, a1
+; RV64-CMOV-NEXT: ret
%tst = icmp ne i32 %a, 5
%ret = select i1 %tst, i32 %b, i32 %c
ret i32 %ret
@@ -136,6 +178,27 @@ define i32 @select_eq_xor(i32 %a, i32 %b, i32 %c) {
; RV64-SFB-NEXT: .LBB2_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_eq_xor:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: xor a2, a2, a1
+; RV32-CMOV-NEXT: beqi a0, 5, .LBB2_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a2, a1
+; RV32-CMOV-NEXT: .LBB2_2:
+; RV32-CMOV-NEXT: mv a0, a2
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_eq_xor:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: xor a2, a2, a1
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: beqi a0, 5, .LBB2_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a2, a1
+; RV64-CMOV-NEXT: .LBB2_2:
+; RV64-CMOV-NEXT: mv a0, a2
+; RV64-CMOV-NEXT: ret
%tst = icmp eq i32 %a, 5
%xor = xor i32 %b, %c
%ret = select i1 %tst, i32 %xor, i32 %b
@@ -179,6 +242,27 @@ define i32 @select_ne_add(i32 %a, i32 %b, i32 %c) {
; RV64-SFB-NEXT: .LBB3_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_ne_add:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: add a2, a2, a1
+; RV32-CMOV-NEXT: bnei a0, 5, .LBB3_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a2, a1
+; RV32-CMOV-NEXT: .LBB3_2:
+; RV32-CMOV-NEXT: mv a0, a2
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_ne_add:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: addw a2, a2, a1
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: bnei a0, 5, .LBB3_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a2, a1
+; RV64-CMOV-NEXT: .LBB3_2:
+; RV64-CMOV-NEXT: mv a0, a2
+; RV64-CMOV-NEXT: ret
%tst = icmp ne i32 %a, 5
%add = add i32 %b, %c
%ret = select i1 %tst, i32 %add, i32 %b
@@ -225,6 +309,25 @@ define i32 @select_eq_imm1(i32 %a, i32 %b, i32 %c) {
; RV64-SFB-NEXT: .LBB4_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_eq_imm1:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: beqi a0, 1, .LBB4_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a1, a2
+; RV32-CMOV-NEXT: .LBB4_2:
+; RV32-CMOV-NEXT: mv a0, a1
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_eq_imm1:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: beqi a0, 1, .LBB4_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a1, a2
+; RV64-CMOV-NEXT: .LBB4_2:
+; RV64-CMOV-NEXT: mv a0, a1
+; RV64-CMOV-NEXT: ret
%tst = icmp eq i32 %a, 1
%ret = select i1 %tst, i32 %b, i32 %c
ret i32 %ret
@@ -270,6 +373,25 @@ define i32 @select_eq_imm31(i32 %a, i32 %b, i32 %c) {
; RV64-SFB-NEXT: .LBB5_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_eq_imm31:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: beqi a0, 31, .LBB5_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a1, a2
+; RV32-CMOV-NEXT: .LBB5_2:
+; RV32-CMOV-NEXT: mv a0, a1
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_eq_imm31:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: beqi a0, 31, .LBB5_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a1, a2
+; RV64-CMOV-NEXT: .LBB5_2:
+; RV64-CMOV-NEXT: mv a0, a1
+; RV64-CMOV-NEXT: ret
%tst = icmp eq i32 %a, 31
%ret = select i1 %tst, i32 %b, i32 %c
ret i32 %ret
@@ -315,6 +437,25 @@ define i32 @select_eq_imm_neg1(i32 %a, i32 %b, i32 %c) {
; RV64-SFB-NEXT: .LBB6_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_eq_imm_neg1:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: beqi a0, -1, .LBB6_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a1, a2
+; RV32-CMOV-NEXT: .LBB6_2:
+; RV32-CMOV-NEXT: mv a0, a1
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_eq_imm_neg1:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: beqi a0, -1, .LBB6_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a1, a2
+; RV64-CMOV-NEXT: .LBB6_2:
+; RV64-CMOV-NEXT: mv a0, a1
+; RV64-CMOV-NEXT: ret
%tst = icmp eq i32 %a, -1
%ret = select i1 %tst, i32 %b, i32 %c
ret i32 %ret
@@ -364,6 +505,27 @@ define i32 @select_eq_imm32(i32 %a, i32 %b, i32 %c) {
; RV64-SFB-NEXT: .LBB7_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_eq_imm32:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: li a3, 32
+; RV32-CMOV-NEXT: beq a0, a3, .LBB7_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a1, a2
+; RV32-CMOV-NEXT: .LBB7_2:
+; RV32-CMOV-NEXT: mv a0, a1
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_eq_imm32:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: li a3, 32
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: beq a0, a3, .LBB7_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a1, a2
+; RV64-CMOV-NEXT: .LBB7_2:
+; RV64-CMOV-NEXT: mv a0, a1
+; RV64-CMOV-NEXT: ret
%tst = icmp eq i32 %a, 32
%ret = select i1 %tst, i32 %b, i32 %c
ret i32 %ret
@@ -409,6 +571,25 @@ define i32 @select_eq_imm0(i32 %a, i32 %b, i32 %c) {
; RV64-SFB-NEXT: .LBB8_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_eq_imm0:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: beqz a0, .LBB8_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a1, a2
+; RV32-CMOV-NEXT: .LBB8_2:
+; RV32-CMOV-NEXT: mv a0, a1
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_eq_imm0:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: beqz a0, .LBB8_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a1, a2
+; RV64-CMOV-NEXT: .LBB8_2:
+; RV64-CMOV-NEXT: mv a0, a1
+; RV64-CMOV-NEXT: ret
%tst = icmp eq i32 %a, 0
%ret = select i1 %tst, i32 %b, i32 %c
ret i32 %ret
@@ -454,6 +635,25 @@ define i32 @select_eq_minsize(i32 %a, i32 %b, i32 %c) minsize {
; RV64-SFB-NEXT: .LBB9_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_eq_minsize:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: beqi a0, 5, .LBB9_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a1, a2
+; RV32-CMOV-NEXT: .LBB9_2:
+; RV32-CMOV-NEXT: mv a0, a1
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_eq_minsize:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: beqi a0, 5, .LBB9_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a1, a2
+; RV64-CMOV-NEXT: .LBB9_2:
+; RV64-CMOV-NEXT: mv a0, a1
+; RV64-CMOV-NEXT: ret
%tst = icmp eq i32 %a, 5
%ret = select i1 %tst, i32 %b, i32 %c
ret i32 %ret
@@ -498,6 +698,25 @@ define i32 @select_ne_minsize(i32 %a, i32 %b, i32 %c) minsize {
; RV64-SFB-NEXT: .LBB10_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_ne_minsize:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: bnei a0, 5, .LBB10_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a1, a2
+; RV32-CMOV-NEXT: .LBB10_2:
+; RV32-CMOV-NEXT: mv a0, a1
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_ne_minsize:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: bnei a0, 5, .LBB10_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a1, a2
+; RV64-CMOV-NEXT: .LBB10_2:
+; RV64-CMOV-NEXT: mv a0, a1
+; RV64-CMOV-NEXT: ret
%tst = icmp ne i32 %a, 5
%ret = select i1 %tst, i32 %b, i32 %c
ret i32 %ret
@@ -543,6 +762,27 @@ define i32 @select_eq_xor_minsize(i32 %a, i32 %b, i32 %c) minsize {
; RV64-SFB-NEXT: .LBB11_2:
; RV64-SFB-NEXT: mv a0, a1
; RV64-SFB-NEXT: ret
+;
+; RV32-CMOV-LABEL: select_eq_xor_minsize:
+; RV32-CMOV: # %bb.0:
+; RV32-CMOV-NEXT: xor a2, a2, a1
+; RV32-CMOV-NEXT: beqi a0, 5, .LBB11_2
+; RV32-CMOV-NEXT: # %bb.1:
+; RV32-CMOV-NEXT: mv a2, a1
+; RV32-CMOV-NEXT: .LBB11_2:
+; RV32-CMOV-NEXT: mv a0, a2
+; RV32-CMOV-NEXT: ret
+;
+; RV64-CMOV-LABEL: select_eq_xor_minsize:
+; RV64-CMOV: # %bb.0:
+; RV64-CMOV-NEXT: xor a2, a2, a1
+; RV64-CMOV-NEXT: sext.w a0, a0
+; RV64-CMOV-NEXT: beqi a0, 5, .LBB11_2
+; RV64-CMOV-NEXT: # %bb.1:
+; RV64-CMOV-NEXT: mv a2, a1
+; RV64-CMOV-NEXT: .LBB11_2:
+; RV64-CMOV-NEXT: mv a0, a2
+; RV64-CMOV-NEXT: ret
%tst = icmp eq i32 %a, 5
%xor = xor i32 %b, %c
%ret = select i1 %tst, i32 %xor, i32 %b
More information about the llvm-commits
mailing list