Skip to content

Commit 728079b

Browse files
fixup! combine with optimizeCondBr
1 parent 8fab8b1 commit 728079b

File tree

10 files changed

+138
-439
lines changed

10 files changed

+138
-439
lines changed

llvm/lib/CodeGen/PeepholeOptimizer.cpp

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -566,14 +566,9 @@ class PeepholeOptimizerLegacy : public MachineFunctionPass {
566566
bool runOnMachineFunction(MachineFunction &MF) override;
567567

568568
void getAnalysisUsage(AnalysisUsage &AU) const override {
569-
AU.setPreservesCFG();
570569
MachineFunctionPass::getAnalysisUsage(AU);
571570
AU.addRequired<MachineLoopInfoWrapperPass>();
572-
AU.addPreserved<MachineLoopInfoWrapperPass>();
573-
if (Aggressive) {
574-
AU.addRequired<MachineDominatorTreeWrapperPass>();
575-
AU.addPreserved<MachineDominatorTreeWrapperPass>();
576-
}
571+
AU.addRequired<MachineDominatorTreeWrapperPass>();
577572
}
578573

579574
MachineFunctionProperties getRequiredProperties() const override {
@@ -1650,27 +1645,20 @@ PreservedAnalyses
16501645
PeepholeOptimizerPass::run(MachineFunction &MF,
16511646
MachineFunctionAnalysisManager &MFAM) {
16521647
MFPropsModifier _(*this, MF);
1653-
auto *DT =
1654-
Aggressive ? &MFAM.getResult<MachineDominatorTreeAnalysis>(MF) : nullptr;
1648+
auto *DT = &MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
16551649
auto *MLI = &MFAM.getResult<MachineLoopAnalysis>(MF);
16561650
PeepholeOptimizer Impl(DT, MLI);
16571651
bool Changed = Impl.run(MF);
16581652
if (!Changed)
16591653
return PreservedAnalyses::all();
16601654

1661-
auto PA = getMachineFunctionPassPreservedAnalyses();
1662-
PA.preserve<MachineDominatorTreeAnalysis>();
1663-
PA.preserve<MachineLoopAnalysis>();
1664-
PA.preserveSet<CFGAnalyses>();
1665-
return PA;
1655+
return getMachineFunctionPassPreservedAnalyses();
16661656
}
16671657

16681658
bool PeepholeOptimizerLegacy::runOnMachineFunction(MachineFunction &MF) {
16691659
if (skipFunction(MF.getFunction()))
16701660
return false;
1671-
auto *DT = Aggressive
1672-
? &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree()
1673-
: nullptr;
1661+
auto *DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
16741662
auto *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
16751663
PeepholeOptimizer Impl(DT, MLI);
16761664
return Impl.run(MF);
@@ -1791,6 +1779,20 @@ bool PeepholeOptimizer::run(MachineFunction &MF) {
17911779
}
17921780

17931781
if (MI->isConditionalBranch() && optimizeCondBranch(*MI)) {
1782+
// optimizeCondBranch might have converted a conditional branch to
1783+
// an unconditional branch. If there is a branch instruction after it,
1784+
// delete it.
1785+
MachineInstr *NewBr = &*std::prev(MII);
1786+
if (NewBr->isUnconditionalBranch()) {
1787+
if (MII != MBB.end()) {
1788+
MachineInstr *Dead = &*MII;
1789+
++MII;
1790+
MachineBasicBlock *DeadDest = TII->getBranchDestBlock(*Dead);
1791+
if (TII->getBranchDestBlock(*NewBr)!= DeadDest)
1792+
DT->deleteEdge(&MBB, DeadDest);
1793+
Dead->eraseFromParent();
1794+
}
1795+
}
17941796
Changed = true;
17951797
continue;
17961798
}

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 107 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,109 +1014,6 @@ RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
10141014
}
10151015
}
10161016

1017-
// Return true if MO definitely contains the value one.
1018-
static bool isOne(MachineOperand &MO) {
1019-
if (MO.isImm() && MO.getImm() == 1)
1020-
return true;
1021-
1022-
if (!MO.isReg() || !MO.getReg().isVirtual())
1023-
return false;
1024-
1025-
MachineRegisterInfo &MRI =
1026-
MO.getParent()->getParent()->getParent()->getRegInfo();
1027-
MachineInstr *DefMI = MRI.getUniqueVRegDef(MO.getReg());
1028-
if (!DefMI)
1029-
return false;
1030-
1031-
// For now, just check the canonical one value.
1032-
if (DefMI->getOpcode() == RISCV::ADDI &&
1033-
DefMI->getOperand(1).getReg() == RISCV::X0 &&
1034-
DefMI->getOperand(2).getImm() == 1)
1035-
return true;
1036-
1037-
return false;
1038-
}
1039-
1040-
// Return true if MO definitely contains the value zero.
1041-
static bool isZero(MachineOperand &MO) {
1042-
if (MO.isImm() && MO.getImm() == 0)
1043-
return true;
1044-
if (MO.isReg() && MO.getReg() == RISCV::X0)
1045-
return true;
1046-
return false;
1047-
}
1048-
1049-
bool RISCVInstrInfo::trySimplifyCondBr(
1050-
MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
1051-
SmallVectorImpl<MachineOperand> &Cond) const {
1052-
1053-
if (!TBB || Cond.size() != 3)
1054-
return false;
1055-
1056-
RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
1057-
auto LHS = Cond[1];
1058-
auto RHS = Cond[2];
1059-
1060-
MachineBasicBlock *Folded = nullptr;
1061-
switch (CC) {
1062-
default:
1063-
// TODO: Implement for more CCs
1064-
return false;
1065-
case RISCVCC::COND_EQ: {
1066-
// We can statically evaluate that we take the first branch
1067-
if ((isZero(LHS) && isZero(RHS)) || (isOne(LHS) && isOne(RHS))) {
1068-
Folded = TBB;
1069-
break;
1070-
}
1071-
// We can statically evaluate that we take the second branch
1072-
if ((isZero(LHS) && isOne(RHS)) || (isOne(LHS) && isZero(RHS))) {
1073-
Folded = FBB;
1074-
break;
1075-
}
1076-
return false;
1077-
}
1078-
case RISCVCC::COND_NE: {
1079-
// We can statically evaluate that we take the first branch
1080-
if ((isOne(LHS) && isZero(RHS)) || (isZero(LHS) && isOne(RHS))) {
1081-
Folded = TBB;
1082-
break;
1083-
}
1084-
// We can statically evaluate that we take the second branch
1085-
if ((isZero(LHS) && isZero(RHS)) || (isOne(LHS) && isOne(RHS))) {
1086-
Folded = FBB;
1087-
break;
1088-
}
1089-
return false;
1090-
}
1091-
}
1092-
1093-
// At this point, its legal to optimize.
1094-
removeBranch(MBB);
1095-
Cond.clear();
1096-
1097-
// Only need to insert a branch if we're not falling through.
1098-
if (Folded) {
1099-
DebugLoc DL = MBB.findBranchDebugLoc();
1100-
insertBranch(MBB, Folded, nullptr, {}, DL);
1101-
}
1102-
1103-
// Update the successors. Remove them all and add back the correct one.
1104-
while (!MBB.succ_empty())
1105-
MBB.removeSuccessor(MBB.succ_end() - 1);
1106-
1107-
// If it's a fallthrough, we need to figure out where MBB is going.
1108-
if (!Folded) {
1109-
MachineFunction::iterator Fallthrough = ++MBB.getIterator();
1110-
if (Fallthrough != MBB.getParent()->end())
1111-
MBB.addSuccessor(&*Fallthrough);
1112-
} else
1113-
MBB.addSuccessor(Folded);
1114-
1115-
TBB = Folded;
1116-
FBB = nullptr;
1117-
return true;
1118-
}
1119-
11201017
bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
11211018
MachineBasicBlock *&TBB,
11221019
MachineBasicBlock *&FBB,
@@ -1174,9 +1071,12 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
11741071
// Handle a single conditional branch.
11751072
if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
11761073
parseCondBranch(*I, TBB, Cond);
1177-
// Try to fold the branch of the conditional branch into a the fallthru.
1178-
if (AllowModify)
1179-
trySimplifyCondBr(MBB, TBB, FBB, Cond);
1074+
// Try and optimize the conditional branch.
1075+
if (AllowModify) {
1076+
optimizeCondBranch(*I);
1077+
// The branch might have changed, reanalyze it.
1078+
return analyzeBranch(MBB, TBB, FBB, Cond, false);
1079+
}
11801080
return false;
11811081
}
11821082

