Skip to content

Commit 0f6e12f

Browse files
fixup! combine with optimizeCondBr
1 parent c403110 commit 0f6e12f

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
@@ -568,14 +568,9 @@ class PeepholeOptimizerLegacy : public MachineFunctionPass {
568568
bool runOnMachineFunction(MachineFunction &MF) override;
569569

570570
void getAnalysisUsage(AnalysisUsage &AU) const override {
571-
AU.setPreservesCFG();
572571
MachineFunctionPass::getAnalysisUsage(AU);
573572
AU.addRequired<MachineLoopInfoWrapperPass>();
574-
AU.addPreserved<MachineLoopInfoWrapperPass>();
575-
if (Aggressive) {
576-
AU.addRequired<MachineDominatorTreeWrapperPass>();
577-
AU.addPreserved<MachineDominatorTreeWrapperPass>();
578-
}
573+
AU.addRequired<MachineDominatorTreeWrapperPass>();
579574
}
580575

581576
MachineFunctionProperties getRequiredProperties() const override {
@@ -1652,27 +1647,20 @@ PreservedAnalyses
16521647
PeepholeOptimizerPass::run(MachineFunction &MF,
16531648
MachineFunctionAnalysisManager &MFAM) {
16541649
MFPropsModifier _(*this, MF);
1655-
auto *DT =
1656-
Aggressive ? &MFAM.getResult<MachineDominatorTreeAnalysis>(MF) : nullptr;
1650+
auto *DT = &MFAM.getResult<MachineDominatorTreeAnalysis>(MF);
16571651
auto *MLI = &MFAM.getResult<MachineLoopAnalysis>(MF);
16581652
PeepholeOptimizer Impl(DT, MLI);
16591653
bool Changed = Impl.run(MF);
16601654
if (!Changed)
16611655
return PreservedAnalyses::all();
16621656

1663-
auto PA = getMachineFunctionPassPreservedAnalyses();
1664-
PA.preserve<MachineDominatorTreeAnalysis>();
1665-
PA.preserve<MachineLoopAnalysis>();
1666-
PA.preserveSet<CFGAnalyses>();
1667-
return PA;
1657+
return getMachineFunctionPassPreservedAnalyses();
16681658
}
16691659

16701660
bool PeepholeOptimizerLegacy::runOnMachineFunction(MachineFunction &MF) {
16711661
if (skipFunction(MF.getFunction()))
16721662
return false;
1673-
auto *DT = Aggressive
1674-
? &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree()
1675-
: nullptr;
1663+
auto *DT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
16761664
auto *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
16771665
PeepholeOptimizer Impl(DT, MLI);
16781666
return Impl.run(MF);
@@ -1793,6 +1781,20 @@ bool PeepholeOptimizer::run(MachineFunction &MF) {
17931781
}
17941782

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

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 107 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,109 +1005,6 @@ RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
10051005
}
10061006
}
10071007

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

@@ -1176,10 +1076,14 @@ bool RISCVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
11761076
I->getDesc().isUnconditionalBranch()) {
11771077
parseCondBranch(*std::prev(I), TBB, Cond);
11781078
FBB = getBranchDestBlock(*I);
1179-
// Try to fold the branch of the conditional branch into an unconditional
1180-
// branch.
1181-
if (AllowModify)
1182-
trySimplifyCondBr(MBB, TBB, FBB, Cond);
1079+
// Try and optimize the pair.
1080+
if (AllowModify) {
1081+
if (optimizeCondBranch(*std::prev(I)))
1082+
I->eraseFromParent();
1083+
1084+
// The branch might have changed, reanalyze it.
1085+
return analyzeBranch(MBB, TBB, FBB, Cond, false);
1086+
}
11831087
return false;
11841088
}
11851089

@@ -1335,7 +1239,8 @@ bool RISCVInstrInfo::reverseBranchCondition(
13351239

13361240
bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13371241
MachineBasicBlock *MBB = MI.getParent();
1338-
MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
1242+
if (!MBB)
1243+
return false;
13391244

13401245
MachineBasicBlock *TBB, *FBB;
13411246
SmallVector<MachineOperand, 3> Cond;
@@ -1345,8 +1250,98 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13451250
RISCVCC::CondCode CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
13461251
assert(CC != RISCVCC::COND_INVALID);
13471252

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

13511346
// For two constants C0 and C1 from
13521347
// ```
@@ -1365,24 +1360,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
13651360
//
13661361
// To make sure this optimization is really beneficial, we only
13671362
// optimize for cases where Y had only one use (i.e. only used by the branch).
1368-
1369-
// Right now we only care about LI (i.e. ADDI x0, imm)
1370-
auto isLoadImm = [](const MachineInstr *MI, int64_t &Imm) -> bool {
1371-
if (MI->getOpcode() == RISCV::ADDI && MI->getOperand(1).isReg() &&
1372-
MI->getOperand(1).getReg() == RISCV::X0) {
1373-
Imm = MI->getOperand(2).getImm();
1374-
return true;
1375-
}
1376-
return false;
1377-
};
1378-
// Either a load from immediate instruction or X0.
1379-
auto isFromLoadImm = [&](const MachineOperand &Op, int64_t &Imm) -> bool {
1380-
if (!Op.isReg())
1381-
return false;
1382-
Register Reg = Op.getReg();
1383-
return Reg.isVirtual() && isLoadImm(MRI.getVRegDef(Reg), Imm);
1384-
};
1385-
13861363
MachineOperand &LHS = MI.getOperand(0);
13871364
MachineOperand &RHS = MI.getOperand(1);
13881365
// Try to find the register for constant Z; return
@@ -1401,7 +1378,6 @@ bool RISCVInstrInfo::optimizeCondBranch(MachineInstr &MI) const {
14011378
};
14021379

14031380
bool Modify = false;
1404-
int64_t C0;
14051381
if (isFromLoadImm(LHS, C0) && MRI.hasOneUse(LHS.getReg())) {
14061382
// Might be case 1.
14071383
// 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)