[llvm] [RISCV] Add late optimization pass for riscv (PR #133256)

Mikhail R. Gadelha via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 27 07:25:22 PDT 2025


https://github.com/mikhailramalho created https://github.com/llvm/llvm-project/pull/133256

This patch is an alternative to PRs #117060, #131684, #131728, and builds on top of #132988.

The patch adds a late optimization pass that replaces conditional branches that can be statically evaluated with an unconditinal branch.

Once this PR and #132988 land, I plan to send a follow-up patch that reduces code size by adding a branch folding pass after the newly added late optimization pass.

Adding Michael as a co-author as most of the code that evaluates the condition comes from #131684.

Co-authored-by: Michael Maitland michaeltmaitland at gmail.com

>From 4a64565c3843770da1be232b78e119e8da210c89 Mon Sep 17 00:00:00 2001
From: Philip Reames <preames at rivosinc.com>
Date: Tue, 25 Mar 2025 12:52:07 -0700
Subject: [PATCH 1/4] [RISCV] Canonicalize foldable branch conditions in
 optimizeCondBranch

optimizeCondBranch isn't allowed to modify the CFG, but it can rewrite
the branch condition freely.  However, If we could fold a conditional
branch to an unconditional one (aside from that restriction), we can
also rewrite it into some canonical conditional branch instead.

Looking at the diffs, the only cases this catches in tree tests are
cases where we could have constant folded during lowering from IR,
but didn't.  This is inspired by trying to salvage code from https://github.com/llvm/llvm-project/pull/131684
which might be useful.  Given the test impact, it's of questionable merits.
The main advantage over only the late cleanup pass is that it kills off the
LIs for the constants early - which can help e.g. register allocation.
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp      | 102 +++++++++-----
 llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll     |  12 +-
 llvm/test/CodeGen/RISCV/double-br-fcmp.ll     |  24 ++--
 llvm/test/CodeGen/RISCV/float-br-fcmp.ll      |  24 ++--
 llvm/test/CodeGen/RISCV/half-br-fcmp.ll       |  48 +++----
 .../RISCV/machine-sink-load-immediate.ll      | 124 +++++++++---------
 6 files changed, 164 insertions(+), 170 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 62f978d64fbb9..1d105806ecbd6 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -998,6 +998,26 @@ static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
   }
 }
 
+
+static bool evaluateCondBranch(unsigned CC, int64_t C0, int64_t C1) {
+  switch (CC) {
+  default:
+    llvm_unreachable("Unexpected CC");
+  case RISCVCC::COND_EQ:
+    return C0 == C1;
+  case RISCVCC::COND_NE:
+    return C0 != C1;
+  case RISCVCC::COND_LT:
+    return C0 < C1;
+  case RISCVCC::COND_GE:
+    return C0 >= C1;
+  case RISCVCC::COND_LTU:
+    return (uint64_t)C0 < (uint64_t)C1;
+  case RISCVCC::COND_GEU:
+    return (uint64_t)C0 >= (uint64_t)C1;
+  }
+}
+
 // The contents of values added to Cond are not examined outside of
 // RISCVInstrInfo, giving us flexibility in what to push to it. For RISCV, we
 // push BranchOpcode, Reg1, Reg2.
@@ -1295,6 +1315,49 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
   RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
   assert(CC != RISCVCC::COND_INVALID);
 
+  auto modifyBranch = [&]() {
+    // Build the new branch and remove the old one.
+    BuildMI(*MBB, MI, MI.getDebugLoc(),
+            getBrCond(static_cast<RISCVCC::CondCode>(Cond[0].getImm())))
+        .add(Cond[1])
+        .add(Cond[2])
+        .addMBB(TBB);
+    MI.eraseFromParent();
+  };
+
+  // Right now we only care about LI (i.e. ADDI x0, imm)
+  auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
+    if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
+        MI->getOperand(1).getReg() == RISCV::X0) {
+      Imm = MI->getOperand(2).getImm();
+      return true;
+    }
+    return false;
+  };
+  // Either a load from immediate instruction or X0.
+  auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
+    if (!Op.isReg())
+      return false;
+    Register Reg = Op.getReg();
+    if (Reg == RISCV::X0) {
+      Imm = 0;
+      return true;
+    }
+    return Reg.isVirtual() && isLoadImm(MRI.getVRegDef(Reg), Imm);
+  };
+
+  // Canonicalize conditional branches which can be constant folded into
+  // beqz or bnez.  We can't modify the CFG here.
+  int64_t C0, C1;
+  if (isFromLoadImm(Cond[1], C0) && isFromLoadImm(Cond[2], C1)) {
+    unsigned NewCC =
+      evaluateCondBranch(CC, C0, C1) ? RISCVCC::COND_EQ : RISCVCC::COND_NE;
+    Cond[0] = MachineOperand::CreateImm(NewCC);
+    Cond[1] = Cond[2] = MachineOperand::CreateReg(RISCV::X0, /*isDef=*/false);
+    modifyBranch();
+    return true;
+  }
+
   if (CC == RISCVCC::COND_EQ || CC == RISCVCC::COND_NE)
     return false;
 
@@ -1315,24 +1378,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
   //
   // To make sure this optimization is really beneficial, we only
   // optimize for cases where Y had only one use (i.e. only used by the branch).
-
-  // Right now we only care about LI (i.e. ADDI x0, imm)
-  auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
-    if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
-        MI->getOperand(1).getReg() == RISCV::X0) {
-      Imm = MI->getOperand(2).getImm();
-      return true;
-    }
-    return false;
-  };
-  // Either a load from immediate instruction or X0.
-  auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
-    if (!Op.isReg())
-      return false;
-    Register Reg = Op.getReg();
-    return Reg.isVirtual() && isLoadImm(MRI.getVRegDef(Reg), Imm);
-  };
-
   MachineOperand &LHS = MI.getOperand(0);
   MachineOperand &RHS = MI.getOperand(1);
   // Try to find the register for constant Z; return
@@ -1350,8 +1395,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
     return Register();
   };
 
-  bool Modify = false;
-  int64_t C0;
   if (isFromLoadImm(LHS, C0) && MRI.hasOneUse(LHS.getReg())) {
     // Might be case 1.
     // Signed integer overflow is UB. (UINT64_MAX is bigger so we don't need
@@ -1364,7 +1407,8 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
         // We might extend the live range of Z, clear its kill flag to
         // account for this.
         MRI.clearKillFlags(RegZ);
-        Modify = true;
+        modifyBranch();
+        return true;
       }
   } else if (isFromLoadImm(RHS, C0) && MRI.hasOneUse(RHS.getReg())) {
     // Might be case 2.
@@ -1378,22 +1422,12 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
         // We might extend the live range of Z, clear its kill flag to
         // account for this.
         MRI.clearKillFlags(RegZ);
-        Modify = true;
+        modifyBranch();
+        return true;
       }
   }
 
-  if (!Modify)
-    return false;
-
-  // Build the new branch and remove the old one.
-  BuildMI(*MBB, MI, MI.getDebugLoc(),
-          getBrCond(static_cast<RISCVCC::CondCode>(Cond[0].getImm())))
-      .add(Cond[1])
-      .add(Cond[2])
-      .addMBB(TBB);
-  MI.eraseFromParent();
-
-  return true;
+  return false;
 }
 
 MachineBasicBlock *