@@ -1185,10 +1085,14 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
11851085
I->getDesc().isUnconditionalBranch()) {
11861086
parseCondBranch(*std::prev(I), TBB, Cond);
11871087
FBB = getBranchDestBlock(*I);
1188-
// Try to fold the branch of the conditional branch into an unconditional
1189-
// branch.
1190-
if (AllowModify)
1191-
trySimplifyCondBr(MBB, TBB, FBB, Cond);
1088+
// Try and optimize the pair.
1089+
if (AllowModify) {
1090+
if (optimizeCondBranch(*std::prev(I)))
1091+
I->eraseFromParent();
1092+
1093+
// The branch might have changed, reanalyze it.
1094+
return analyzeBranch(MBB, TBB, FBB, Cond, false);
1095+
}
11921096
return false;
11931097
}
11941098

@@ -1344,7 +1248,8 @@ bool RISCVInstrInfo::reverseBranchCondition(
13441248

13451249
bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13461250
MachineBasicBlock *MBB = MI.getParent();
1347-
MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
1251+
if (!MBB)
1252+
return false;
13481253

13491254
MachineBasicBlock *TBB, *FBB;
13501255
SmallVector<MachineOperand, 3> Cond;
@@ -1354,8 +1259,98 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13541259
RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
13551260
assert(CC != RISCVCC::COND_INVALID);
13561261

1357-
if (CC == RISCVCC::COND_EQ || CC == RISCVCC::COND_NE)
1262+
// Right now we only care about LI (i.e. ADDI x0, imm)
1263+
auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
1264+
if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
1265+
MI->getOperand(1).getReg() == RISCV::X0) {
1266+
Imm = MI->getOperand(2).getImm();
1267+
return true;
1268+
}
13581269
return false;
1270+
};
1271+
1272+
MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
1273+
// Either a load from immediate instruction or X0.
1274+
auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
1275+
if (!Op.isReg())
1276+
return false;
1277+
Register Reg = Op.getReg();
1278+
if (Reg == RISCV::X0) {
1279+
Imm = 0;
1280+
return true;
1281+
}
1282+
return Reg.isVirtual() && isLoadImm(MRI.getVRegDef(Reg), Imm);
1283+
};
1284+
1285+
// Try and convert a conditional branch that can be evaluated statically
1286+
// into an unconditional branch.
1287+
MachineBasicBlock *Folded = nullptr;
1288+
int64_t C0, C1;
1289+
if (isFromLoadImm(Cond[1], C0) && isFromLoadImm(Cond[2], C1)) {
1290+
switch (CC) {
1291+
default:
1292+
// TODO: Implement for more CCs
1293+
break;
1294+
case RISCVCC::COND_EQ: {
1295+
Folded = (C0 == C1) ? TBB : FBB;
1296+
break;
1297+
}
1298+
case RISCVCC::COND_NE: {
1299+
Folded = (C0 != C1) ? TBB : FBB;
1300+
break;
1301+
}
1302+
case RISCVCC::COND_LT: {
1303+
Folded = (C0 < C1) ? TBB : FBB;
1304+
break;
1305+
}
1306+
case RISCVCC::COND_GE: {
1307+
Folded = (C0 >= C1) ? TBB : FBB;
1308+
break;
1309+
}
1310+
case RISCVCC::COND_LTU: {
1311+
Folded = ((uint64_t)C0 < (uint64_t)C1) ? TBB : FBB;
1312+
break;
1313+
}
1314+
case RISCVCC::COND_GEU: {
1315+
Folded = ((uint64_t)C0 >= (uint64_t)C1) ? TBB : FBB;
1316+
break;
1317+
}
1318+
}
1319+
1320+
// Do the conversion
1321+
// Build the new unconditional branch
1322+
DebugLoc DL = MBB->findBranchDebugLoc();
1323+
if (Folded) {
1324+
BuildMI(*MBB, MI, DL, get(RISCV::PseudoBR)).addMBB(Folded);
1325+
} else {
1326+
MachineFunction::iterator Fallthrough = ++MBB->getIterator();
1327+
if (Fallthrough == MBB->getParent()->end())
1328+
return false;
1329+
BuildMI(*MBB, MI, DL, get(RISCV::PseudoBR)).addMBB(&*Fallthrough);
1330+
}
1331+
1332+
// Update successors of MBB.
1333+
if (Folded == TBB) {
1334+
// If we're taking TBB, then the succ to delete is the fallthrough (if
1335+
// it was a succ in the first place), or its the MBB from the
1336+
// unconditional branch.
1337+
if (!FBB) {
1338+
MachineFunction::iterator Fallthrough = ++MBB->getIterator();
1339+
if (Fallthrough != MBB->getParent()->end() &&
1340+
MBB->isSuccessor(&*Fallthrough))
1341+
MBB->removeSuccessor(&*Fallthrough, true);
1342+
} else {
1343+
MBB->removeSuccessor(FBB, true);
1344+
}
1345+
} else if (Folded == FBB) {
1346+
// If we're taking the fallthrough or unconditional branch, then the
1347+
// succ to remove is the one from the conditional branch.
1348+
MBB->removeSuccessor(TBB, true);
1349+
}
1350+
1351+
MI.eraseFromParent();
1352+
return true;
1353+
}
13591354

