[llvm] [RISCV] Add (BSETI x0, 11) to isLoadImm for optimizeCondBranch (PR #180820)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 10 11:53:30 PST 2026


https://github.com/topperc created https://github.com/llvm/llvm-project/pull/180820

optimizeCondBranch is looking for immediates that are 1 apart to rewrite the branch by sharing a constant. BSETI x0, 11 can be used to produce 2048 which is one more than the largest positive constant produced by addi.

>From 5bbac0b938a29ab5a203ddb0a73611a01424fad5 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 10 Feb 2026 11:25:09 -0800
Subject: [PATCH 1/2] Pre-commit test

---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp |  6 +++
 llvm/test/CodeGen/RISCV/branch-opt.ll    | 64 +++++++++++++++++++++++-
 2 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 2156d1919ddbe..ed52c70c23b66 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1598,6 +1598,12 @@ static bool isLoadImm(const MachineInstr *MI, int64_t &Imm) {
     Imm = MI->getOperand(2).getImm();
     return true;
   }
+//  // BSETI can be used to create power of 2 constants.
+//  if (MI->getOpcode() == RISCV::BSETI && MI->getOperand(1).isReg() &&
+//      MI->getOperand(1).getReg() == RISCV::X0) {
+//    Imm = 1ULL << MI->getOperand(2).getImm();
+//    return true;
+//  }
   return false;
 }
 
diff --git a/llvm/test/CodeGen/RISCV/branch-opt.ll b/llvm/test/CodeGen/RISCV/branch-opt.ll
index e4912bbf861a2..4ee85461fa4d6 100644
--- a/llvm/test/CodeGen/RISCV/branch-opt.ll
+++ b/llvm/test/CodeGen/RISCV/branch-opt.ll
@@ -1,6 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
-; RUN: llc -mtriple=riscv32 -O2 -verify-machineinstrs < %s | FileCheck %s
-; RUN: llc -mtriple=riscv64 -O2 -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=riscv32 -mattr=+zbs -O2 -verify-machineinstrs < %s | FileCheck %s
+; RUN: llc -mtriple=riscv64 -mattr=+zbs -O2 -verify-machineinstrs < %s | FileCheck %s
 
 define void @u_case1_a(ptr %a, i32 signext %b, ptr %c, ptr %d) {
 ; CHECK-LABEL: u_case1_a:
@@ -117,3 +117,63 @@ block2:                                           ; preds = %0
 end_block:                                        ; preds = %block2, %block1
   ret void
 }
+
+define void @bset_case1_a(ptr %a, i32 signext %b, ptr %c, ptr %d) {
+; CHECK-LABEL: bset_case1_a:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    bseti a4, zero, 11
+; CHECK-NEXT:    li a5, 2047
+; CHECK-NEXT:    sw a4, 0(a0)
+; CHECK-NEXT:    bltu a5, a1, .LBB4_2
+; CHECK-NEXT:  # %bb.1: # %block1
+; CHECK-NEXT:    sw a1, 0(a2)
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB4_2: # %block2
+; CHECK-NEXT:    li a0, 87
+; CHECK-NEXT:    sw a0, 0(a3)
+; CHECK-NEXT:    ret
+  store i32 2048, ptr %a
+  %p = icmp ule i32 %b, 2047
+  br i1 %p, label %block1, label %block2
+
+block1:                                           ; preds = %0
+  store i32 %b, ptr %c
+  br label %end_block
+
+block2:                                           ; preds = %0
+  store i32 87, ptr %d
+  br label %end_block
+
+end_block:                                        ; preds = %block2, %block1
+  ret void
+}
+
+define void @bset_case2_a(ptr %a, i32 signext %b, ptr %c, ptr %d) {
+; CHECK-LABEL: bset_case2_a:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    li a4, 2047
+; CHECK-NEXT:    bseti a5, zero, 11
+; CHECK-NEXT:    sw a4, 0(a0)
+; CHECK-NEXT:    blt a1, a5, .LBB5_2
+; CHECK-NEXT:  # %bb.1: # %block1
+; CHECK-NEXT:    sw a1, 0(a2)
+; CHECK-NEXT:    ret
+; CHECK-NEXT:  .LBB5_2: # %block2
+; CHECK-NEXT:    li a0, 87
+; CHECK-NEXT:    sw a0, 0(a3)
+; CHECK-NEXT:    ret
+  store i32 2047, ptr %a
+  %p = icmp sge i32 %b, 2048
+  br i1 %p, label %block1, label %block2
+
+block1:                                           ; preds = %0
+  store i32 %b, ptr %c
+  br label %end_block
+
+block2:                                           ; preds = %0
+  store i32 87, ptr %d
+  br label %end_block
+
+end_block:                                        ; preds = %block2, %block1
+  ret void
+}

