Skip to content

Commit 8742022

Browse files
authored
[RISCV] Canonicalize foldable branch conditions in optimizeCondBranch (#132988)
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 #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.
1 parent b38c23b commit 8742022

File tree

6 files changed

+163
-170
lines changed

6 files changed

+163
-170
lines changed

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,25 @@ static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
997997
}
998998
}
999999

1000+
static bool evaluateCondBranch(unsigned CC, int64_t C0, int64_t C1) {
1001+
switch (CC) {
1002+
default:
1003+
llvm_unreachable("Unexpected CC");
1004+
case RISCVCC::COND_EQ:
1005+
return C0 == C1;
1006+
case RISCVCC::COND_NE:
1007+
return C0 != C1;
1008+
case RISCVCC::COND_LT:
1009+
return C0 < C1;
1010+
case RISCVCC::COND_GE:
1011+
return C0 >= C1;
1012+
case RISCVCC::COND_LTU:
1013+
return (uint64_t)C0 < (uint64_t)C1;
1014+
case RISCVCC::COND_GEU:
1015+
return (uint64_t)C0 >= (uint64_t)C1;
1016+
}
1017+
}
1018+
10001019
// The contents of values added to Cond are not examined outside of
10011020
// RISCVInstrInfo, giving us flexibility in what to push to it. For RISCV, we
10021021
// push BranchOpcode, Reg1, Reg2.
@@ -1294,6 +1313,49 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
12941313
RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
12951314
assert(CC != RISCVCC::COND_INVALID);
12961315

1316+
auto modifyBranch = [&]() {
1317+
// Build the new branch and remove the old one.
1318+
BuildMI(*MBB, MI, MI.getDebugLoc(),
1319+
getBrCond(static_cast<RISCVCC::CondCode>(Cond[0].getImm())))
1320+
.add(Cond[1])
1321+
.add(Cond[2])
1322+
.addMBB(TBB);
1323+
MI.eraseFromParent();
1324+
};
1325+
1326+
// Right now we only care about LI (i.e. ADDI x0, imm)
1327+
auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
1328+
if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
1329+
MI->getOperand(1).getReg() == RISCV::X0) {
1330+
Imm = MI->getOperand(2).getImm();
1331+
return true;
1332+
}
1333+
return false;
1334+
};
1335+
// Either a load from immediate instruction or X0.
1336+
auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
1337+
if (!Op.isReg())
1338+
return false;
1339+
Register Reg = Op.getReg();
1340+
if (Reg == RISCV::X0) {
1341+
Imm = 0;
1342+
return true;
1343+
}
1344+
return Reg.isVirtual() && isLoadImm(MRI.getVRegDef(Reg), Imm);
1345+
};
1346+
1347+
// Canonicalize conditional branches which can be constant folded into
1348+
// beqz or bnez. We can't modify the CFG here.
1349+
int64_t C0, C1;
1350+
if (isFromLoadImm(Cond[1], C0) && isFromLoadImm(Cond[2], C1)) {
1351+
unsigned NewCC =
1352+
evaluateCondBranch(CC, C0, C1) ? RISCVCC::COND_EQ : RISCVCC::COND_NE;
1353+
Cond[0] = MachineOperand::CreateImm(NewCC);
1354+
Cond[1] = Cond[2] = MachineOperand::CreateReg(RISCV::X0, /*isDef=*/false);
1355+
modifyBranch();
1356+
return true;
1357+
}
1358+
12971359
if (CC == RISCVCC::COND_EQ || CC == RISCVCC::COND_NE)
12981360
return false;
12991361

