[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 09:16:04 PDT 2025
https://github.com/mikhailramalho updated https://github.com/llvm/llvm-project/pull/133256
>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/9] [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/9] 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/9] [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/9] 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
>From 3d28d5f8bf4296db5f85664175aa5379d2373659 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Thu, 27 Mar 2025 11:46:17 -0300
Subject: [PATCH 5/9] Updated description
Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
---
llvm/lib/Target/RISCV/RISCVLateOpt.cpp | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/RISCV/RISCVLateOpt.cpp b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
index 7fa04f0cbba9b..d9352cec2f20e 100644
--- a/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
+++ b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
@@ -6,7 +6,9 @@
//
//===----------------------------------------------------------------------===//
///
-/// This file provides RISC-V specific target descriptions.
+/// This file provides RISC-V specific target optimizations, currently it's
+/// limited to convert conditional branches into unconditional branches when
+/// the condition can be statically evaluated.
///
//===----------------------------------------------------------------------===//
>From 36d9adcc222e88d99c2f374d19010ffed2832cb6 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Thu, 27 Mar 2025 12:03:05 -0300
Subject: [PATCH 6/9] Removed messy code
Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
---
llvm/lib/Target/RISCV/RISCVLateOpt.cpp | 124 ++++++++++---------------
1 file changed, 51 insertions(+), 73 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVLateOpt.cpp b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
index d9352cec2f20e..5dac51549065c 100644
--- a/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
+++ b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
@@ -46,7 +46,7 @@ struct RISCVLateOpt : public MachineFunctionPass {
bool runOnMachineFunction(MachineFunction &Fn) override;
private:
- bool trySimplifyCondBr(MachineInstr *MI, MachineBasicBlock *TBB,
+ bool trySimplifyCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
SmallVectorImpl<MachineOperand> &Cond) const;
@@ -58,10 +58,32 @@ char RISCVLateOpt::ID = 0;
INITIALIZE_PASS(RISCVLateOpt, "riscv-late-opt", RISCV_LATE_OPT_NAME, false,
false)
+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;
+ }
+}
+
bool RISCVLateOpt::trySimplifyCondBr(
- MachineInstr *MI, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
+ MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
SmallVectorImpl<MachineOperand> &Cond) const {
+ if (!TBB || Cond.size() != 3)
+ return false;
+
RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
assert(CC != RISCVCC::COND_INVALID);
@@ -75,8 +97,7 @@ bool RISCVLateOpt::trySimplifyCondBr(
return false;
};
- MachineBasicBlock *MBB = MI->getParent();
- MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
+ 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())
@@ -94,69 +115,35 @@ bool RISCVLateOpt::trySimplifyCondBr(
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;
- }
- }
+ Folded = evaluateCondBranch(CC, C0, C1) ? TBB : FBB;
+
+ // At this point, its legal to optimize.
+ RII->removeBranch(MBB);
+ Cond.clear();
- // Do the conversion
- // Build the new unconditional branch
- DebugLoc DL = MBB->findBranchDebugLoc();
+ // Only need to insert a branch if we're not falling through.
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);
+ DebugLoc DL = MBB.findBranchDebugLoc();
+ RII->insertBranch(MBB, Folded, nullptr, {}, DL);
}
- // 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);
- }
+ // Update the successors. Remove them all and add back the correct one.
+ while (!MBB.succ_empty())
+ MBB.removeSuccessor(MBB.succ_end() - 1);
+
+ // If it's a fallthrough, we need to figure out where MBB is going.
+ if (!Folded) {
+ MachineFunction::iterator Fallthrough = ++MBB.getIterator();
+ if (Fallthrough != MBB.getParent()->end())
+ MBB.addSuccessor(&*Fallthrough);
+ } else
+ MBB.addSuccessor(Folded);
- MI->eraseFromParent();
+ TBB = Folded;
+ FBB = nullptr;
return true;
}
+
return false;
}
@@ -170,19 +157,10 @@ bool RISCVLateOpt::runOnMachineFunction(MachineFunction &Fn) {
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);
- }
+ MachineBasicBlock *TBB, *FBB;
+ SmallVector<MachineOperand, 4> Cond;
+ if (!RII->analyzeBranch(MBB, TBB, FBB, Cond, /*AllowModify=*/false))
+ Changed |= trySimplifyCondBr(MBB, TBB, FBB, Cond);
}
return Changed;
>From 08ddd9e98188518907d5fbbf34c611a08789df69 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Thu, 27 Mar 2025 12:03:18 -0300
Subject: [PATCH 7/9] Updated tests
Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
---
llvm/test/CodeGen/RISCV/branch_zero.ll | 6 ++----
.../CodeGen/RISCV/machine-sink-load-immediate.ll | 14 ++++----------
.../CodeGen/RISCV/rvv/vxrm-insert-out-of-loop.ll | 3 +--
3 files changed, 7 insertions(+), 16 deletions(-)
diff --git a/llvm/test/CodeGen/RISCV/branch_zero.ll b/llvm/test/CodeGen/RISCV/branch_zero.ll
index 0554f8c168c80..9f96f0d94a27a 100644
--- a/llvm/test/CodeGen/RISCV/branch_zero.ll
+++ b/llvm/test/CodeGen/RISCV/branch_zero.ll
@@ -10,8 +10,7 @@ define void @foo(i16 %finder_idx) {
; CHECK-NEXT: bltz a0, .LBB0_4
; CHECK-NEXT: # %bb.2: # %while.cond.preheader.i
; CHECK-NEXT: li a0, 0
-; CHECK-NEXT: j .LBB0_3
-; CHECK-NEXT: .LBB0_3: # %while.body
+; CHECK-NEXT: # %bb.3: # %while.body
; CHECK-NEXT: .LBB0_4: # %while.cond1.preheader.i
entry:
br label %for.body
@@ -49,8 +48,7 @@ define void @bar(i16 %finder_idx) {
; CHECK-NEXT: bgez a0, .LBB1_4
; CHECK-NEXT: # %bb.2: # %while.cond.preheader.i
; CHECK-NEXT: li a0, 0
-; CHECK-NEXT: j .LBB1_3
-; CHECK-NEXT: .LBB1_3: # %while.body
+; CHECK-NEXT: # %bb.3: # %while.body
; CHECK-NEXT: .LBB1_4: # %while.cond1.preheader.i
entry:
br label %for.body
diff --git a/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll b/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll
index a71fbf1b9280e..6d3000a513538 100644
--- a/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll
+++ b/llvm/test/CodeGen/RISCV/machine-sink-load-immediate.ll
@@ -43,28 +43,22 @@ define i1 @sink_li(ptr %text, ptr %text.addr.0) nounwind {
; CHECK-NEXT: # in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT: j .LBB0_1
; CHECK-NEXT: # %bb.12: # %while.body.6
-; 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: # %bb.13: # %while.body.6
+; CHECK-NEXT: # %bb.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: j .LBB0_17
-; CHECK-NEXT: j .LBB0_17
; CHECK-NEXT: .LBB0_16: # %while.body.1
-; 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: j .LBB0_19
-; CHECK-NEXT: .LBB0_19: # %strdup.exit.split.loop.exit120
+; CHECK-NEXT: # %bb.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: j .LBB0_21
-; CHECK-NEXT: .LBB0_21: # %strdup.exit.split.loop.exit122
+; CHECK-NEXT: # %bb.21: # %strdup.exit.split.loop.exit122
; CHECK-NEXT: addi s0, s1, 5
; CHECK-NEXT: j .LBB0_24
; CHECK-NEXT: .LBB0_22: # %while.body.5
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 8c019cbf8c25d..75f4b977a98b0 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,8 +26,7 @@ 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: j .LBB0_3
-; RV32-NEXT: .LBB0_3: # %for.cond1.preheader.us.preheader
+; RV32-NEXT: # %bb.3: # %for.cond1.preheader.us.preheader
; RV32-NEXT: li t0, 32
; RV32-NEXT: # %bb.4: # %for.cond1.preheader.us.preheader
; RV32-NEXT: addi sp, sp, -16
>From df34ba64f4857d5f265708e9cd8a392436c7d170 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Thu, 27 Mar 2025 12:19:14 -0300
Subject: [PATCH 8/9] Make evaluateCondBranch, isLoadImm, and isFromLoadImm
static member function of RISCVInstrInfo
Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
---
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 53 +++++++++++++-----------
llvm/lib/Target/RISCV/RISCVInstrInfo.h | 7 ++++
llvm/lib/Target/RISCV/RISCVLateOpt.cpp | 49 +++-------------------
3 files changed, 40 insertions(+), 69 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index af9975aca206e..2b60b8ee42d5d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -998,7 +998,7 @@ static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
}
}
-static bool evaluateCondBranch(unsigned CC, int64_t C0, int64_t C1) {
+bool RISCVInstrInfo::evaluateCondBranch(unsigned CC, int64_t C0, int64_t C1) {
switch (CC) {
default:
llvm_unreachable("Unexpected CC");
@@ -1302,6 +1302,30 @@ bool RISCVInstrInfo::reverseBranchCondition(
return false;
}
+bool RISCVInstrInfo::isLoadImm(const MachineInstr *MI, int64_t &Imm) {
+ // For now, Only checks for LI (i.e. ADDI x0, imm)
+ if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
+ MI->getOperand(1).getReg() == RISCV::X0) {
+ Imm = MI->getOperand(2).getImm();
+ return true;
+ }
+ return false;
+}
+
+bool RISCVInstrInfo::isFromLoadImm(const MachineRegisterInfo &MRI,
+ const MachineOperand &Op, int64_t &Imm) {
+ // Either a load from immediate instruction or X0.
+ 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);
+}
+
bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
MachineBasicBlock *MBB = MI.getParent();
MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
@@ -1324,31 +1348,10 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
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)) {
+ if (isFromLoadImm(MRI, Cond[1], C0) && isFromLoadImm(MRI, Cond[2], C1)) {
unsigned NewCC =
evaluateCondBranch(CC, C0, C1) ? RISCVCC::COND_EQ : RISCVCC::COND_NE;
Cond[0] = MachineOperand::CreateImm(NewCC);
@@ -1394,7 +1397,7 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
return Register();
};
- if (isFromLoadImm(LHS, C0) && MRI.hasOneUse(LHS.getReg())) {
+ if (isFromLoadImm(MRI, LHS, C0) && MRI.hasOneUse(LHS.getReg())) {
// Might be case 1.
// Signed integer overflow is UB. (UINT64_MAX is bigger so we don't need
// to worry about unsigned overflow here)
@@ -1409,7 +1412,7 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
modifyBranch();
return true;
}
- } else if (isFromLoadImm(RHS, C0) && MRI.hasOneUse(RHS.getReg())) {
+ } else if (isFromLoadImm(MRI, RHS, C0) && MRI.hasOneUse(RHS.getReg())) {
// Might be case 2.
// For unsigned cases, we don't want C1 to wrap back to UINT64_MAX
// when C0 is zero.
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index fcf296fcba74b..2584606866fa4 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -307,6 +307,13 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
static bool isLdStSafeToPair(const MachineInstr &LdSt,
const TargetRegisterInfo *TRI);
+ static bool evaluateCondBranch(unsigned CC, int64_t C0, int64_t C1);
+
+ static bool isLoadImm(const MachineInstr *MI, int64_t &Imm);
+
+ static bool isFromLoadImm(const MachineRegisterInfo &MRI,
+ const MachineOperand &Op, int64_t &Imm);
+
protected:
const RISCVSubtarget &STI;
diff --git a/llvm/lib/Target/RISCV/RISCVLateOpt.cpp b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
index 5dac51549065c..a482e3c4d6459 100644
--- a/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
+++ b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
@@ -58,25 +58,6 @@ char RISCVLateOpt::ID = 0;
INITIALIZE_PASS(RISCVLateOpt, "riscv-late-opt", RISCV_LATE_OPT_NAME, false,
false)
-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;
- }
-}
-
bool RISCVLateOpt::trySimplifyCondBr(
MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
SmallVectorImpl<MachineOperand> &Cond) const {
@@ -87,35 +68,15 @@ bool RISCVLateOpt::trySimplifyCondBr(
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;
- };
-
- 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)) {
- Folded = evaluateCondBranch(CC, C0, C1) ? TBB : FBB;
+
+ MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
+ if (RISCVInstrInfo::isFromLoadImm(MRI, Cond[1], C0) &&
+ RISCVInstrInfo::isFromLoadImm(MRI, Cond[2], C1)) {
+ Folded = RISCVInstrInfo::evaluateCondBranch(CC, C0, C1) ? TBB : FBB;
// At this point, its legal to optimize.
RII->removeBranch(MBB);
>From e53bb1b4e54a2dbae7dd7005018f95d69fcee571 Mon Sep 17 00:00:00 2001
From: "Mikhail R. Gadelha" <mikhail at igalia.com>
Date: Thu, 27 Mar 2025 13:13:18 -0300
Subject: [PATCH 9/9] Cleanup includes
Signed-off-by: Mikhail R. Gadelha <mikhail at igalia.com>
---
llvm/lib/Target/RISCV/RISCVLateOpt.cpp | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVLateOpt.cpp b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
index a482e3c4d6459..0f2ed38c94edb 100644
--- a/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
+++ b/llvm/lib/Target/RISCV/RISCVLateOpt.cpp
@@ -12,18 +12,8 @@
///
//===----------------------------------------------------------------------===//
-#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;
More information about the llvm-commits
mailing list