diff --git a/llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll b/llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll
index 51ea8873d8c03..2e8cf35a294f6 100644
--- a/llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll
+++ b/llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll
@@ -11,8 +11,7 @@ declare bfloat @dummy(bfloat)
 define void @br_fcmp_false(bfloat %a, bfloat %b) nounwind {
 ; RV32IZFBFMIN-LABEL: br_fcmp_false:
 ; RV32IZFBFMIN:       # %bb.0:
-; RV32IZFBFMIN-NEXT:    li a0, 1
-; RV32IZFBFMIN-NEXT:    bnez a0, .LBB0_2
+; RV32IZFBFMIN-NEXT:    beqz zero, .LBB0_2
 ; RV32IZFBFMIN-NEXT:  # %bb.1: # %if.then
 ; RV32IZFBFMIN-NEXT:    ret
 ; RV32IZFBFMIN-NEXT:  .LBB0_2: # %if.else
@@ -22,8 +21,7 @@ define void @br_fcmp_false(bfloat %a, bfloat %b) nounwind {
 ;
 ; RV64IZFBFMIN-LABEL: br_fcmp_false:
 ; RV64IZFBFMIN:       # %bb.0:
-; RV64IZFBFMIN-NEXT:    li a0, 1
-; RV64IZFBFMIN-NEXT:    bnez a0, .LBB0_2
+; RV64IZFBFMIN-NEXT:    beqz zero, .LBB0_2
 ; RV64IZFBFMIN-NEXT:  # %bb.1: # %if.then
 ; RV64IZFBFMIN-NEXT:    ret
 ; RV64IZFBFMIN-NEXT:  .LBB0_2: # %if.else
@@ -583,8 +581,7 @@ if.then:
 define void @br_fcmp_true(bfloat %a, bfloat %b) nounwind {
 ; RV32IZFBFMIN-LABEL: br_fcmp_true:
 ; RV32IZFBFMIN:       # %bb.0:
-; RV32IZFBFMIN-NEXT:    li a0, 1
-; RV32IZFBFMIN-NEXT:    bnez a0, .LBB16_2
+; RV32IZFBFMIN-NEXT:    beqz zero, .LBB16_2
 ; RV32IZFBFMIN-NEXT:  # %bb.1: # %if.else
 ; RV32IZFBFMIN-NEXT:    ret
 ; RV32IZFBFMIN-NEXT:  .LBB16_2: # %if.then
@@ -594,8 +591,7 @@ define void @br_fcmp_true(bfloat %a, bfloat %b) nounwind {
 ;
 ; RV64IZFBFMIN-LABEL: br_fcmp_true:
 ; RV64IZFBFMIN:       # %bb.0:
-; RV64IZFBFMIN-NEXT:    li a0, 1
-; RV64IZFBFMIN-NEXT:    bnez a0, .LBB16_2
+; RV64IZFBFMIN-NEXT:    beqz zero, .LBB16_2
 ; RV64IZFBFMIN-NEXT:  # %bb.1: # %if.else
 ; RV64IZFBFMIN-NEXT:    ret
 ; RV64IZFBFMIN-NEXT:  .LBB16_2: # %if.then
diff --git a/llvm/test/CodeGen/RISCV/double-br-fcmp.ll b/llvm/test/CodeGen/RISCV/double-br-fcmp.ll
index 035228e73c707..42f1b1360a2d3 100644
--- a/llvm/test/CodeGen/RISCV/double-br-fcmp.ll
+++ b/llvm/test/CodeGen/RISCV/double-br-fcmp.ll
@@ -14,8 +14,7 @@ declare void @exit(i32)
 define void @br_fcmp_false(double %a, double %b) nounwind {
 ; RV32IFD-LABEL: br_fcmp_false:
 ; RV32IFD:       # %bb.0:
-; RV32IFD-NEXT:    li a0, 1
-; RV32IFD-NEXT:    bnez a0, .LBB0_2
+; RV32IFD-NEXT:    beqz zero, .LBB0_2
 ; RV32IFD-NEXT:  # %bb.1: # %if.then
 ; RV32IFD-NEXT:    ret
 ; RV32IFD-NEXT:  .LBB0_2: # %if.else
@@ -25,8 +24,7 @@ define void @br_fcmp_false(double %a, double %b) nounwind {
 ;
 ; RV64IFD-LABEL: br_fcmp_false:
 ; RV64IFD:       # %bb.0:
-; RV64IFD-NEXT:    li a0, 1
-; RV64IFD-NEXT:    bnez a0, .LBB0_2
+; RV64IFD-NEXT:    beqz zero, .LBB0_2
 ; RV64IFD-NEXT:  # %bb.1: # %if.then
 ; RV64IFD-NEXT:    ret
 ; RV64IFD-NEXT:  .LBB0_2: # %if.else
@@ -36,8 +34,7 @@ define void @br_fcmp_false(double %a, double %b) nounwind {
 ;
 ; RV32IZFINXZDINX-LABEL: br_fcmp_false:
 ; RV32IZFINXZDINX:       # %bb.0:
-; RV32IZFINXZDINX-NEXT:    li a0, 1
-; RV32IZFINXZDINX-NEXT:    bnez a0, .LBB0_2
+; RV32IZFINXZDINX-NEXT:    beqz zero, .LBB0_2
 ; RV32IZFINXZDINX-NEXT:  # %bb.1: # %if.then
 ; RV32IZFINXZDINX-NEXT:    ret
 ; RV32IZFINXZDINX-NEXT:  .LBB0_2: # %if.else
@@ -47,8 +44,7 @@ define void @br_fcmp_false(double %a, double %b) nounwind {
 ;
 ; RV64IZFINXZDINX-LABEL: br_fcmp_false:
 ; RV64IZFINXZDINX:       # %bb.0:
-; RV64IZFINXZDINX-NEXT:    li a0, 1
-; RV64IZFINXZDINX-NEXT:    bnez a0, .LBB0_2
+; RV64IZFINXZDINX-NEXT:    beqz zero, .LBB0_2
 ; RV64IZFINXZDINX-NEXT:  # %bb.1: # %if.then
 ; RV64IZFINXZDINX-NEXT:    ret
 ; RV64IZFINXZDINX-NEXT:  .LBB0_2: # %if.else
@@ -897,8 +893,7 @@ if.then:
 define void @br_fcmp_true(double %a, double %b) nounwind {
 ; RV32IFD-LABEL: br_fcmp_true:
 ; RV32IFD:       # %bb.0:
-; RV32IFD-NEXT:    li a0, 1
-; RV32IFD-NEXT:    bnez a0, .LBB16_2
+; RV32IFD-NEXT:    beqz zero, .LBB16_2
 ; RV32IFD-NEXT:  # %bb.1: # %if.else
 ; RV32IFD-NEXT:    ret
 ; RV32IFD-NEXT:  .LBB16_2: # %if.then
@@ -908,8 +903,7 @@ define void @br_fcmp_true(double %a, double %b) nounwind {
 ;
 ; RV64IFD-LABEL: br_fcmp_true:
 ; RV64IFD:       # %bb.0:
-; RV64IFD-NEXT:    li a0, 1
-; RV64IFD-NEXT:    bnez a0, .LBB16_2
+; RV64IFD-NEXT:    beqz zero, .LBB16_2
 ; RV64IFD-NEXT:  # %bb.1: # %if.else
 ; RV64IFD-NEXT:    ret
 ; RV64IFD-NEXT:  .LBB16_2: # %if.then
@@ -919,8 +913,7 @@ define void @br_fcmp_true(double %a, double %b) nounwind {
 ;
 ; RV32IZFINXZDINX-LABEL: br_fcmp_true:
 ; RV32IZFINXZDINX:       # %bb.0:
-; RV32IZFINXZDINX-NEXT:    li a0, 1
-; RV32IZFINXZDINX-NEXT:    bnez a0, .LBB16_2
+; RV32IZFINXZDINX-NEXT:    beqz zero, .LBB16_2
 ; RV32IZFINXZDINX-NEXT:  # %bb.1: # %if.else
 ; RV32IZFINXZDINX-NEXT:    ret
 ; RV32IZFINXZDINX-NEXT:  .LBB16_2: # %if.then
@@ -930,8 +923,7 @@ define void @br_fcmp_true(double %a, double %b) nounwind {
 ;
 ; RV64IZFINXZDINX-LABEL: br_fcmp_true:
 ; RV64IZFINXZDINX:       # %bb.0:
-; RV64IZFINXZDINX-NEXT:    li a0, 1
-; RV64IZFINXZDINX-NEXT:    bnez a0, .LBB16_2
+; RV64IZFINXZDINX-NEXT:    beqz zero, .LBB16_2
 ; RV64IZFINXZDINX-NEXT:  # %bb.1: # %if.else
 ; RV64IZFINXZDINX-NEXT:    ret
 ; RV64IZFINXZDINX-NEXT:  .LBB16_2: # %if.then
diff --git a/llvm/test/CodeGen/RISCV/float-br-fcmp.ll b/llvm/test/CodeGen/RISCV/float-br-fcmp.ll
index 35caa627b57bc..00da1cc1c8bbe 100644
--- a/llvm/test/CodeGen/RISCV/float-br-fcmp.ll
+++ b/llvm/test/CodeGen/RISCV/float-br-fcmp.ll
@@ -15,8 +15,7 @@ declare float @dummy(float)
 define void @br_fcmp_false(float %a, float %b) nounwind {
 ; RV32IF-LABEL: br_fcmp_false:
 ; RV32IF:       # %bb.0:
-; RV32IF-NEXT:    li a0, 1
-; RV32IF-NEXT:    bnez a0, .LBB0_2
+; RV32IF-NEXT:    beqz zero, .LBB0_2
 ; RV32IF-NEXT:  # %bb.1: # %if.then
 ; RV32IF-NEXT:    ret
 ; RV32IF-NEXT:  .LBB0_2: # %if.else
@@ -26,8 +25,7 @@ define void @br_fcmp_false(float %a, float %b) nounwind {
 ;
 ; RV64IF-LABEL: br_fcmp_false:
 ; RV64IF:       # %bb.0:
-; RV64IF-NEXT:    li a0, 1
-; RV64IF-NEXT:    bnez a0, .LBB0_2
+; RV64IF-NEXT:    beqz zero, .LBB0_2
 ; RV64IF-NEXT:  # %bb.1: # %if.then
 ; RV64IF-NEXT:    ret
 ; RV64IF-NEXT:  .LBB0_2: # %if.else
@@ -37,8 +35,7 @@ define void @br_fcmp_false(float %a, float %b) nounwind {
 ;
 ; RV32IZFINX-LABEL: br_fcmp_false:
 ; RV32IZFINX:       # %bb.0:
-; RV32IZFINX-NEXT:    li a0, 1
-; RV32IZFINX-NEXT:    bnez a0, .LBB0_2
+; RV32IZFINX-NEXT:    beqz zero, .LBB0_2
 ; RV32IZFINX-NEXT:  # %bb.1: # %if.then
 ; RV32IZFINX-NEXT:    ret
 ; RV32IZFINX-NEXT:  .LBB0_2: # %if.else
@@ -48,8 +45,7 @@ define void @br_fcmp_false(float %a, float %b) nounwind {
 ;
 ; RV64IZFINX-LABEL: br_fcmp_false:
 ; RV64IZFINX:       # %bb.0:
-; RV64IZFINX-NEXT:    li a0, 1
-; RV64IZFINX-NEXT:    bnez a0, .LBB0_2
+; RV64IZFINX-NEXT:    beqz zero, .LBB0_2
 ; RV64IZFINX-NEXT:  # %bb.1: # %if.then
 ; RV64IZFINX-NEXT:    ret
 ; RV64IZFINX-NEXT:  .LBB0_2: # %if.else
@@ -898,8 +894,7 @@ if.then:
 define void @br_fcmp_true(float %a, float %b) nounwind {
 ; RV32IF-LABEL: br_fcmp_true:
 ; RV32IF:       # %bb.0:
-; RV32IF-NEXT:    li a0, 1
-; RV32IF-NEXT:    bnez a0, .LBB16_2
+; RV32IF-NEXT:    beqz zero, .LBB16_2
 ; RV32IF-NEXT:  # %bb.1: # %if.else
 ; RV32IF-NEXT:    ret
 ; RV32IF-NEXT:  .LBB16_2: # %if.then
@@ -909,8 +904,7 @@ define void @br_fcmp_true(float %a, float %b) nounwind {
 ;
 ; RV64IF-LABEL: br_fcmp_true:
 ; RV64IF:       # %bb.0:
-; RV64IF-NEXT:    li a0, 1
-; RV64IF-NEXT:    bnez a0, .LBB16_2
+; RV64IF-NEXT:    beqz zero, .LBB16_2
 ; RV64IF-NEXT:  # %bb.1: # %if.else
 ; RV64IF-NEXT:    ret
 ; RV64IF-NEXT:  .LBB16_2: # %if.then
@@ -920,8 +914,7 @@ define void @br_fcmp_true(float %a, float %b) nounwind {
 ;
 ; RV32IZFINX-LABEL: br_fcmp_true:
 ; RV32IZFINX:       # %bb.0:
-; RV32IZFINX-NEXT:    li a0, 1
-; RV32IZFINX-NEXT:    bnez a0, .LBB16_2
+; RV32IZFINX-NEXT:    beqz zero, .LBB16_2
 ; RV32IZFINX-NEXT:  # %bb.1: # %if.else
 ; RV32IZFINX-NEXT:    ret
 ; RV32IZFINX-NEXT:  .LBB16_2: # %if.then
@@ -931,8 +924,7 @@ define void @br_fcmp_true(float %a, float %b) nounwind {
 ;
 ; RV64IZFINX-LABEL: br_fcmp_true:
 ; RV64IZFINX:       # %bb.0:
-; RV64IZFINX-NEXT:    li a0, 1
-; RV64IZFINX-NEXT:    bnez a0, .LBB16_2
+; RV64IZFINX-NEXT:    beqz zero, .LBB16_2
 ; RV64IZFINX-NEXT:  # %bb.1: # %if.else
 ; RV64IZFINX-NEXT:    ret
 ; RV64IZFINX-NEXT:  .LBB16_2: # %if.then
diff --git a/llvm/test/CodeGen/RISCV/half-br-fcmp.ll b/llvm/test/CodeGen/RISCV/half-br-fcmp.ll
index e9b142e33362f..1cee927662c14 100644
--- a/llvm/test/CodeGen/RISCV/half-br-fcmp.ll
+++ b/llvm/test/CodeGen/RISCV/half-br-fcmp.ll
@@ -23,8 +23,7 @@ declare half @dummy(half)
 define void @br_fcmp_false(half %a, half %b) nounwind {
 ; RV32IZFH-LABEL: br_fcmp_false:
 ; RV32IZFH:       # %bb.0:
-; RV32IZFH-NEXT:    li a0, 1
-; RV32IZFH-NEXT:    bnez a0, .LBB0_2
+; RV32IZFH-NEXT:    beqz zero, .LBB0_2
 ; RV32IZFH-NEXT:  # %bb.1: # %if.then
 ; RV32IZFH-NEXT:    ret
 ; RV32IZFH-NEXT:  .LBB0_2: # %if.else
@@ -34,8 +33,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV64IZFH-LABEL: br_fcmp_false:
 ; RV64IZFH:       # %bb.0:
-; RV64IZFH-NEXT:    li a0, 1
-; RV64IZFH-NEXT:    bnez a0, .LBB0_2
+; RV64IZFH-NEXT:    beqz zero, .LBB0_2
 ; RV64IZFH-NEXT:  # %bb.1: # %if.then
 ; RV64IZFH-NEXT:    ret
 ; RV64IZFH-NEXT:  .LBB0_2: # %if.else
@@ -45,8 +43,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV32IZHINX-LABEL: br_fcmp_false:
 ; RV32IZHINX:       # %bb.0:
-; RV32IZHINX-NEXT:    li a0, 1
-; RV32IZHINX-NEXT:    bnez a0, .LBB0_2
+; RV32IZHINX-NEXT:    beqz zero, .LBB0_2
 ; RV32IZHINX-NEXT:  # %bb.1: # %if.then
 ; RV32IZHINX-NEXT:    ret
 ; RV32IZHINX-NEXT:  .LBB0_2: # %if.else
@@ -56,8 +53,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV64IZHINX-LABEL: br_fcmp_false:
 ; RV64IZHINX:       # %bb.0:
-; RV64IZHINX-NEXT:    li a0, 1
-; RV64IZHINX-NEXT:    bnez a0, .LBB0_2
+; RV64IZHINX-NEXT:    beqz zero, .LBB0_2
 ; RV64IZHINX-NEXT:  # %bb.1: # %if.then
 ; RV64IZHINX-NEXT:    ret
 ; RV64IZHINX-NEXT:  .LBB0_2: # %if.else
@@ -67,8 +63,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV32IZFHMIN-LABEL: br_fcmp_false:
 ; RV32IZFHMIN:       # %bb.0:
-; RV32IZFHMIN-NEXT:    li a0, 1
-; RV32IZFHMIN-NEXT:    bnez a0, .LBB0_2
+; RV32IZFHMIN-NEXT:    beqz zero, .LBB0_2
 ; RV32IZFHMIN-NEXT:  # %bb.1: # %if.then
 ; RV32IZFHMIN-NEXT:    ret
 ; RV32IZFHMIN-NEXT:  .LBB0_2: # %if.else
@@ -78,8 +73,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV64IZFHMIN-LABEL: br_fcmp_false:
 ; RV64IZFHMIN:       # %bb.0:
-; RV64IZFHMIN-NEXT:    li a0, 1
-; RV64IZFHMIN-NEXT:    bnez a0, .LBB0_2
+; RV64IZFHMIN-NEXT:    beqz zero, .LBB0_2
 ; RV64IZFHMIN-NEXT:  # %bb.1: # %if.then
 ; RV64IZFHMIN-NEXT:    ret
 ; RV64IZFHMIN-NEXT:  .LBB0_2: # %if.else
@@ -89,8 +83,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV32IZHINXMIN-LABEL: br_fcmp_false:
 ; RV32IZHINXMIN:       # %bb.0:
-; RV32IZHINXMIN-NEXT:    li a0, 1
-; RV32IZHINXMIN-NEXT:    bnez a0, .LBB0_2
+; RV32IZHINXMIN-NEXT:    beqz zero, .LBB0_2
 ; RV32IZHINXMIN-NEXT:  # %bb.1: # %if.then
 ; RV32IZHINXMIN-NEXT:    ret
 ; RV32IZHINXMIN-NEXT:  .LBB0_2: # %if.else
@@ -100,8 +93,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV64IZHINXMIN-LABEL: br_fcmp_false:
 ; RV64IZHINXMIN:       # %bb.0:
-; RV64IZHINXMIN-NEXT:    li a0, 1
-; RV64IZHINXMIN-NEXT:    bnez a0, .LBB0_2
+; RV64IZHINXMIN-NEXT:    beqz zero, .LBB0_2
 ; RV64IZHINXMIN-NEXT:  # %bb.1: # %if.then
 ; RV64IZHINXMIN-NEXT:    ret
 ; RV64IZHINXMIN-NEXT:  .LBB0_2: # %if.else
@@ -1762,8 +1754,7 @@ if.then:
 define void @br_fcmp_true(half %a, half %b) nounwind {
 ; RV32IZFH-LABEL: br_fcmp_true:
 ; RV32IZFH:       # %bb.0:
-; RV32IZFH-NEXT:    li a0, 1
-; RV32IZFH-NEXT:    bnez a0, .LBB16_2
+; RV32IZFH-NEXT:    beqz zero, .LBB16_2
 ; RV32IZFH-NEXT:  # %bb.1: # %if.else
 ; RV32IZFH-NEXT:    ret
 ; RV32IZFH-NEXT:  .LBB16_2: # %if.then
@@ -1773,8 +1764,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV64IZFH-LABEL: br_fcmp_true:
 ; RV64IZFH:       # %bb.0:
-; RV64IZFH-NEXT:    li a0, 1
-; RV64IZFH-NEXT:    bnez a0, .LBB16_2
+; RV64IZFH-NEXT:    beqz zero, .LBB16_2
 ; RV64IZFH-NEXT:  # %bb.1: # %if.else
 ; RV64IZFH-NEXT:    ret
 ; RV64IZFH-NEXT:  .LBB16_2: # %if.then
@@ -1784,8 +1774,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV32IZHINX-LABEL: br_fcmp_true:
 ; RV32IZHINX:       # %bb.0:
-; RV32IZHINX-NEXT:    li a0, 1
-; RV32IZHINX-NEXT:    bnez a0, .LBB16_2
+; RV32IZHINX-NEXT:    beqz zero, .LBB16_2
 ; RV32IZHINX-NEXT:  # %bb.1: # %if.else
 ; RV32IZHINX-NEXT:    ret
 ; RV32IZHINX-NEXT:  .LBB16_2: # %if.then
@@ -1795,8 +1784,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV64IZHINX-LABEL: br_fcmp_true:
 ; RV64IZHINX:       # %bb.0:
-; RV64IZHINX-NEXT:    li a0, 1
-; RV64IZHINX-NEXT:    bnez a0, .LBB16_2
+; RV64IZHINX-NEXT:    beqz zero, .LBB16_2
 ; RV64IZHINX-NEXT:  # %bb.1: # %if.else
 ; RV64IZHINX-NEXT:    ret
 ; RV64IZHINX-NEXT:  .LBB16_2: # %if.then
@@ -1806,8 +1794,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV32IZFHMIN-LABEL: br_fcmp_true:
 ; RV32IZFHMIN:       # %bb.0:
-; RV32IZFHMIN-NEXT:    li a0, 1
-; RV32IZFHMIN-NEXT:    bnez a0, .LBB16_2
+; RV32IZFHMIN-NEXT:    beqz zero, .LBB16_2
 ; RV32IZFHMIN-NEXT:  # %bb.1: # %if.else
 ; RV32IZFHMIN-NEXT:    ret
 ; RV32IZFHMIN-NEXT:  .LBB16_2: # %if.then
@@ -1817,8 +1804,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV64IZFHMIN-LABEL: br_fcmp_true:
 ; RV64IZFHMIN:       # %bb.0:
-; RV64IZFHMIN-NEXT:    li a0, 1
-; RV64IZFHMIN-NEXT:    bnez a0, .LBB16_2
+; RV64IZFHMIN-NEXT:    beqz zero, .LBB16_2
 ; RV64IZFHMIN-NEXT:  # %bb.1: # %if.else
 ; RV64IZFHMIN-NEXT:    ret
 ; RV64IZFHMIN-NEXT:  .LBB16_2: # %if.then
@@ -1828,8 +1814,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV32IZHINXMIN-LABEL: br_fcmp_true:
 ; RV32IZHINXMIN:       # %bb.0:
-; RV32IZHINXMIN-NEXT:    li a0, 1
-; RV32IZHINXMIN-NEXT:    bnez a0, .LBB16_2
+; RV32IZHINXMIN-NEXT:    beqz zero, .LBB16_2
 ; RV32IZHINXMIN-NEXT:  # %bb.1: # %if.else
 ; RV32IZHINXMIN-NEXT:    ret
 ; RV32IZHINXMIN-NEXT:  .LBB16_2: # %if.then
@@ -1839,8 +1824,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV64IZHINXMIN-LABEL: br_fcmp_true:
 ; RV64IZHINXMIN:       # %bb.0:
-; RV64IZHINXMIN-NEXT:    li a0, 1
-; RV64IZHINXMIN-NEXT:    bnez a0, .LBB16_2
+; RV64IZHINXMIN-NEXT:    beqz zero, .LBB16_2
 ; RV64IZHINXMIN-NEXT:  # %bb.1: # %if.else
 ; RV64IZHINXMIN-NEXT:    ret
 ; RV64IZHINXMIN-NEXT:  .LBB16_2: # %if.then
diff --git a/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll b/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll
index eb84774014a4b..4947423971c6b 100644
--- a/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll
+++ b/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll
@@ -13,76 +13,72 @@ define i1 @sink_li(ptr %text, ptr %text.addr.0) nounwind {
 ; CHECK-NEXT:    mv s0, a0
 ; CHECK-NEXT:    call toupper
 ; CHECK-NEXT:    li a1, 0
-; CHECK-NEXT:    beqz s0, .LBB0_26
-; CHECK-NEXT:  # %bb.1: # %while.body.preheader
-; CHECK-NEXT:    li a2, 1
-; CHECK-NEXT:    li a3, 9
-; CHECK-NEXT:    li a4, 32
-; CHECK-NEXT:  .LBB0_2: # %while.body
+; CHECK-NEXT:    beqz s0, .LBB0_25
+; CHECK-NEXT:  .LBB0_1: # %while.body
 ; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
-; CHECK-NEXT:    bnez a2, .LBB0_4
-; CHECK-NEXT:  # %bb.3: # %while.body
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bne a2, a3, .LBB0_16
-; CHECK-NEXT:  .LBB0_4: # %while.body.1
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bnez a2, .LBB0_6
-; CHECK-NEXT:  # %bb.5: # %while.body.1
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bne a2, a3, .LBB0_17
-; CHECK-NEXT:  .LBB0_6: # %while.body.3
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bnez a2, .LBB0_8
-; CHECK-NEXT:  # %bb.7: # %while.body.3
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bne a2, a4, .LBB0_19
-; CHECK-NEXT:  .LBB0_8: # %while.body.4
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bnez a2, .LBB0_10
-; CHECK-NEXT:  # %bb.9: # %while.body.4
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bne a2, a4, .LBB0_21
-; CHECK-NEXT:  .LBB0_10: # %while.body.5
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bnez a2, .LBB0_12
-; CHECK-NEXT:  # %bb.11: # %while.body.5
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bne a2, a3, .LBB0_23
-; CHECK-NEXT:  .LBB0_12: # %while.body.6
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    bnez a2, .LBB0_2
+; CHECK-NEXT:    beqz zero, .LBB0_3
+; CHECK-NEXT:  # %bb.2: # %while.body
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_15
+; CHECK-NEXT:  .LBB0_3: # %while.body.1
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_5
+; CHECK-NEXT:  # %bb.4: # %while.body.1
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_16
+; CHECK-NEXT:  .LBB0_5: # %while.body.3
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_7
+; CHECK-NEXT:  # %bb.6: # %while.body.3
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_18
+; CHECK-NEXT:  .LBB0_7: # %while.body.4
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_9
+; CHECK-NEXT:  # %bb.8: # %while.body.4
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_20
+; CHECK-NEXT:  .LBB0_9: # %while.body.5
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_11
+; CHECK-NEXT:  # %bb.10: # %while.body.5
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_22
+; CHECK-NEXT:  .LBB0_11: # %while.body.6
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    beqz zero, .LBB0_1
+; CHECK-NEXT:  # %bb.12: # %while.body.6
+; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
+; CHECK-NEXT:    bnez zero, .LBB0_1
 ; CHECK-NEXT:  # %bb.13: # %while.body.6
-; CHECK-NEXT:    # in Loop: Header=BB0_2 Depth=1
-; CHECK-NEXT:    beq a2, a3, .LBB0_2
-; CHECK-NEXT:  # %bb.14: # %while.body.6
-; CHECK-NEXT:    beqz a2, .LBB0_24
-; CHECK-NEXT:  # %bb.15: # %strdup.exit.split.loop.exit126
+; CHECK-NEXT:    bnez zero, .LBB0_23
+; CHECK-NEXT:  # %bb.14: # %strdup.exit.split.loop.exit126
 ; CHECK-NEXT:    addi s0, s1, 7
-; CHECK-NEXT:    j .LBB0_25
-; CHECK-NEXT:  .LBB0_16: # %while.body
-; CHECK-NEXT:    beqz a2, .LBB0_26
-; CHECK-NEXT:    j .LBB0_18
-; CHECK-NEXT:  .LBB0_17: # %while.body.1
-; CHECK-NEXT:    beqz a2, .LBB0_24
-; CHECK-NEXT:  .LBB0_18: # %strdup.exit.loopexit
+; CHECK-NEXT:    j .LBB0_24
+; CHECK-NEXT:  .LBB0_15: # %while.body
+; CHECK-NEXT:    bnez zero, .LBB0_25
+; CHECK-NEXT:    j .LBB0_17
+; CHECK-NEXT:  .LBB0_16: # %while.body.1
+; CHECK-NEXT:    bnez zero, .LBB0_23
+; CHECK-NEXT:  .LBB0_17: # %strdup.exit.loopexit
 ; CHECK-NEXT:    li s0, 0
-; CHECK-NEXT:    j .LBB0_25
-; CHECK-NEXT:  .LBB0_19: # %while.body.3
-; CHECK-NEXT:    beqz a2, .LBB0_24
-; CHECK-NEXT:  # %bb.20: # %strdup.exit.split.loop.exit120
+; CHECK-NEXT:    j .LBB0_24
+; CHECK-NEXT:  .LBB0_18: # %while.body.3
+; CHECK-NEXT:    bnez zero, .LBB0_23
+; CHECK-NEXT:  # %bb.19: # %strdup.exit.split.loop.exit120
 ; CHECK-NEXT:    addi s0, s1, 4
-; CHECK-NEXT:    j .LBB0_25
-; CHECK-NEXT:  .LBB0_21: # %while.body.4
-; CHECK-NEXT:    beqz a2, .LBB0_24
-; CHECK-NEXT:  # %bb.22: # %strdup.exit.split.loop.exit122
+; CHECK-NEXT:    j .LBB0_24
+; CHECK-NEXT:  .LBB0_20: # %while.body.4
+; CHECK-NEXT:    bnez zero, .LBB0_23
+; CHECK-NEXT:  # %bb.21: # %strdup.exit.split.loop.exit122
 ; CHECK-NEXT:    addi s0, s1, 5
-; CHECK-NEXT:    j .LBB0_25
-; CHECK-NEXT:  .LBB0_23: # %while.body.5
-; CHECK-NEXT:    bnez a2, .LBB0_25
-; CHECK-NEXT:  .LBB0_24:
+; CHECK-NEXT:    j .LBB0_24
+; CHECK-NEXT:  .LBB0_22: # %while.body.5
+; CHECK-NEXT:    beqz zero, .LBB0_24
+; CHECK-NEXT:  .LBB0_23:
 ; CHECK-NEXT:    li a1, 0
-; CHECK-NEXT:    j .LBB0_26
-; CHECK-NEXT:  .LBB0_25: # %strdup.exit
+; CHECK-NEXT:    j .LBB0_25
+; CHECK-NEXT:  .LBB0_24: # %strdup.exit
 ; CHECK-NEXT:    li s1, 0
 ; CHECK-NEXT:    mv s2, a0
 ; CHECK-NEXT:    li a0, 0
@@ -93,7 +89,7 @@ define i1 @sink_li(ptr %text, ptr %text.addr.0) nounwind {
 ; CHECK-NEXT:    li a2, 0
 ; CHECK-NEXT:    jalr s1
 ; CHECK-NEXT:    li a1, 1
-; CHECK-NEXT:  .LBB0_26: # %return
+; CHECK-NEXT:  .LBB0_25: # %return
 ; CHECK-NEXT:    mv a0, a1
 ; CHECK-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
 ; CHECK-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload

>From 40439cd36af3213aef0605f9785d7c4300ac226d Mon Sep 17 00:00:00 2001
From: Philip Reames <preames at rivosinc.com>
Date: Tue, 25 Mar 2025 13:11:19 -0700
Subject: [PATCH 2/4] clang-format

---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 1d105806ecbd6..af9975aca206e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -998,7 +998,6 @@ static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
   }
 }
 
-
 static bool evaluateCondBranch(unsigned CC, int64_t C0, int64_t C1) {
   switch (CC) {
   default:
@@ -1351,7 +1350,7 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
   int64_t C0, C1;
   if (isFromLoadImm(Cond[1], C0) && isFromLoadImm(Cond[2], C1)) {
     unsigned NewCC =
-      evaluateCondBranch(CC, C0, C1) ? RISCVCC::COND_EQ : RISCVCC::COND_NE;
+        evaluateCondBranch(CC, C0, C1) ? RISCVCC::COND_EQ : RISCVCC::COND_NE;
     Cond[0] = MachineOperand::CreateImm(NewCC);
     Cond[1] = Cond[2] = MachineOperand::CreateReg(RISCV::X0, /*isDef=*/false);
     modifyBranch();

>From 25c88ba9acaee5b6fa8f13b6711557e03fb7dac4 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Wed, 26 Mar 2025 14:58:15 -0300
Subject: [PATCH 3/4] [RISCV] Add late optimization pass for riscv

This patch is an alternative to PRs #117060, #131684, #131728.

The patch adds a late optimization pass that replaces conditional
branches that can be statically evaluated with an unconditinal branch.

Adding michael as a co-author as most of code that evaluates the
condition comes from #131684.
---
 llvm/lib/Target/RISCV/CMakeLists.txt          |   1 +
 llvm/lib/Target/RISCV/RISCV.h                 |   3 +
 llvm/lib/Target/RISCV/RISCVLateOpt.cpp        | 190 ++++++++++++++++++
 llvm/lib/Target/RISCV/RISCVTargetMachine.cpp  |   2 +
 llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb.ll |   8 +-
 llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll     |   8 +-
 llvm/test/CodeGen/RISCV/branch_zero.ll        |  16 +-
 llvm/test/CodeGen/RISCV/double-br-fcmp.ll     |  16 +-
 llvm/test/CodeGen/RISCV/float-br-fcmp.ll      |  16 +-
 llvm/test/CodeGen/RISCV/half-br-fcmp.ll       |  32 +--
 .../RISCV/machine-sink-load-immediate.ll      |  52 +++--
 .../RISCV/rvv/vxrm-insert-out-of-loop.ll      |  10 +-
 12 files changed, 271 insertions(+), 83 deletions(-)
 create mode 100644 llvm/lib/Target/RISCV/RISCVLateOpt.cpp

diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index e8d00f4df7c86..c9609d224414d 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -35,6 +35,7 @@ add_llvm_target(RISCVCodeGen
   RISCVConstantPoolValue.cpp
   RISCVDeadRegisterDefinitions.cpp
   RISCVMakeCompressible.cpp
+  RISCVLateOpt.cpp
   RISCVExpandAtomicPseudoInsts.cpp
   RISCVExpandPseudoInsts.cpp
   RISCVFoldMemOffset.cpp
diff --git a/llvm/lib/Target/RISCV/RISCV.h b/llvm/lib/Target/RISCV/RISCV.h
index 641e2eb4094f9..1f1d7e1fa21df 100644
--- a/llvm/lib/Target/RISCV/RISCV.h
+++ b/llvm/lib/Target/RISCV/RISCV.h
@@ -40,6 +40,9 @@ void initializeRISCVLandingPadSetupPass(PassRegistry &);
 FunctionPass *createRISCVISelDag(RISCVTargetMachine &TM,
                                  CodeGenOptLevel OptLevel);
 
+FunctionPass *createRISCVLateOptPass();
+void initializeRISCVLateOptPass(PassRegistry &);
+
 FunctionPass *createRISCVMakeCompressibleOptPass();
 void initializeRISCVMakeCompressibleOptPass(PassRegistry &);
 
diff --git a/llvm/lib/Target/RISCV/RISCVLateOpt.cpp b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
new file mode 100644
index 0000000000000..7fa04f0cbba9b
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
@@ -0,0 +1,190 @@
+//===-- RISCVLateOpt.cpp - Late stage optimization ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file provides RISC-V specific target descriptions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "RISCV.h"
+#include "RISCVInstrInfo.h"
+#include "RISCVSubtarget.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
+#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "riscv-late-opt"
+#define RISCV_LATE_OPT_NAME "RISC-V Late Stage Optimizations"
+
+namespace {
+
+struct RISCVLateOpt : public MachineFunctionPass {
+  static char ID;
+
+  RISCVLateOpt() : MachineFunctionPass(ID) {}
+
+  StringRef getPassName() const override { return RISCV_LATE_OPT_NAME; }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+
+  bool runOnMachineFunction(MachineFunction &Fn) override;
+
+private:
+  bool trySimplifyCondBr(MachineInstr *MI, MachineBasicBlock *TBB,
+                         MachineBasicBlock *FBB,
+                         SmallVectorImpl<MachineOperand> &Cond) const;
+
+  const RISCVInstrInfo *RII = nullptr;
+};
+} // namespace
+
+char RISCVLateOpt::ID = 0;
+INITIALIZE_PASS(RISCVLateOpt, "riscv-late-opt", RISCV_LATE_OPT_NAME, false,
+                false)
+
+bool RISCVLateOpt::trySimplifyCondBr(
+    MachineInstr *MI, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
+    SmallVectorImpl<MachineOperand> &Cond) const {
+
+  RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
+  assert(CC != RISCVCC::COND_INVALID);
+
+  // Right now we only care about LI (i.e. ADDI x0, imm)
+  auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
+    if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
+        MI->getOperand(1).getReg() == RISCV::X0) {
+      Imm = MI->getOperand(2).getImm();
+      return true;
+    }
+    return false;
+  };
+
+  MachineBasicBlock *MBB = MI->getParent();
+  MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
+  // Either a load from immediate instruction or X0.
+  auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
+    if (!Op.isReg())
+      return false;
+    Register Reg = Op.getReg();
+    if (Reg == RISCV::X0) {
+      Imm = 0;
+      return true;
+    }
+    return Reg.isVirtual() && isLoadImm(MRI.getVRegDef(Reg), Imm);
+  };
+
+  // Try and convert a conditional branch that can be evaluated statically
+  // into an unconditional branch.
+  MachineBasicBlock *Folded = nullptr;
+  int64_t C0, C1;
+  if (isFromLoadImm(Cond[1], C0) && isFromLoadImm(Cond[2], C1)) {
+    switch (CC) {
+    case RISCVCC::COND_INVALID:
+      llvm_unreachable("Unexpected CC");
+    case RISCVCC::COND_EQ: {
+      Folded = (C0 == C1) ? TBB : FBB;
+      break;
+    }
+    case RISCVCC::COND_NE: {
+      Folded = (C0 != C1) ? TBB : FBB;
+      break;
+    }
+    case RISCVCC::COND_LT: {
+      Folded = (C0 < C1) ? TBB : FBB;
+      break;
+    }
+    case RISCVCC::COND_GE: {
+      Folded = (C0 >= C1) ? TBB : FBB;
+      break;
+    }
+    case RISCVCC::COND_LTU: {
+      Folded = ((uint64_t)C0 < (uint64_t)C1) ? TBB : FBB;
+      break;
+    }
+    case RISCVCC::COND_GEU: {
+      Folded = ((uint64_t)C0 >= (uint64_t)C1) ? TBB : FBB;
+      break;
+    }
+    }
+
+    // Do the conversion
+    // Build the new unconditional branch
+    DebugLoc DL = MBB->findBranchDebugLoc();
+    if (Folded) {
+      BuildMI(*MBB, MI, DL, RII->get(RISCV::PseudoBR)).addMBB(Folded);
+    } else {
+      MachineFunction::iterator Fallthrough = ++MBB->getIterator();
+      if (Fallthrough == MBB->getParent()->end())
+        return false;
+      BuildMI(*MBB, MI, DL, RII->get(RISCV::PseudoBR)).addMBB(&*Fallthrough);
+    }
+
+    // Update successors of MBB->
+    if (Folded == TBB) {
+      // If we're taking TBB, then the succ to delete is the fallthrough (if
+      // it was a succ in the first place), or its the MBB from the
+      // unconditional branch.
+      if (!FBB) {
+        MachineFunction::iterator Fallthrough = ++MBB->getIterator();
+        if (Fallthrough != MBB->getParent()->end() &&
+            MBB->isSuccessor(&*Fallthrough))
+          MBB->removeSuccessor(&*Fallthrough, true);
+      } else {
+        MBB->removeSuccessor(FBB, true);
+      }
+    } else if (Folded == FBB) {
+      // If we're taking the fallthrough or unconditional branch, then the
+      // succ to remove is the one from the conditional branch.
+      MBB->removeSuccessor(TBB, true);
+    }
+
+    MI->eraseFromParent();
+    return true;
+  }
+  return false;
+}
+
+bool RISCVLateOpt::runOnMachineFunction(MachineFunction &Fn) {
+  if (skipFunction(Fn.getFunction()))
+    return false;
+
+  auto &ST = Fn.getSubtarget<RISCVSubtarget>();
+  RII = ST.getInstrInfo();
+
+  bool Changed = false;
+
+  for (MachineBasicBlock &MBB : Fn) {
+    for (MachineBasicBlock::iterator MII = MBB.begin(), MIE = MBB.end();
+         MII != MIE;) {
+      MachineInstr *MI = &*MII;
+      // We may be erasing MI below, increment MII now.
+      ++MII;
+      if (!MI->isConditionalBranch())
+        continue;
+
+      MachineBasicBlock *TBB, *FBB;
+      SmallVector<MachineOperand, 4> Cond;
+      if (!RII->analyzeBranch(MBB, TBB, FBB, Cond, /*AllowModify=*/false))
+        Changed |= trySimplifyCondBr(MI, TBB, FBB, Cond);
+    }
+  }
+
+  return Changed;
+}
+
+/// Returns an instance of the Make Compressible Optimization pass.
+FunctionPass *llvm::createRISCVLateOptPass() { return new RISCVLateOpt(); }
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index f78e5f8147d98..40c1aead7991b 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -127,6 +127,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
   initializeRISCVPostLegalizerCombinerPass(*PR);
   initializeKCFIPass(*PR);
   initializeRISCVDeadRegisterDefinitionsPass(*PR);
+  initializeRISCVLateOptPass(*PR);
   initializeRISCVMakeCompressibleOptPass(*PR);
   initializeRISCVGatherScatterLoweringPass(*PR);
   initializeRISCVCodeGenPreparePass(*PR);
@@ -565,6 +566,7 @@ void RISCVPassConfig::addPreEmitPass() {
   if (TM->getOptLevel() >= CodeGenOptLevel::Default &&
       EnableRISCVCopyPropagation)
     addPass(createMachineCopyPropagationPass(true));
+  addPass(createRISCVLateOptPass());
   addPass(&BranchRelaxationPassID);
   addPass(createRISCVMakeCompressibleOptPass());
 }
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb.ll b/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb.ll
index 338925059862c..95af7861d4798 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/rv32zbb.ll
@@ -357,7 +357,7 @@ define i64 @ctpop_i64(i64 %a) nounwind {
 define i1 @ctpop_i64_ugt_two(i64 %a) nounwind {
 ; RV32I-LABEL: ctpop_i64_ugt_two:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    beqz zero, .LBB6_2
+; RV32I-NEXT:    j .LBB6_2
 ; RV32I-NEXT:  # %bb.1:
 ; RV32I-NEXT:    sltiu a0, zero, 0
 ; RV32I-NEXT:    ret
@@ -404,7 +404,7 @@ define i1 @ctpop_i64_ugt_two(i64 %a) nounwind {
 ;
 ; RV32ZBB-LABEL: ctpop_i64_ugt_two:
 ; RV32ZBB:       # %bb.0:
-; RV32ZBB-NEXT:    beqz zero, .LBB6_2
+; RV32ZBB-NEXT:    j .LBB6_2
 ; RV32ZBB-NEXT:  # %bb.1:
 ; RV32ZBB-NEXT:    sltiu a0, zero, 0
 ; RV32ZBB-NEXT:    ret
@@ -422,7 +422,7 @@ define i1 @ctpop_i64_ugt_two(i64 %a) nounwind {
 define i1 @ctpop_i64_ugt_one(i64 %a) nounwind {
 ; RV32I-LABEL: ctpop_i64_ugt_one:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    beqz zero, .LBB7_2
+; RV32I-NEXT:    j .LBB7_2
 ; RV32I-NEXT:  # %bb.1:
 ; RV32I-NEXT:    snez a0, zero
 ; RV32I-NEXT:    ret
@@ -470,7 +470,7 @@ define i1 @ctpop_i64_ugt_one(i64 %a) nounwind {
 ;
 ; RV32ZBB-LABEL: ctpop_i64_ugt_one:
 ; RV32ZBB:       # %bb.0:
-; RV32ZBB-NEXT:    beqz zero, .LBB7_2
+; RV32ZBB-NEXT:    j .LBB7_2
 ; RV32ZBB-NEXT:  # %bb.1:
 ; RV32ZBB-NEXT:    snez a0, zero
 ; RV32ZBB-NEXT:    ret
diff --git a/llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll b/llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll
index 2e8cf35a294f6..b2558cde29832 100644
--- a/llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll
+++ b/llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll
@@ -11,7 +11,7 @@ declare bfloat @dummy(bfloat)
 define void @br_fcmp_false(bfloat %a, bfloat %b) nounwind {
 ; RV32IZFBFMIN-LABEL: br_fcmp_false:
 ; RV32IZFBFMIN:       # %bb.0:
-; RV32IZFBFMIN-NEXT:    beqz zero, .LBB0_2
+; RV32IZFBFMIN-NEXT:    j .LBB0_2
 ; RV32IZFBFMIN-NEXT:  # %bb.1: # %if.then
 ; RV32IZFBFMIN-NEXT:    ret
 ; RV32IZFBFMIN-NEXT:  .LBB0_2: # %if.else
@@ -21,7 +21,7 @@ define void @br_fcmp_false(bfloat %a, bfloat %b) nounwind {
 ;
 ; RV64IZFBFMIN-LABEL: br_fcmp_false:
 ; RV64IZFBFMIN:       # %bb.0:
-; RV64IZFBFMIN-NEXT:    beqz zero, .LBB0_2
+; RV64IZFBFMIN-NEXT:    j .LBB0_2
 ; RV64IZFBFMIN-NEXT:  # %bb.1: # %if.then
 ; RV64IZFBFMIN-NEXT:    ret
 ; RV64IZFBFMIN-NEXT:  .LBB0_2: # %if.else
@@ -581,7 +581,7 @@ if.then:
 define void @br_fcmp_true(bfloat %a, bfloat %b) nounwind {
 ; RV32IZFBFMIN-LABEL: br_fcmp_true:
 ; RV32IZFBFMIN:       # %bb.0:
-; RV32IZFBFMIN-NEXT:    beqz zero, .LBB16_2
+; RV32IZFBFMIN-NEXT:    j .LBB16_2
 ; RV32IZFBFMIN-NEXT:  # %bb.1: # %if.else
 ; RV32IZFBFMIN-NEXT:    ret
 ; RV32IZFBFMIN-NEXT:  .LBB16_2: # %if.then
@@ -591,7 +591,7 @@ define void @br_fcmp_true(bfloat %a, bfloat %b) nounwind {
 ;
 ; RV64IZFBFMIN-LABEL: br_fcmp_true:
 ; RV64IZFBFMIN:       # %bb.0:
-; RV64IZFBFMIN-NEXT:    beqz zero, .LBB16_2
+; RV64IZFBFMIN-NEXT:    j .LBB16_2
 ; RV64IZFBFMIN-NEXT:  # %bb.1: # %if.else
 ; RV64IZFBFMIN-NEXT:    ret
 ; RV64IZFBFMIN-NEXT:  .LBB16_2: # %if.then
diff --git a/llvm/test/CodeGen/RISCV/branch_zero.ll b/llvm/test/CodeGen/RISCV/branch_zero.ll
index fd0979977ba3b..0554f8c168c80 100644
--- a/llvm/test/CodeGen/RISCV/branch_zero.ll
+++ b/llvm/test/CodeGen/RISCV/branch_zero.ll
@@ -5,15 +5,13 @@
 define void @foo(i16 %finder_idx) {
 ; CHECK-LABEL: foo:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:  .LBB0_1: # %for.body
-; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:  # %bb.1: # %for.body
 ; CHECK-NEXT:    slli a0, a0, 48
 ; CHECK-NEXT:    bltz a0, .LBB0_4
 ; CHECK-NEXT:  # %bb.2: # %while.cond.preheader.i
-; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
 ; CHECK-NEXT:    li a0, 0
-; CHECK-NEXT:    bnez zero, .LBB0_1
-; CHECK-NEXT:  # %bb.3: # %while.body
+; CHECK-NEXT:    j .LBB0_3
+; CHECK-NEXT:  .LBB0_3: # %while.body
 ; CHECK-NEXT:  .LBB0_4: # %while.cond1.preheader.i
 entry:
   br label %for.body
@@ -46,15 +44,13 @@ if.then:
 define void @bar(i16 %finder_idx) {
 ; CHECK-LABEL: bar:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:  .LBB1_1: # %for.body
-; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:  # %bb.1: # %for.body
 ; CHECK-NEXT:    slli a0, a0, 48
 ; CHECK-NEXT:    bgez a0, .LBB1_4
 ; CHECK-NEXT:  # %bb.2: # %while.cond.preheader.i
-; CHECK-NEXT:    # in Loop: Header=BB1_1 Depth=1
 ; CHECK-NEXT:    li a0, 0
-; CHECK-NEXT:    bnez zero, .LBB1_1
-; CHECK-NEXT:  # %bb.3: # %while.body
+; CHECK-NEXT:    j .LBB1_3
+; CHECK-NEXT:  .LBB1_3: # %while.body
 ; CHECK-NEXT:  .LBB1_4: # %while.cond1.preheader.i
 entry:
   br label %for.body
diff --git a/llvm/test/CodeGen/RISCV/double-br-fcmp.ll b/llvm/test/CodeGen/RISCV/double-br-fcmp.ll
index 42f1b1360a2d3..b2c882878f8bc 100644
--- a/llvm/test/CodeGen/RISCV/double-br-fcmp.ll
+++ b/llvm/test/CodeGen/RISCV/double-br-fcmp.ll
@@ -14,7 +14,7 @@ declare void @exit(i32)
 define void @br_fcmp_false(double %a, double %b) nounwind {
 ; RV32IFD-LABEL: br_fcmp_false:
 ; RV32IFD:       # %bb.0:
-; RV32IFD-NEXT:    beqz zero, .LBB0_2
+; RV32IFD-NEXT:    j .LBB0_2
 ; RV32IFD-NEXT:  # %bb.1: # %if.then
 ; RV32IFD-NEXT:    ret
 ; RV32IFD-NEXT:  .LBB0_2: # %if.else
@@ -24,7 +24,7 @@ define void @br_fcmp_false(double %a, double %b) nounwind {
 ;
 ; RV64IFD-LABEL: br_fcmp_false:
 ; RV64IFD:       # %bb.0:
-; RV64IFD-NEXT:    beqz zero, .LBB0_2
+; RV64IFD-NEXT:    j .LBB0_2
 ; RV64IFD-NEXT:  # %bb.1: # %if.then
 ; RV64IFD-NEXT:    ret
 ; RV64IFD-NEXT:  .LBB0_2: # %if.else
@@ -34,7 +34,7 @@ define void @br_fcmp_false(double %a, double %b) nounwind {
 ;
 ; RV32IZFINXZDINX-LABEL: br_fcmp_false:
 ; RV32IZFINXZDINX:       # %bb.0:
-; RV32IZFINXZDINX-NEXT:    beqz zero, .LBB0_2
+; RV32IZFINXZDINX-NEXT:    j .LBB0_2
 ; RV32IZFINXZDINX-NEXT:  # %bb.1: # %if.then
 ; RV32IZFINXZDINX-NEXT:    ret
 ; RV32IZFINXZDINX-NEXT:  .LBB0_2: # %if.else
@@ -44,7 +44,7 @@ define void @br_fcmp_false(double %a, double %b) nounwind {
 ;
 ; RV64IZFINXZDINX-LABEL: br_fcmp_false:
 ; RV64IZFINXZDINX:       # %bb.0:
-; RV64IZFINXZDINX-NEXT:    beqz zero, .LBB0_2
+; RV64IZFINXZDINX-NEXT:    j .LBB0_2
 ; RV64IZFINXZDINX-NEXT:  # %bb.1: # %if.then
 ; RV64IZFINXZDINX-NEXT:    ret
 ; RV64IZFINXZDINX-NEXT:  .LBB0_2: # %if.else
@@ -893,7 +893,7 @@ if.then:
 define void @br_fcmp_true(double %a, double %b) nounwind {
 ; RV32IFD-LABEL: br_fcmp_true:
 ; RV32IFD:       # %bb.0:
-; RV32IFD-NEXT:    beqz zero, .LBB16_2
+; RV32IFD-NEXT:    j .LBB16_2
 ; RV32IFD-NEXT:  # %bb.1: # %if.else
 ; RV32IFD-NEXT:    ret
 ; RV32IFD-NEXT:  .LBB16_2: # %if.then
@@ -903,7 +903,7 @@ define void @br_fcmp_true(double %a, double %b) nounwind {
 ;
 ; RV64IFD-LABEL: br_fcmp_true:
 ; RV64IFD:       # %bb.0:
-; RV64IFD-NEXT:    beqz zero, .LBB16_2
+; RV64IFD-NEXT:    j .LBB16_2
 ; RV64IFD-NEXT:  # %bb.1: # %if.else
 ; RV64IFD-NEXT:    ret
 ; RV64IFD-NEXT:  .LBB16_2: # %if.then
@@ -913,7 +913,7 @@ define void @br_fcmp_true(double %a, double %b) nounwind {
 ;
 ; RV32IZFINXZDINX-LABEL: br_fcmp_true:
 ; RV32IZFINXZDINX:       # %bb.0:
-; RV32IZFINXZDINX-NEXT:    beqz zero, .LBB16_2
+; RV32IZFINXZDINX-NEXT:    j .LBB16_2
 ; RV32IZFINXZDINX-NEXT:  # %bb.1: # %if.else
 ; RV32IZFINXZDINX-NEXT:    ret
 ; RV32IZFINXZDINX-NEXT:  .LBB16_2: # %if.then
@@ -923,7 +923,7 @@ define void @br_fcmp_true(double %a, double %b) nounwind {
 ;
 ; RV64IZFINXZDINX-LABEL: br_fcmp_true:
 ; RV64IZFINXZDINX:       # %bb.0:
-; RV64IZFINXZDINX-NEXT:    beqz zero, .LBB16_2
+; RV64IZFINXZDINX-NEXT:    j .LBB16_2
 ; RV64IZFINXZDINX-NEXT:  # %bb.1: # %if.else
 ; RV64IZFINXZDINX-NEXT:    ret
 ; RV64IZFINXZDINX-NEXT:  .LBB16_2: # %if.then
diff --git a/llvm/test/CodeGen/RISCV/float-br-fcmp.ll b/llvm/test/CodeGen/RISCV/float-br-fcmp.ll
index 00da1cc1c8bbe..b2892115cac7a 100644
--- a/llvm/test/CodeGen/RISCV/float-br-fcmp.ll
+++ b/llvm/test/CodeGen/RISCV/float-br-fcmp.ll
@@ -15,7 +15,7 @@ declare float @dummy(float)
 define void @br_fcmp_false(float %a, float %b) nounwind {
 ; RV32IF-LABEL: br_fcmp_false:
 ; RV32IF:       # %bb.0:
-; RV32IF-NEXT:    beqz zero, .LBB0_2
+; RV32IF-NEXT:    j .LBB0_2
 ; RV32IF-NEXT:  # %bb.1: # %if.then
 ; RV32IF-NEXT:    ret
 ; RV32IF-NEXT:  .LBB0_2: # %if.else
@@ -25,7 +25,7 @@ define void @br_fcmp_false(float %a, float %b) nounwind {
 ;
 ; RV64IF-LABEL: br_fcmp_false:
 ; RV64IF:       # %bb.0:
-; RV64IF-NEXT:    beqz zero, .LBB0_2
+; RV64IF-NEXT:    j .LBB0_2
 ; RV64IF-NEXT:  # %bb.1: # %if.then
 ; RV64IF-NEXT:    ret
 ; RV64IF-NEXT:  .LBB0_2: # %if.else
@@ -35,7 +35,7 @@ define void @br_fcmp_false(float %a, float %b) nounwind {
 ;
 ; RV32IZFINX-LABEL: br_fcmp_false:
 ; RV32IZFINX:       # %bb.0:
-; RV32IZFINX-NEXT:    beqz zero, .LBB0_2
+; RV32IZFINX-NEXT:    j .LBB0_2
 ; RV32IZFINX-NEXT:  # %bb.1: # %if.then
 ; RV32IZFINX-NEXT:    ret
 ; RV32IZFINX-NEXT:  .LBB0_2: # %if.else
@@ -45,7 +45,7 @@ define void @br_fcmp_false(float %a, float %b) nounwind {
 ;
 ; RV64IZFINX-LABEL: br_fcmp_false:
 ; RV64IZFINX:       # %bb.0:
-; RV64IZFINX-NEXT:    beqz zero, .LBB0_2
+; RV64IZFINX-NEXT:    j .LBB0_2
 ; RV64IZFINX-NEXT:  # %bb.1: # %if.then
 ; RV64IZFINX-NEXT:    ret
 ; RV64IZFINX-NEXT:  .LBB0_2: # %if.else
@@ -894,7 +894,7 @@ if.then:
 define void @br_fcmp_true(float %a, float %b) nounwind {
 ; RV32IF-LABEL: br_fcmp_true:
 ; RV32IF:       # %bb.0:
-; RV32IF-NEXT:    beqz zero, .LBB16_2
+; RV32IF-NEXT:    j .LBB16_2
 ; RV32IF-NEXT:  # %bb.1: # %if.else
 ; RV32IF-NEXT:    ret
 ; RV32IF-NEXT:  .LBB16_2: # %if.then
@@ -904,7 +904,7 @@ define void @br_fcmp_true(float %a, float %b) nounwind {
 ;
 ; RV64IF-LABEL: br_fcmp_true:
 ; RV64IF:       # %bb.0:
-; RV64IF-NEXT:    beqz zero, .LBB16_2
+; RV64IF-NEXT:    j .LBB16_2
 ; RV64IF-NEXT:  # %bb.1: # %if.else
 ; RV64IF-NEXT:    ret
 ; RV64IF-NEXT:  .LBB16_2: # %if.then
@@ -914,7 +914,7 @@ define void @br_fcmp_true(float %a, float %b) nounwind {
 ;
 ; RV32IZFINX-LABEL: br_fcmp_true:
 ; RV32IZFINX:       # %bb.0:
-; RV32IZFINX-NEXT:    beqz zero, .LBB16_2
+; RV32IZFINX-NEXT:    j .LBB16_2
 ; RV32IZFINX-NEXT:  # %bb.1: # %if.else
 ; RV32IZFINX-NEXT:    ret
 ; RV32IZFINX-NEXT:  .LBB16_2: # %if.then
@@ -924,7 +924,7 @@ define void @br_fcmp_true(float %a, float %b) nounwind {
 ;
 ; RV64IZFINX-LABEL: br_fcmp_true:
 ; RV64IZFINX:       # %bb.0:
-; RV64IZFINX-NEXT:    beqz zero, .LBB16_2
+; RV64IZFINX-NEXT:    j .LBB16_2
 ; RV64IZFINX-NEXT:  # %bb.1: # %if.else
 ; RV64IZFINX-NEXT:    ret
 ; RV64IZFINX-NEXT:  .LBB16_2: # %if.then
diff --git a/llvm/test/CodeGen/RISCV/half-br-fcmp.ll b/llvm/test/CodeGen/RISCV/half-br-fcmp.ll
index 1cee927662c14..ab8f7cd4e6bfd 100644
--- a/llvm/test/CodeGen/RISCV/half-br-fcmp.ll
+++ b/llvm/test/CodeGen/RISCV/half-br-fcmp.ll
@@ -23,7 +23,7 @@ declare half @dummy(half)
 define void @br_fcmp_false(half %a, half %b) nounwind {
 ; RV32IZFH-LABEL: br_fcmp_false:
 ; RV32IZFH:       # %bb.0:
-; RV32IZFH-NEXT:    beqz zero, .LBB0_2
+; RV32IZFH-NEXT:    j .LBB0_2
 ; RV32IZFH-NEXT:  # %bb.1: # %if.then
 ; RV32IZFH-NEXT:    ret
 ; RV32IZFH-NEXT:  .LBB0_2: # %if.else
@@ -33,7 +33,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV64IZFH-LABEL: br_fcmp_false:
 ; RV64IZFH:       # %bb.0:
-; RV64IZFH-NEXT:    beqz zero, .LBB0_2
+; RV64IZFH-NEXT:    j .LBB0_2
 ; RV64IZFH-NEXT:  # %bb.1: # %if.then
 ; RV64IZFH-NEXT:    ret
 ; RV64IZFH-NEXT:  .LBB0_2: # %if.else
@@ -43,7 +43,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV32IZHINX-LABEL: br_fcmp_false:
 ; RV32IZHINX:       # %bb.0:
-; RV32IZHINX-NEXT:    beqz zero, .LBB0_2
+; RV32IZHINX-NEXT:    j .LBB0_2
 ; RV32IZHINX-NEXT:  # %bb.1: # %if.then
 ; RV32IZHINX-NEXT:    ret
 ; RV32IZHINX-NEXT:  .LBB0_2: # %if.else
@@ -53,7 +53,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV64IZHINX-LABEL: br_fcmp_false:
 ; RV64IZHINX:       # %bb.0:
-; RV64IZHINX-NEXT:    beqz zero, .LBB0_2
+; RV64IZHINX-NEXT:    j .LBB0_2
 ; RV64IZHINX-NEXT:  # %bb.1: # %if.then
 ; RV64IZHINX-NEXT:    ret
 ; RV64IZHINX-NEXT:  .LBB0_2: # %if.else
@@ -63,7 +63,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV32IZFHMIN-LABEL: br_fcmp_false:
 ; RV32IZFHMIN:       # %bb.0:
-; RV32IZFHMIN-NEXT:    beqz zero, .LBB0_2
+; RV32IZFHMIN-NEXT:    j .LBB0_2
 ; RV32IZFHMIN-NEXT:  # %bb.1: # %if.then
 ; RV32IZFHMIN-NEXT:    ret
 ; RV32IZFHMIN-NEXT:  .LBB0_2: # %if.else
@@ -73,7 +73,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV64IZFHMIN-LABEL: br_fcmp_false:
 ; RV64IZFHMIN:       # %bb.0:
-; RV64IZFHMIN-NEXT:    beqz zero, .LBB0_2
+; RV64IZFHMIN-NEXT:    j .LBB0_2
 ; RV64IZFHMIN-NEXT:  # %bb.1: # %if.then
 ; RV64IZFHMIN-NEXT:    ret
 ; RV64IZFHMIN-NEXT:  .LBB0_2: # %if.else
@@ -83,7 +83,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV32IZHINXMIN-LABEL: br_fcmp_false:
 ; RV32IZHINXMIN:       # %bb.0:
-; RV32IZHINXMIN-NEXT:    beqz zero, .LBB0_2
+; RV32IZHINXMIN-NEXT:    j .LBB0_2
 ; RV32IZHINXMIN-NEXT:  # %bb.1: # %if.then
 ; RV32IZHINXMIN-NEXT:    ret
 ; RV32IZHINXMIN-NEXT:  .LBB0_2: # %if.else
@@ -93,7 +93,7 @@ define void @br_fcmp_false(half %a, half %b) nounwind {
 ;
 ; RV64IZHINXMIN-LABEL: br_fcmp_false:
 ; RV64IZHINXMIN:       # %bb.0:
-; RV64IZHINXMIN-NEXT:    beqz zero, .LBB0_2
+; RV64IZHINXMIN-NEXT:    j .LBB0_2
 ; RV64IZHINXMIN-NEXT:  # %bb.1: # %if.then
 ; RV64IZHINXMIN-NEXT:    ret
 ; RV64IZHINXMIN-NEXT:  .LBB0_2: # %if.else
@@ -1754,7 +1754,7 @@ if.then:
 define void @br_fcmp_true(half %a, half %b) nounwind {
 ; RV32IZFH-LABEL: br_fcmp_true:
 ; RV32IZFH:       # %bb.0:
-; RV32IZFH-NEXT:    beqz zero, .LBB16_2
+; RV32IZFH-NEXT:    j .LBB16_2
 ; RV32IZFH-NEXT:  # %bb.1: # %if.else
 ; RV32IZFH-NEXT:    ret
 ; RV32IZFH-NEXT:  .LBB16_2: # %if.then
@@ -1764,7 +1764,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV64IZFH-LABEL: br_fcmp_true:
 ; RV64IZFH:       # %bb.0:
-; RV64IZFH-NEXT:    beqz zero, .LBB16_2
+; RV64IZFH-NEXT:    j .LBB16_2
 ; RV64IZFH-NEXT:  # %bb.1: # %if.else
 ; RV64IZFH-NEXT:    ret
 ; RV64IZFH-NEXT:  .LBB16_2: # %if.then
@@ -1774,7 +1774,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV32IZHINX-LABEL: br_fcmp_true:
 ; RV32IZHINX:       # %bb.0:
-; RV32IZHINX-NEXT:    beqz zero, .LBB16_2
+; RV32IZHINX-NEXT:    j .LBB16_2
 ; RV32IZHINX-NEXT:  # %bb.1: # %if.else
 ; RV32IZHINX-NEXT:    ret
 ; RV32IZHINX-NEXT:  .LBB16_2: # %if.then
@@ -1784,7 +1784,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV64IZHINX-LABEL: br_fcmp_true:
 ; RV64IZHINX:       # %bb.0:
-; RV64IZHINX-NEXT:    beqz zero, .LBB16_2
+; RV64IZHINX-NEXT:    j .LBB16_2
 ; RV64IZHINX-NEXT:  # %bb.1: # %if.else
 ; RV64IZHINX-NEXT:    ret
 ; RV64IZHINX-NEXT:  .LBB16_2: # %if.then
@@ -1794,7 +1794,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV32IZFHMIN-LABEL: br_fcmp_true:
 ; RV32IZFHMIN:       # %bb.0:
-; RV32IZFHMIN-NEXT:    beqz zero, .LBB16_2
+; RV32IZFHMIN-NEXT:    j .LBB16_2
 ; RV32IZFHMIN-NEXT:  # %bb.1: # %if.else
 ; RV32IZFHMIN-NEXT:    ret
 ; RV32IZFHMIN-NEXT:  .LBB16_2: # %if.then
@@ -1804,7 +1804,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV64IZFHMIN-LABEL: br_fcmp_true:
 ; RV64IZFHMIN:       # %bb.0:
-; RV64IZFHMIN-NEXT:    beqz zero, .LBB16_2
+; RV64IZFHMIN-NEXT:    j .LBB16_2
 ; RV64IZFHMIN-NEXT:  # %bb.1: # %if.else
 ; RV64IZFHMIN-NEXT:    ret
 ; RV64IZFHMIN-NEXT:  .LBB16_2: # %if.then
@@ -1814,7 +1814,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV32IZHINXMIN-LABEL: br_fcmp_true:
 ; RV32IZHINXMIN:       # %bb.0:
-; RV32IZHINXMIN-NEXT:    beqz zero, .LBB16_2
+; RV32IZHINXMIN-NEXT:    j .LBB16_2
 ; RV32IZHINXMIN-NEXT:  # %bb.1: # %if.else
 ; RV32IZHINXMIN-NEXT:    ret
 ; RV32IZHINXMIN-NEXT:  .LBB16_2: # %if.then
@@ -1824,7 +1824,7 @@ define void @br_fcmp_true(half %a, half %b) nounwind {
 ;
 ; RV64IZHINXMIN-LABEL: br_fcmp_true:
 ; RV64IZHINXMIN:       # %bb.0:
-; RV64IZHINXMIN-NEXT:    beqz zero, .LBB16_2
+; RV64IZHINXMIN-NEXT:    j .LBB16_2
 ; RV64IZHINXMIN-NEXT:  # %bb.1: # %if.else
 ; RV64IZHINXMIN-NEXT:    ret
 ; RV64IZHINXMIN-NEXT:  .LBB16_2: # %if.then
diff --git a/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll b/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll
index 4947423971c6b..a71fbf1b9280e 100644
--- a/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll
+++ b/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll
@@ -16,66 +16,60 @@ define i1 @sink_li(ptr %text, ptr %text.addr.0) nounwind {
 ; CHECK-NEXT:    beqz s0, .LBB0_25
 ; CHECK-NEXT:  .LBB0_1: # %while.body
 ; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_3
+; CHECK-NEXT:    j .LBB0_3
 ; CHECK-NEXT:  # %bb.2: # %while.body
-; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_15
+; CHECK-NEXT:    j .LBB0_15
 ; CHECK-NEXT:  .LBB0_3: # %while.body.1
 ; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_5
+; CHECK-NEXT:    j .LBB0_5
 ; CHECK-NEXT:  # %bb.4: # %while.body.1
-; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_16
+; CHECK-NEXT:    j .LBB0_16
 ; CHECK-NEXT:  .LBB0_5: # %while.body.3
 ; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_7
+; CHECK-NEXT:    j .LBB0_7
 ; CHECK-NEXT:  # %bb.6: # %while.body.3
-; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_18
+; CHECK-NEXT:    j .LBB0_18
 ; CHECK-NEXT:  .LBB0_7: # %while.body.4
 ; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_9
+; CHECK-NEXT:    j .LBB0_9
 ; CHECK-NEXT:  # %bb.8: # %while.body.4
-; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_20
+; CHECK-NEXT:    j .LBB0_20
 ; CHECK-NEXT:  .LBB0_9: # %while.body.5
 ; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_11
+; CHECK-NEXT:    j .LBB0_11
 ; CHECK-NEXT:  # %bb.10: # %while.body.5
-; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_22
+; CHECK-NEXT:    j .LBB0_22
 ; CHECK-NEXT:  .LBB0_11: # %while.body.6
 ; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    beqz zero, .LBB0_1
+; CHECK-NEXT:    j .LBB0_1
 ; CHECK-NEXT:  # %bb.12: # %while.body.6
-; CHECK-NEXT:    # in Loop: Header=BB0_1 Depth=1
-; CHECK-NEXT:    bnez zero, .LBB0_1
-; CHECK-NEXT:  # %bb.13: # %while.body.6
-; CHECK-NEXT:    bnez zero, .LBB0_23
-; CHECK-NEXT:  # %bb.14: # %strdup.exit.split.loop.exit126
+; CHECK-NEXT:    j .LBB0_13
+; CHECK-NEXT:  .LBB0_13: # %while.body.6
+; CHECK-NEXT:    j .LBB0_14
+; CHECK-NEXT:  .LBB0_14: # %strdup.exit.split.loop.exit126
 ; CHECK-NEXT:    addi s0, s1, 7
 ; CHECK-NEXT:    j .LBB0_24
 ; CHECK-NEXT:  .LBB0_15: # %while.body
-; CHECK-NEXT:    bnez zero, .LBB0_25
+; CHECK-NEXT:    j .LBB0_17
 ; CHECK-NEXT:    j .LBB0_17
 ; CHECK-NEXT:  .LBB0_16: # %while.body.1
-; CHECK-NEXT:    bnez zero, .LBB0_23
+; CHECK-NEXT:    j .LBB0_17
 ; CHECK-NEXT:  .LBB0_17: # %strdup.exit.loopexit
 ; CHECK-NEXT:    li s0, 0
 ; CHECK-NEXT:    j .LBB0_24
 ; CHECK-NEXT:  .LBB0_18: # %while.body.3
-; CHECK-NEXT:    bnez zero, .LBB0_23
-; CHECK-NEXT:  # %bb.19: # %strdup.exit.split.loop.exit120
+; CHECK-NEXT:    j .LBB0_19
+; CHECK-NEXT:  .LBB0_19: # %strdup.exit.split.loop.exit120
 ; CHECK-NEXT:    addi s0, s1, 4
 ; CHECK-NEXT:    j .LBB0_24
 ; CHECK-NEXT:  .LBB0_20: # %while.body.4
-; CHECK-NEXT:    bnez zero, .LBB0_23
-; CHECK-NEXT:  # %bb.21: # %strdup.exit.split.loop.exit122
+; CHECK-NEXT:    j .LBB0_21
+; CHECK-NEXT:  .LBB0_21: # %strdup.exit.split.loop.exit122
 ; CHECK-NEXT:    addi s0, s1, 5
 ; CHECK-NEXT:    j .LBB0_24
 ; CHECK-NEXT:  .LBB0_22: # %while.body.5
-; CHECK-NEXT:    beqz zero, .LBB0_24
-; CHECK-NEXT:  .LBB0_23:
+; CHECK-NEXT:    j .LBB0_24
+; CHECK-NEXT:  # %bb.23:
 ; CHECK-NEXT:    li a1, 0
 ; CHECK-NEXT:    j .LBB0_25
 ; CHECK-NEXT:  .LBB0_24: # %strdup.exit
diff --git a/llvm/test/CodeGen/RISCV/rvv/vxrm-insert-out-of-loop.ll b/llvm/test/CodeGen/RISCV/rvv/vxrm-insert-out-of-loop.ll
index c35f05be304cc..8c019cbf8c25d 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vxrm-insert-out-of-loop.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vxrm-insert-out-of-loop.ll
@@ -26,10 +26,10 @@ define void @test1(ptr nocapture noundef writeonly %dst, i32 noundef signext %i_
 ; RV32-NEXT:    slli t1, t2, 1
 ; RV32-NEXT:    li t6, 32
 ; RV32-NEXT:    mv t0, t1
-; RV32-NEXT:    bnez zero, .LBB0_4
-; RV32-NEXT:  # %bb.3: # %for.cond1.preheader.us.preheader
+; RV32-NEXT:    j .LBB0_3
+; RV32-NEXT:  .LBB0_3: # %for.cond1.preheader.us.preheader
 ; RV32-NEXT:    li t0, 32
-; RV32-NEXT:  .LBB0_4: # %for.cond1.preheader.us.preheader
+; RV32-NEXT:  # %bb.4: # %for.cond1.preheader.us.preheader
 ; RV32-NEXT:    addi sp, sp, -16
 ; RV32-NEXT:    .cfi_def_cfa_offset 16
 ; RV32-NEXT:    sw s0, 12(sp) # 4-byte Folded Spill
@@ -38,6 +38,7 @@ define void @test1(ptr nocapture noundef writeonly %dst, i32 noundef signext %i_
 ; RV32-NEXT:    .cfi_offset s0, -4
 ; RV32-NEXT:    .cfi_offset s1, -8
 ; RV32-NEXT:    .cfi_offset s2, -12
+; RV32-NEXT:    .cfi_remember_state
 ; RV32-NEXT:    add t3, a0, t3
 ; RV32-NEXT:    add t4, a2, t4
 ; RV32-NEXT:    add s0, a4, t5
@@ -48,10 +49,11 @@ define void @test1(ptr nocapture noundef writeonly %dst, i32 noundef signext %i_
 ; RV32-NEXT:    add t3, t3, a6
 ; RV32-NEXT:    add t5, t4, a6
 ; RV32-NEXT:    add t4, s0, a6
-; RV32-NEXT:    beqz zero, .LBB0_8
+; RV32-NEXT:    j .LBB0_8
 ; RV32-NEXT:  # %bb.7: # %for.cond1.preheader.us.preheader
 ; RV32-NEXT:    mv t1, t0
 ; RV32-NEXT:  .LBB0_8: # %for.cond1.preheader.us.preheader
+; RV32-NEXT:    .cfi_restore_state
 ; RV32-NEXT:    li t0, 0
 ; RV32-NEXT:    sltu t5, a0, t5
 ; RV32-NEXT:    sltu t6, a2, t3

>From 8aac8e91f57116c6489d02ffd5c419ab78bda4a9 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Wed, 26 Mar 2025 18:13:32 -0300
Subject: [PATCH 4/4] Fix pipeline tests

Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
---
 llvm/test/CodeGen/RISCV/O0-pipeline.ll | 1 +
 llvm/test/CodeGen/RISCV/O3-pipeline.ll | 1 +
 2 files changed, 2 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/O0-pipeline.ll b/llvm/test/CodeGen/RISCV/O0-pipeline.ll
index 694662eab1681..0b02c8a5e66cb 100644
--- a/llvm/test/CodeGen/RISCV/O0-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O0-pipeline.ll
@@ -62,6 +62,7 @@
 ; CHECK-NEXT:       Insert fentry calls
 ; CHECK-NEXT:       Insert XRay ops
 ; CHECK-NEXT:       Implement the 'patchable-function' attribute
+; CHECK-NEXT:       RISC-V Late Stage Optimizations
 ; CHECK-NEXT:       Branch relaxation pass
 ; CHECK-NEXT:       RISC-V Make Compressible
 ; CHECK-NEXT:       Contiguously Lay Out Funclets
diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
index beef7a574dc4f..1ca9ecaac6342 100644
--- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
@@ -194,6 +194,7 @@
 ; CHECK-NEXT:       Insert XRay ops
 ; CHECK-NEXT:       Implement the 'patchable-function' attribute
 ; CHECK-NEXT:       Machine Copy Propagation Pass
+; CHECK-NEXT:       RISC-V Late Stage Optimizations
 ; CHECK-NEXT:       Branch relaxation pass
 ; CHECK-NEXT:       RISC-V Make Compressible
 ; CHECK-NEXT:       Contiguously Lay Out Funclets



More information about the llvm-commits mailing list