@@ -1314,24 +1376,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13141376
//
13151377
// To make sure this optimization is really beneficial, we only
13161378
// optimize for cases where Y had only one use (i.e. only used by the branch).
1317-
1318-
// Right now we only care about LI (i.e. ADDI x0, imm)
1319-
auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
1320-
if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
1321-
MI->getOperand(1).getReg() == RISCV::X0) {
1322-
Imm = MI->getOperand(2).getImm();
1323-
return true;
1324-
}
1325-
return false;
1326-
};
1327-
// Either a load from immediate instruction or X0.
1328-
auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
1329-
if (!Op.isReg())
1330-
return false;
1331-
Register Reg = Op.getReg();
1332-
return Reg.isVirtual() && isLoadImm(MRI.getVRegDef(Reg), Imm);
1333-
};
1334-
13351379
MachineOperand &LHS = MI.getOperand(0);
13361380
MachineOperand &RHS = MI.getOperand(1);
13371381
// Try to find the register for constant Z; return
@@ -1349,8 +1393,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13491393
return Register();
13501394
};
13511395

1352-
bool Modify = false;
1353-
int64_t C0;
13541396
if (isFromLoadImm(LHS, C0) && MRI.hasOneUse(LHS.getReg())) {
13551397
// Might be case 1.
13561398
// Signed integer overflow is UB. (UINT64_MAX is bigger so we don't need
@@ -1363,7 +1405,8 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13631405
// We might extend the live range of Z, clear its kill flag to
13641406
// account for this.
13651407
MRI.clearKillFlags(RegZ);
1366-
Modify = true;
1408+
modifyBranch();
1409+
return true;
13671410
}
13681411
} else if (isFromLoadImm(RHS, C0) && MRI.hasOneUse(RHS.getReg())) {
13691412
// Might be case 2.
@@ -1377,22 +1420,12 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13771420
// We might extend the live range of Z, clear its kill flag to
13781421
// account for this.
13791422
MRI.clearKillFlags(RegZ);
1380-
Modify = true;
1423+
modifyBranch();
1424+
return true;
13811425
}
13821426
}
13831427

1384-
if (!Modify)
1385-
return false;
1386-
1387-
// Build the new branch and remove the old one.
1388-
BuildMI(*MBB, MI, MI.getDebugLoc(),
1389-
getBrCond(static_cast<RISCVCC::CondCode>(Cond[0].getImm())))
1390-
.add(Cond[1])
1391-
.add(Cond[2])
1392-
.addMBB(TBB);
1393-
MI.eraseFromParent();
1394-
1395-
return true;
1428+
return false;
13961429
}
13971430

13981431
MachineBasicBlock *