13601355
// For two constants C0 and C1 from
13611356
// ```
@@ -1374,24 +1369,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13741369
//
13751370
// To make sure this optimization is really beneficial, we only
13761371
// optimize for cases where Y had only one use (i.e. only used by the branch).
1377-
1378-
// Right now we only care about LI (i.e. ADDI x0, imm)
1379-
auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
1380-
if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
1381-
MI->getOperand(1).getReg() == RISCV::X0) {
1382-
Imm = MI->getOperand(2).getImm();
1383-
return true;
1384-
}
1385-
return false;
1386-
};
1387-
// Either a load from immediate instruction or X0.
1388-
auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
1389-
if (!Op.isReg())
1390-
return false;
1391-
Register Reg = Op.getReg();
1392-
return Reg.isVirtual() && isLoadImm(MRI.getVRegDef(Reg), Imm);
1393-
};
1394-
13951372
MachineOperand &LHS = MI.getOperand(0);
13961373
MachineOperand &RHS = MI.getOperand(1);
13971374
// Try to find the register for constant Z; return
@@ -1410,7 +1387,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
14101387
};
14111388

14121389
bool Modify = false;
1413-
int64_t C0;
14141390
if (isFromLoadImm(LHS, C0) && MRI.hasOneUse(LHS.getReg())) {
14151391
// Might be case 1.
14161392
// Signed integer overflow is UB. (UINT64_MAX is bigger so we don't need

llvm/lib/Target/RISCV/RISCVInstrInfo.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -319,26 +319,6 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
319319
const MachineInstr &MI2) const;
320320
bool hasReassociableVectorSibling(const MachineInstr &Inst,
321321
bool &Commuted) const;
322-
/// Return true if the branch represented by the conditional branch with
323-
/// components TBB, FBB, and CurCond was folded into an unconditional branch.
324-
///
325-
/// If FBB is nullptr, then the the input represents a conditional branch with
326-
/// a fallthrough.
327-
///
328-
/// For example:
329-
/// BRCOND EQ 0, 0, BB1
330-
/// BR BB2
331-
///
332-
/// can be simplified to BR BB1 since 0 == 0 statically. On the other hand,
333-
///
334-
///
335-
/// BRCOND EQ 0, 1, BB1
336-
/// BR BB2
337-
///
338-
/// can be simplified to BR BB2 because 0 != 1 statically.
339-
bool trySimplifyCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
340-
MachineBasicBlock *FBB,
341-
SmallVectorImpl<MachineOperand> &Cond) const;
342322
};
343323

344324
namespace RISCV {

llvm/test/CodeGen/AArch64/O3-pipeline.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@
158158
; CHECK-NEXT: MachinePostDominator Tree Construction
159159
; CHECK-NEXT: Machine Cycle Info Analysis
160160
; CHECK-NEXT: Machine code sinking
161+
; CHECK-NEXT: MachineDominator Tree Construction
161162
; CHECK-NEXT: Peephole Optimizations
162163
; CHECK-NEXT: Remove dead machine instructions
163164
; CHECK-NEXT: AArch64 MI Peephole Optimization pass

llvm/test/CodeGen/RISCV/O3-pipeline.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
; CHECK-NEXT: MachinePostDominator Tree Construction
116116
; CHECK-NEXT: Machine Cycle Info Analysis
117117
; CHECK-NEXT: Machine code sinking
118+
; CHECK-NEXT: MachineDominator Tree Construction
118119
; CHECK-NEXT: Peephole Optimizations
119120
; CHECK-NEXT: Remove dead machine instructions
120121
; CHECK-NEXT: Machine Trace Metrics

0 commit comments

Comments
 (0)