[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