llvm/test/CodeGen/RISCV/bfloat-br-fcmp.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ declare bfloat @dummy(bfloat)
1111
define void @br_fcmp_false(bfloat %a, bfloat %b) nounwind {
1212
; RV32IZFBFMIN-LABEL: br_fcmp_false:
1313
; RV32IZFBFMIN: # %bb.0:
14-
; RV32IZFBFMIN-NEXT: li a0, 1
15-
; RV32IZFBFMIN-NEXT: bnez a0, .LBB0_2
14+
; RV32IZFBFMIN-NEXT: beqz zero, .LBB0_2
1615
; RV32IZFBFMIN-NEXT: # %bb.1: # %if.then
1716
; RV32IZFBFMIN-NEXT: ret
1817
; RV32IZFBFMIN-NEXT: .LBB0_2: # %if.else
@@ -22,8 +21,7 @@ define void @br_fcmp_false(bfloat %a, bfloat %b) nounwind {
2221
;
2322
; RV64IZFBFMIN-LABEL: br_fcmp_false:
2423
; RV64IZFBFMIN: # %bb.0:
25-
; RV64IZFBFMIN-NEXT: li a0, 1
26-
; RV64IZFBFMIN-NEXT: bnez a0, .LBB0_2
24+
; RV64IZFBFMIN-NEXT: beqz zero, .LBB0_2
2725
; RV64IZFBFMIN-NEXT: # %bb.1: # %if.then
2826
; RV64IZFBFMIN-NEXT: ret
2927
; RV64IZFBFMIN-NEXT: .LBB0_2: # %if.else
@@ -583,8 +581,7 @@ if.then:
583581
define void @br_fcmp_true(bfloat %a, bfloat %b) nounwind {
584582
; RV32IZFBFMIN-LABEL: br_fcmp_true:
585583
; RV32IZFBFMIN: # %bb.0:
586-
; RV32IZFBFMIN-NEXT: li a0, 1
587-
; RV32IZFBFMIN-NEXT: bnez a0, .LBB16_2
584+
; RV32IZFBFMIN-NEXT: beqz zero, .LBB16_2
588585
; RV32IZFBFMIN-NEXT: # %bb.1: # %if.else
589586
; RV32IZFBFMIN-NEXT: ret
590587
; RV32IZFBFMIN-NEXT: .LBB16_2: # %if.then
@@ -594,8 +591,7 @@ define void @br_fcmp_true(bfloat %a, bfloat %b) nounwind {
594591
;
595592
; RV64IZFBFMIN-LABEL: br_fcmp_true:
596593
; RV64IZFBFMIN: # %bb.0:
597-
; RV64IZFBFMIN-NEXT: li a0, 1
598-
; RV64IZFBFMIN-NEXT: bnez a0, .LBB16_2
594+
; RV64IZFBFMIN-NEXT: beqz zero, .LBB16_2
599595
; RV64IZFBFMIN-NEXT: # %bb.1: # %if.else
600596
; RV64IZFBFMIN-NEXT: ret
601597
; RV64IZFBFMIN-NEXT: .LBB16_2: # %if.then

llvm/test/CodeGen/RISCV/double-br-fcmp.ll

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ declare void @exit(i32)
1414
define void @br_fcmp_false(double %a, double %b) nounwind {
1515
; RV32IFD-LABEL: br_fcmp_false:
1616
; RV32IFD: # %bb.0:
17-
; RV32IFD-NEXT: li a0, 1
18-
; RV32IFD-NEXT: bnez a0, .LBB0_2
17+
; RV32IFD-NEXT: beqz zero, .LBB0_2
1918
; RV32IFD-NEXT: # %bb.1: # %if.then
2019
; RV32IFD-NEXT: ret
2120
; RV32IFD-NEXT: .LBB0_2: # %if.else
@@ -25,8 +24,7 @@ define void @br_fcmp_false(double %a, double %b) nounwind {
2524
;
2625
; RV64IFD-LABEL: br_fcmp_false:
2726
; RV64IFD: # %bb.0:
28-
; RV64IFD-NEXT: li a0, 1
29-
; RV64IFD-NEXT: bnez a0, .LBB0_2
27+
; RV64IFD-NEXT: beqz zero, .LBB0_2
3028
; RV64IFD-NEXT: # %bb.1: # %if.then
3129
; RV64IFD-NEXT: ret
3230
; RV64IFD-NEXT: .LBB0_2: # %if.else
@@ -36,8 +34,7 @@ define void @br_fcmp_false(double %a, double %b) nounwind {
3634
;
3735
; RV32IZFINXZDINX-LABEL: br_fcmp_false:
3836
; RV32IZFINXZDINX: # %bb.0:
39-
; RV32IZFINXZDINX-NEXT: li a0, 1
40-
; RV32IZFINXZDINX-NEXT: bnez a0, .LBB0_2
37+
; RV32IZFINXZDINX-NEXT: beqz zero, .LBB0_2
4138
; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.then
4239
; RV32IZFINXZDINX-NEXT: ret
4340
; RV32IZFINXZDINX-NEXT: .LBB0_2: # %if.else
@@ -47,8 +44,7 @@ define void @br_fcmp_false(double %a, double %b) nounwind {
4744
;
4845
; RV64IZFINXZDINX-LABEL: br_fcmp_false:
4946
; RV64IZFINXZDINX: # %bb.0:
50-
; RV64IZFINXZDINX-NEXT: li a0, 1
51-
; RV64IZFINXZDINX-NEXT: bnez a0, .LBB0_2
47+
; RV64IZFINXZDINX-NEXT: beqz zero, .LBB0_2
5248
; RV64IZFINXZDINX-NEXT: # %bb.1: # %if.then
5349
; RV64IZFINXZDINX-NEXT: ret
5450
; RV64IZFINXZDINX-NEXT: .LBB0_2: # %if.else
@@ -897,8 +893,7 @@ if.then:
897893
define void @br_fcmp_true(double %a, double %b) nounwind {
898894
; RV32IFD-LABEL: br_fcmp_true:
899895
; RV32IFD: # %bb.0:
900-
; RV32IFD-NEXT: li a0, 1
901-
; RV32IFD-NEXT: bnez a0, .LBB16_2
896+
; RV32IFD-NEXT: beqz zero, .LBB16_2
902897
; RV32IFD-NEXT: # %bb.1: # %if.else
903898
; RV32IFD-NEXT: ret
904899
; RV32IFD-NEXT: .LBB16_2: # %if.then
@@ -908,8 +903,7 @@ define void @br_fcmp_true(double %a, double %b) nounwind {
908903
;
909904
; RV64IFD-LABEL: br_fcmp_true:
910905
; RV64IFD: # %bb.0:
911-
; RV64IFD-NEXT: li a0, 1
912-
; RV64IFD-NEXT: bnez a0, .LBB16_2
906+
; RV64IFD-NEXT: beqz zero, .LBB16_2
913907
; RV64IFD-NEXT: # %bb.1: # %if.else
914908
; RV64IFD-NEXT: ret
915909
; RV64IFD-NEXT: .LBB16_2: # %if.then
@@ -919,8 +913,7 @@ define void @br_fcmp_true(double %a, double %b) nounwind {
919913
;
920914
; RV32IZFINXZDINX-LABEL: br_fcmp_true:
921915
; RV32IZFINXZDINX: # %bb.0:
922-
; RV32IZFINXZDINX-NEXT: li a0, 1
923-
; RV32IZFINXZDINX-NEXT: bnez a0, .LBB16_2
916+
; RV32IZFINXZDINX-NEXT: beqz zero, .LBB16_2
924917
; RV32IZFINXZDINX-NEXT: # %bb.1: # %if.else
925918
; RV32IZFINXZDINX-NEXT: ret
926919
; RV32IZFINXZDINX-NEXT: .LBB16_2: # %if.then
@@ -930,8 +923,7 @@ define void @br_fcmp_true(double %a, double %b) nounwind {
930923
;
931924
; RV64IZFINXZDINX-LABEL: br_fcmp_true:
932925
; RV64IZFINXZDINX: # %bb.0:
933-
; RV64IZFINXZDINX-NEXT: li a0, 1
934-
; RV64IZFINXZDINX-NEXT: bnez a0, .LBB16_2
926+
; RV64IZFINXZDINX-NEXT: beqz zero, .LBB16_2
935927
; RV64IZFINXZDINX-NEXT: # %bb.1: # %if.else
936928
; RV64IZFINXZDINX-NEXT: ret
937929
; RV64IZFINXZDINX-NEXT: .LBB16_2: # %if.then

llvm/test/CodeGen/RISCV/float-br-fcmp.ll

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ declare float @dummy(float)
1515
define void @br_fcmp_false(float %a, float %b) nounwind {
1616
; RV32IF-LABEL: br_fcmp_false:
1717
; RV32IF: # %bb.0:
18-
; RV32IF-NEXT: li a0, 1
19-
; RV32IF-NEXT: bnez a0, .LBB0_2
18+
; RV32IF-NEXT: beqz zero, .LBB0_2
2019
; RV32IF-NEXT: # %bb.1: # %if.then
2120
; RV32IF-NEXT: ret
2221
; RV32IF-NEXT: .LBB0_2: # %if.else
@@ -26,8 +25,7 @@ define void @br_fcmp_false(float %a, float %b) nounwind {
2625
;
2726
; RV64IF-LABEL: br_fcmp_false:
2827
; RV64IF: # %bb.0:
29-
; RV64IF-NEXT: li a0, 1
30-
; RV64IF-NEXT: bnez a0, .LBB0_2
28+
; RV64IF-NEXT: beqz zero, .LBB0_2
3129
; RV64IF-NEXT: # %bb.1: # %if.then
3230
; RV64IF-NEXT: ret
3331
; RV64IF-NEXT: .LBB0_2: # %if.else
@@ -37,8 +35,7 @@ define void @br_fcmp_false(float %a, float %b) nounwind {
3735
;
3836
; RV32IZFINX-LABEL: br_fcmp_false:
3937
; RV32IZFINX: # %bb.0:
40-
; RV32IZFINX-NEXT: li a0, 1
41-
; RV32IZFINX-NEXT: bnez a0, .LBB0_2
38+
; RV32IZFINX-NEXT: beqz zero, .LBB0_2
4239
; RV32IZFINX-NEXT: # %bb.1: # %if.then
4340
; RV32IZFINX-NEXT: ret
4441
; RV32IZFINX-NEXT: .LBB0_2: # %if.else
@@ -48,8 +45,7 @@ define void @br_fcmp_false(float %a, float %b) nounwind {
4845
;
4946
; RV64IZFINX-LABEL: br_fcmp_false:
5047
; RV64IZFINX: # %bb.0:
51-
; RV64IZFINX-NEXT: li a0, 1
52-
; RV64IZFINX-NEXT: bnez a0, .LBB0_2
48+
; RV64IZFINX-NEXT: beqz zero, .LBB0_2
5349
; RV64IZFINX-NEXT: # %bb.1: # %if.then
5450
; RV64IZFINX-NEXT: ret
5551
; RV64IZFINX-NEXT: .LBB0_2: # %if.else
@@ -898,8 +894,7 @@ if.then:
898894
define void @br_fcmp_true(float %a, float %b) nounwind {
899895
; RV32IF-LABEL: br_fcmp_true:
900896
; RV32IF: # %bb.0:
901-
; RV32IF-NEXT: li a0, 1
902-
; RV32IF-NEXT: bnez a0, .LBB16_2
897+
; RV32IF-NEXT: beqz zero, .LBB16_2
903898
; RV32IF-NEXT: # %bb.1: # %if.else
904899
; RV32IF-NEXT: ret
905900
; RV32IF-NEXT: .LBB16_2: # %if.then
@@ -909,8 +904,7 @@ define void @br_fcmp_true(float %a, float %b) nounwind {
909904
;
910905
; RV64IF-LABEL: br_fcmp_true:
911906
; RV64IF: # %bb.0:
912-
; RV64IF-NEXT: li a0, 1
913-
; RV64IF-NEXT: bnez a0, .LBB16_2
907+
; RV64IF-NEXT: beqz zero, .LBB16_2
914908
; RV64IF-NEXT: # %bb.1: # %if.else
915909
; RV64IF-NEXT: ret
916910
; RV64IF-NEXT: .LBB16_2: # %if.then
@@ -920,8 +914,7 @@ define void @br_fcmp_true(float %a, float %b) nounwind {
920914
;
921915
; RV32IZFINX-LABEL: br_fcmp_true:
922916
; RV32IZFINX: # %bb.0:
923-
; RV32IZFINX-NEXT: li a0, 1
924-
; RV32IZFINX-NEXT: bnez a0, .LBB16_2
917+
; RV32IZFINX-NEXT: beqz zero, .LBB16_2
925918
; RV32IZFINX-NEXT: # %bb.1: # %if.else
926919
; RV32IZFINX-NEXT: ret
927920
; RV32IZFINX-NEXT: .LBB16_2: # %if.then
@@ -931,8 +924,7 @@ define void @br_fcmp_true(float %a, float %b) nounwind {
931924
;
932925
; RV64IZFINX-LABEL: br_fcmp_true:
933926
; RV64IZFINX: # %bb.0:
934-
; RV64IZFINX-NEXT: li a0, 1
935-
; RV64IZFINX-NEXT: bnez a0, .LBB16_2
927+
; RV64IZFINX-NEXT: beqz zero, .LBB16_2
936928
; RV64IZFINX-NEXT: # %bb.1: # %if.else
937929
; RV64IZFINX-NEXT: ret
938930
; RV64IZFINX-NEXT: .LBB16_2: # %if.then

0 commit comments

Comments
 (0)