>From f2bd62cca1e3b69621ae597ef9ddb3dc0668bac8 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 10 Feb 2026 11:26:40 -0800
Subject: [PATCH 2/2] [RISCV] Add (BSETI x0, imm) to isLoadImm for
 optimizeCondBranch

---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 20 +++++++++++---------
 llvm/test/CodeGen/RISCV/branch-opt.ll    |  6 ++----
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index ed52c70c23b66..ec4614966876f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1591,19 +1591,21 @@ bool RISCVInstrInfo::reverseBranchCondition(
 }
 
 // Return true if the instruction is a load immediate instruction (i.e.
-// ADDI x0, imm).
+// (ADDI x0, imm) or (BSETI x0, imm)).
 static bool isLoadImm(const MachineInstr *MI, int64_t &Imm) {
   if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
       MI->getOperand(1).getReg() == RISCV::X0) {
     Imm = MI->getOperand(2).getImm();
     return true;
   }
-//  // BSETI can be used to create power of 2 constants.
-//  if (MI->getOpcode() == RISCV::BSETI && MI->getOperand(1).isReg() &&
-//      MI->getOperand(1).getReg() == RISCV::X0) {
-//    Imm = 1ULL << MI->getOperand(2).getImm();
-//    return true;
-//  }
+  // BSETI can be used to create power of 2 constants. Only 2048 is currently
+  // interesting because it is 1 more than the maximum ADDI constant.
+  if (MI->getOpcode() == RISCV::BSETI && MI->getOperand(1).isReg() &&
+      MI->getOperand(1).getReg() == RISCV::X0 &&
+      MI->getOperand(2).getImm() == 11) {
+    Imm = 2048;
+    return true;
+  }
   return false;
 }
 
@@ -1708,7 +1710,7 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
   // return that.
   if (isFromLoadImm(MRI, LHS, C0) && C0 != 0 && LHS.getReg().isVirtual() &&
       MRI.hasOneUse(LHS.getReg()) && (IsSigned || C0 != -1)) {
-    assert(isInt<12>(C0) && "Unexpected immediate");
+    assert((isInt<12>(C0) || C0 == 2048) && "Unexpected immediate");
     if (Register RegZ = searchConst(C0 + 1)) {
       BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpc))
           .add(RHS)
@@ -1729,7 +1731,7 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
   // return that.
   if (isFromLoadImm(MRI, RHS, C0) && C0 != 0 && RHS.getReg().isVirtual() &&
       MRI.hasOneUse(RHS.getReg())) {
-    assert(isInt<12>(C0) && "Unexpected immediate");
+    assert((isInt<12>(C0) || C0 == 2048) && "Unexpected immediate");
     if (Register RegZ = searchConst(C0 - 1)) {
       BuildMI(*MBB, MI, MI.getDebugLoc(), get(NewOpc))
           .addReg(RegZ)
diff --git a/llvm/test/CodeGen/RISCV/branch-opt.ll b/llvm/test/CodeGen/RISCV/branch-opt.ll
index 4ee85461fa4d6..1134b1798b97d 100644
--- a/llvm/test/CodeGen/RISCV/branch-opt.ll
+++ b/llvm/test/CodeGen/RISCV/branch-opt.ll
@@ -122,9 +122,8 @@ define void @bset_case1_a(ptr %a, i32 signext %b, ptr %c, ptr %d) {
 ; CHECK-LABEL: bset_case1_a:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    bseti a4, zero, 11
-; CHECK-NEXT:    li a5, 2047
 ; CHECK-NEXT:    sw a4, 0(a0)
-; CHECK-NEXT:    bltu a5, a1, .LBB4_2
+; CHECK-NEXT:    bgeu a1, a4, .LBB4_2
 ; CHECK-NEXT:  # %bb.1: # %block1
 ; CHECK-NEXT:    sw a1, 0(a2)
 ; CHECK-NEXT:    ret
@@ -152,9 +151,8 @@ define void @bset_case2_a(ptr %a, i32 signext %b, ptr %c, ptr %d) {
 ; CHECK-LABEL: bset_case2_a:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    li a4, 2047
-; CHECK-NEXT:    bseti a5, zero, 11
 ; CHECK-NEXT:    sw a4, 0(a0)
-; CHECK-NEXT:    blt a1, a5, .LBB5_2
+; CHECK-NEXT:    bge a4, a1, .LBB5_2
 ; CHECK-NEXT:  # %bb.1: # %block1
 ; CHECK-NEXT:    sw a1, 0(a2)
 ; CHECK-NEXT:    ret



More information about the llvm-commits mailing list