51#define DEBUG_TYPE "early-ifcvt"
57 cl::desc(
"Maximum number of instructions per speculated block."));
66 cl::desc(
"Enable hard-to-predict branch analysis for if-conversion"));
72 cl::desc(
"Limit the number of steps taken when searching for a "
73 "recently loaded value"));
79 cl::desc(
"Limit the number of blocks and instructions examined when "
80 "searching for calls between a load and the condition it feeds"));
84 cl::desc(
"Cold edge probability threshold in percent for using no "
85 "critical-path extension budget (0 disables the threshold)"));
88STATISTIC(NumDiamondsConv,
"Number of diamonds converted");
90STATISTIC(NumTrianglesConv,
"Number of triangles converted");
92 "Number of data dependent conditional branches encountered");
93STATISTIC(NumLikelyBiased,
"Number of branches with a hot path encountered");
95 "Number of branches with reduced critical-path budget");
139 bool isTriangle()
const {
return TBB == Tail || FBB == Tail; }
142 MachineBasicBlock *getTPred()
const {
return TBB == Tail ? Head : TBB; }
145 MachineBasicBlock *getFPred()
const {
return FBB == Tail ? Head : FBB; }
152 TargetInstrInfo::SelectExpansion Select;
154 PHIInfo(MachineInstr *phi) : PHI(
phi) {}
160 SmallVector<MachineOperand, 4> Cond;
165 SmallPtrSet<MachineInstr*, 8> InsertAfter;
168 BitVector ClobberedRegUnits;
171 SparseSet<MCRegUnit, MCRegUnit, MCRegUnitToIndex> LiveRegUnits;
179 bool canSpeculateInstrs(MachineBasicBlock *
MBB);
183 bool canPredicateInstrs(MachineBasicBlock *
MBB);
187 bool InstrDependenciesAllowIfConv(MachineInstr *
I);
191 void PredicateBlock(MachineBasicBlock *
MBB,
bool ReversePredicate);
194 bool findInsertionPoint();
197 void replacePHIInstrs();
200 void rewritePHIOperands();
204 void clearRepeatedKillFlagsFromTBB(MachineBasicBlock *TBB,
205 MachineBasicBlock *FBB);
213 LiveRegUnits.clear();
214 LiveRegUnits.setUniverse(TRI->getNumRegUnits());
215 ClobberedRegUnits.clear();
216 ClobberedRegUnits.resize(TRI->getNumRegUnits());
223 bool canConvertIf(MachineBasicBlock *
MBB,
bool Predicate =
false);
227 void convertIf(SmallVectorImpl<MachineBasicBlock *> &RemoveBlocks,
228 bool Predicate =
false);
252 for (MachineInstr &
MI :
254 if (
MI.isDebugInstr())
278 bool DontMoveAcrossStore =
true;
279 if (!
MI.isSafeToMove(DontMoveAcrossStore)) {
285 if (!InstrDependenciesAllowIfConv(&
MI))
295bool SSAIfConv::InstrDependenciesAllowIfConv(MachineInstr *
I) {
296 for (
const MachineOperand &MO :
I->operands()) {
297 if (MO.isRegMask()) {
308 ClobberedRegUnits.
set(
static_cast<unsigned>(Unit));
319 LLVM_DEBUG(
dbgs() <<
"Can't insert instructions below terminator.\n");
334bool SSAIfConv::canPredicateInstrs(MachineBasicBlock *
MBB) {
349 if (
I->isDebugInstr())
377 if (!InstrDependenciesAllowIfConv(&(*
I)))
384void SSAIfConv::PredicateBlock(MachineBasicBlock *
MBB,
bool ReversePredicate) {
385 auto Condition =
Cond;
386 if (ReversePredicate) {
388 assert(CanRevCond &&
"Reversed predicate is not supported");
395 if (
I->isDebugInstr())
411bool SSAIfConv::findInsertionPoint() {
414 LiveRegUnits.
clear();
422 if (InsertAfter.
count(&*
I)) {
428 for (
const MachineOperand &MO :
I->operands()) {
438 LiveRegUnits.
erase(Unit);
444 while (!Reads.
empty())
446 if (ClobberedRegUnits.
test(
static_cast<unsigned>(Unit)))
447 LiveRegUnits.
insert(Unit);
450 if (
I != FirstTerm &&
I->isTerminator())
455 if (!LiveRegUnits.
empty()) {
457 dbgs() <<
"Would clobber";
458 for (MCRegUnit LRU : LiveRegUnits)
460 dbgs() <<
" live before " << *
I;
479bool SSAIfConv::canConvertIf(MachineBasicBlock *
MBB,
bool Predicate) {
485 MachineBasicBlock *Succ0 = Head->
succ_begin()[0];
486 MachineBasicBlock *Succ1 = Head->
succ_begin()[1];
509 if (!
Tail->livein_empty()) {
522 if (!Predicate && (
Tail->empty() || !
Tail->front().isPHI())) {
536 LLVM_DEBUG(
dbgs() <<
"analyzeBranch didn't find conditional branch.\n");
543 LLVM_DEBUG(
dbgs() <<
"analyzeBranch found an unconditional branch.\n");
549 FBB =
TBB == Succ0 ? Succ1 : Succ0;
553 MachineBasicBlock *TPred = getTPred();
554 MachineBasicBlock *FPred = getFPred();
556 I !=
E &&
I->isPHI(); ++
I) {
558 PHIInfo &PI = PHIs.
back();
560 for (
unsigned i = 1; i != PI.PHI->getNumOperands(); i += 2) {
561 if (PI.PHI->getOperand(i+1).getMBB() == TPred)
562 PI.TReg = PI.PHI->getOperand(i).getReg();
563 if (PI.PHI->getOperand(i+1).getMBB() == FPred)
564 PI.FReg = PI.PHI->getOperand(i).getReg();
566 assert(PI.TReg.isVirtual() &&
"Bad PHI");
567 assert(PI.FReg.isVirtual() &&
"Bad PHI");
570 if (!
TII->canInsertSelect(*Head,
Cond, PI.PHI->getOperand(0).getReg(),
571 PI.TReg, PI.FReg, PI.Select)) {
579 ClobberedRegUnits.
reset();
581 if (
TBB != Tail && !canPredicateInstrs(
TBB))
583 if (FBB != Tail && !canPredicateInstrs(FBB))
586 if (
TBB != Tail && !canSpeculateInstrs(
TBB))
588 if (FBB != Tail && !canSpeculateInstrs(FBB))
594 if (!findInsertionPoint())
611 if (!TReg.isVirtual() || !FReg.
isVirtual())
633 return MO.isReg() && MO.getReg().isPhysical();
638 if (!
TII->produceSameValue(*TDef, *FDef, &MRI))
644 if (TIdx == -1 || FIdx == -1)
653void SSAIfConv::replacePHIInstrs() {
654 assert(
Tail->pred_size() == 2 &&
"Cannot replace PHIs");
656 assert(FirstTerm != Head->
end() &&
"No terminators");
657 DebugLoc HeadDL = FirstTerm->getDebugLoc();
660 for (PHIInfo &PI : PHIs) {
662 Register DstReg = PI.PHI->getOperand(0).getReg();
666 BuildMI(*Head, FirstTerm, HeadDL,
TII->get(TargetOpcode::COPY), DstReg)
669 TII->insertSelect(*Head, FirstTerm, HeadDL, DstReg,
Cond, PI.TReg,
673 PI.PHI->eraseFromParent();
681void SSAIfConv::rewritePHIOperands() {
683 assert(FirstTerm != Head->
end() &&
"No terminators");
684 DebugLoc HeadDL = FirstTerm->getDebugLoc();
687 for (PHIInfo &PI : PHIs) {
696 Register PHIDst = PI.PHI->getOperand(0).getReg();
698 TII->insertSelect(*Head, FirstTerm, HeadDL,
699 DstReg,
Cond, PI.TReg, PI.FReg);
704 for (
unsigned i = PI.PHI->getNumOperands(); i != 1; i -= 2) {
705 MachineBasicBlock *
MBB = PI.PHI->getOperand(i-1).getMBB();
706 if (
MBB == getTPred()) {
707 PI.PHI->getOperand(i-1).setMBB(Head);
708 PI.PHI->getOperand(i-2).setReg(DstReg);
709 }
else if (
MBB == getFPred()) {
710 PI.PHI->removeOperand(i-1);
711 PI.PHI->removeOperand(i-2);
718void SSAIfConv::clearRepeatedKillFlagsFromTBB(MachineBasicBlock *
TBB,
719 MachineBasicBlock *FBB) {
723 SmallDenseSet<Register> FBBKilledRegs;
724 for (MachineInstr &
MI : FBB->
instrs()) {
725 for (MachineOperand &MO :
MI.operands()) {
726 if (MO.isReg() && MO.isKill() && MO.getReg().isVirtual())
727 FBBKilledRegs.
insert(MO.getReg());
731 if (FBBKilledRegs.
empty())
735 for (MachineInstr &
MI :
TBB->instrs()) {
736 for (MachineOperand &MO :
MI.operands()) {
737 if (MO.isReg() && MO.isKill() && FBBKilledRegs.
contains(MO.getReg()))
748void SSAIfConv::convertIf(SmallVectorImpl<MachineBasicBlock *> &RemoveBlocks,
750 assert(Head && Tail &&
TBB && FBB &&
"Call canConvertIf first.");
762 if (
TBB != Tail && FBB != Tail)
763 clearRepeatedKillFlagsFromTBB(
TBB, FBB);
768 PredicateBlock(
TBB,
false);
773 PredicateBlock(FBB,
true);
777 bool ExtraPreds =
Tail->pred_size() != 2;
779 rewritePHIOperands();
787 TBB->removeSuccessor(Tail,
true);
819 if (Tail != &
Tail->getParent()->back())
820 Tail->moveAfter(&
Tail->getParent()->back());
836class EarlyIfConverter {
837 const TargetInstrInfo *
TII =
nullptr;
838 const TargetRegisterInfo *
TRI =
nullptr;
839 const TargetSubtargetInfo *STI =
nullptr;
840 MachineRegisterInfo *MRI =
nullptr;
841 MachineDominatorTree *DomTree =
nullptr;
842 MachineLoopInfo *
Loops =
nullptr;
843 MachineTraceMetrics *Traces =
nullptr;
845 MachineBranchProbabilityInfo &MBPI;
850 DenseMap<const MachineBasicBlock *, unsigned> NoCallBlocksCache;
853 EarlyIfConverter(MachineDominatorTree &DT, MachineLoopInfo &LI,
854 MachineTraceMetrics &MTM, MachineBranchProbabilityInfo &MBPI)
855 : DomTree(&DT),
Loops(&LI), Traces(&MTM), MBPI(MBPI) {}
856 EarlyIfConverter() =
delete;
861 bool tryConvertIf(MachineBasicBlock *);
862 void invalidateTraces();
863 bool shouldConvertIf();
864 bool isConditionDataDependent();
865 bool doOperandsComeFromMemory(
const MachineInstr *ConditionDef);
866 bool hasCallOrLoopInRange(
const MachineInstr *From,
const MachineInstr *To);
869class EarlyIfConverterLegacy :
public MachineFunctionPass {
872 EarlyIfConverterLegacy() : MachineFunctionPass(
ID) {}
873 void getAnalysisUsage(AnalysisUsage &AU)
const override;
875 StringRef getPassName()
const override {
return "Early If-Conversion"; }
879char EarlyIfConverterLegacy::ID = 0;
890void EarlyIfConverterLegacy::getAnalysisUsage(
AnalysisUsage &AU)
const {
904void updateDomTree(MachineDominatorTree *DomTree,
const SSAIfConv &IfConv,
910 for (
auto *
B : Removed) {
912 assert(Node != HeadNode &&
"Cannot erase the head node");
913 while (!
Node->isLeaf()) {
914 assert(
Node->getBlock() == IfConv.Tail &&
"Unexpected children");
922void updateLoops(MachineLoopInfo *
Loops,
926 for (
auto *
B : Removed)
932void EarlyIfConverter::invalidateTraces() {
943 const PseudoSourceValue *PSV = MOp->getPseudoValue();
944 return PSV && PSV->isConstantPool();
954bool EarlyIfConverter::hasCallOrLoopInRange(
const MachineInstr *From,
955 const MachineInstr *To) {
959 LLVM_DEBUG(
dbgs() <<
" checking for a call or loop between " << *From
961 assert(DomTree->
dominates(From, To) &&
"From is expected to dominate To");
963 const MachineBasicBlock *FromBB = From->
getParent();
964 const MachineBasicBlock *ToBB = To->
getParent();
966 unsigned NumScanned = 0;
967 auto HitSearchLimit = [&](
unsigned N) {
975 auto FoundCall = [](
const MachineInstr &
MI) {
979 auto IsCallOrHitSearchLimit = [&](
const MachineInstr &
MI) {
980 if (HitSearchLimit(1))
984 return FoundCall(
MI);
988 if (FromBB == ToBB) {
992 if (IsCallOrHitSearchLimit(
MI))
1001 if (IsCallOrHitSearchLimit(
MI))
1003 for (
const MachineInstr &
MI :
1006 if (IsCallOrHitSearchLimit(
MI))
1011 SmallPtrSet<const MachineBasicBlock *, 16> Enqueued = {FromBB, ToBB};
1013 auto Enqueue = [&](
const MachineBasicBlock *BB) {
1018 for (
const MachineBasicBlock *Pred : ToBB->
predecessors())
1021 while (!Worklist.
empty()) {
1027 if (
const MachineLoop *BBLoop =
Loops->getLoopFor(BB)) {
1028 if (!BBLoop->contains(ToBB) && !BBLoop->contains(FromBB)) {
1036 auto CacheIt = NoCallBlocksCache.find(BB);
1037 if (CacheIt != NoCallBlocksCache.end()) {
1038 if (HitSearchLimit(CacheIt->second))
1041 unsigned NumBlockInstrs = 0;
1042 for (
const MachineInstr &
MI :
1046 if (IsCallOrHitSearchLimit(
MI))
1049 NoCallBlocksCache[BB] = NumBlockInstrs;
1052 for (
const MachineBasicBlock *Pred : BB->
predecessors())
1065bool EarlyIfConverter::doOperandsComeFromMemory(
1066 const MachineInstr *ConditionDef) {
1071 LLVM_DEBUG(
dbgs() <<
" doOperandsComeFromMemory starting from reg "
1077 MachineLoop *IfConvLoop =
Loops->getLoopFor(IfConv.Head);
1080 SmallPtrSet<const MachineInstr *, 8> VisitedInstrs;
1081 SmallVector<const MachineInstr *> Worklist;
1093 if (!VisitedInstrs.
insert(
MI).second)
1102 const MachineBasicBlock *Parent =
MI->getParent();
1103 MachineLoop *ParentLoop =
Loops->getLoopFor(Parent);
1106 if (IfConvLoop && ParentLoop != IfConvLoop)
1113 !
MI->isDereferenceableInvariantLoad()) {
1118 if (!DomTree->
dominates(
MI, Br) || hasCallOrLoopInRange(
MI, Br))
1125 for (
const MachineOperand &MO :
MI->operands()) {
1126 if (!MO.isReg() || !MO.isUse())
1133 if (!VisitedInstrs.
count(UseDef)) {
1144bool EarlyIfConverter::isConditionDataDependent() {
1145 TargetInstrInfo::MachineBranchPredicate MBP;
1146 if (
TII->analyzeBranchPredicate(*IfConv.Head, MBP,
false))
1157 if (TBBProb != FBBProb) {
1175 if (Delta < 0 && Cyc + Delta > Cyc)
1187 return R <<
ore::NV(
C.Key,
C.Value) << (
C.Value == 1 ?
" cycle" :
" cycles");
1194bool EarlyIfConverter::shouldConvertIf() {
1201 MachineLoop *CurrentLoop =
Loops->getLoopFor(IfConv.Head);
1207 if (CurrentLoop &&
any_of(IfConv.Cond, [&](MachineOperand &MO) {
1208 if (!MO.isReg() || !MO.isUse())
1210 Register Reg = MO.getReg();
1211 if (Reg.isPhysical())
1214 MachineInstr *Def = MRI->getVRegDef(Reg);
1215 return CurrentLoop->isLoopInvariant(*Def) ||
1216 all_of(Def->operands(), [&](MachineOperand &Op) {
1219 if (!Op.isReg() || !Op.isUse())
1221 Register Reg = Op.getReg();
1222 if (Reg.isPhysical())
1225 MachineInstr *Def = MRI->getVRegDef(Reg);
1226 return CurrentLoop->isLoopInvariant(*Def);
1232 MinInstr = Traces->getEnsemble(MachineTraceStrategy::TS_MinInstrCount);
1236 LLVM_DEBUG(
dbgs() <<
"TBB: " << TBBTrace <<
"FBB: " << FBBTrace);
1245 bool DataDependent =
false;
1247 DataDependent = isConditionDataDependent();
1249 const unsigned MispredictPenalty = STI->getMispredictionPenalty();
1250 unsigned CritLimit =
1251 DataDependent ? MispredictPenalty : MispredictPenalty / 2;
1252 const BranchProbability ColdProb =
1253 std::min(MBPI.getEdgeProbability(IfConv.Head, IfConv.TBB),
1254 MBPI.getEdgeProbability(IfConv.Head, IfConv.FBB));
1256 const bool StronglyBiased =
1257 ColdProb < BranchProbability(ColdEdgePercent, 100);
1258 if (StronglyBiased) {
1260 ++NumStronglyBiased;
1263 MachineBasicBlock &
MBB = *IfConv.Head;
1267 <<
", critical-path budget: " << CritLimit <<
" cycles\n");
1268 if (StronglyBiased) {
1270 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
1271 "StronglyBiasedBranch",
1273 <<
"branch has a cold edge below "
1274 <<
ore::NV(
"ColdEdgeThreshold", ColdEdgePercent)
1275 <<
"%, using a critical-path "
1276 "extension budget of "
1277 <<
ore::NV(
"CritLimit", CritLimit) <<
" cycles";
1282 if (DataDependent) {
1284 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
1285 "DataDependentCondition",
1287 <<
"branch condition is data-dependent (from memory load), "
1288 <<
"using higher CritLimit of " <<
ore::NV(
"CritLimit", CritLimit)
1297 if (IfConv.TBB != IfConv.Tail)
1301 <<
", minimal critical path " << MinCrit <<
'\n');
1302 if (ResLength > MinCrit + CritLimit) {
1305 MachineOptimizationRemarkMissed
R(
DEBUG_TYPE,
"IfConversion",
1307 R <<
"did not if-convert branch: the resulting critical path ("
1308 << Cycles{
"ResLength", ResLength}
1309 <<
") would extend the shorter leg's critical path ("
1310 << Cycles{
"MinCrit", MinCrit} <<
") by more than the threshold of "
1311 << Cycles{
"CritLimit", CritLimit}
1312 <<
", which cannot be hidden by available ILP.";
1322 unsigned BranchDepth =
1329 struct CriticalPathInfo {
1333 CriticalPathInfo
Cond{};
1334 CriticalPathInfo TBlock{};
1335 CriticalPathInfo FBlock{};
1336 bool ShouldConvert =
true;
1337 for (SSAIfConv::PHIInfo &PI : IfConv.PHIs) {
1344 if (CondDepth > MaxDepth) {
1345 unsigned Extra = CondDepth - MaxDepth;
1346 LLVM_DEBUG(
dbgs() <<
"Condition adds " << Extra <<
" cycles.\n");
1347 if (Extra >
Cond.Extra)
1348 Cond = {Extra, CondDepth};
1349 if (Extra > CritLimit) {
1351 ShouldConvert =
false;
1358 if (TDepth > MaxDepth) {
1359 unsigned Extra = TDepth - MaxDepth;
1361 if (Extra > TBlock.Extra)
1362 TBlock = {Extra, TDepth};
1363 if (Extra > CritLimit) {
1365 ShouldConvert =
false;
1372 if (FDepth > MaxDepth) {
1373 unsigned Extra = FDepth - MaxDepth;
1375 if (Extra > FBlock.Extra)
1376 FBlock = {Extra, FDepth};
1377 if (Extra > CritLimit) {
1379 ShouldConvert =
false;
1387 const CriticalPathInfo
Short = TBlock.Extra > FBlock.Extra ? FBlock : TBlock;
1388 const CriticalPathInfo
Long = TBlock.Extra > FBlock.Extra ? TBlock : FBlock;
1390 if (ShouldConvert) {
1392 MachineOptimizationRemark
R(
DEBUG_TYPE,
"IfConversion",
1394 R <<
"performing if-conversion on branch: the condition adds "
1395 << Cycles{
"CondCycles",
Cond.Extra} <<
" to the critical path";
1396 if (
Short.Extra > 0)
1397 R <<
", and the short leg adds another "
1398 << Cycles{
"ShortCycles",
Short.Extra};
1400 R <<
", and the long leg adds another "
1401 << Cycles{
"LongCycles",
Long.Extra};
1402 R <<
", each staying under the threshold of "
1403 << Cycles{
"CritLimit", CritLimit} <<
".";
1408 MachineOptimizationRemarkMissed
R(
DEBUG_TYPE,
"IfConversion",
1410 R <<
"did not if-convert branch: the condition would add "
1411 << Cycles{
"CondCycles",
Cond.Extra} <<
" to the critical path";
1412 if (
Cond.Extra > CritLimit)
1413 R <<
" exceeding the limit of " << Cycles{
"CritLimit", CritLimit};
1414 if (
Short.Extra > 0) {
1415 R <<
", and the short leg would add another "
1416 << Cycles{
"ShortCycles",
Short.Extra};
1417 if (
Short.Extra > CritLimit)
1418 R <<
" exceeding the limit of " << Cycles{
"CritLimit", CritLimit};
1420 if (
Long.Extra > 0) {
1421 R <<
", and the long leg would add another "
1422 << Cycles{
"LongCycles",
Long.Extra};
1423 if (
Long.Extra > CritLimit)
1424 R <<
" exceeding the limit of " << Cycles{
"CritLimit", CritLimit};
1431 return ShouldConvert;
1436bool EarlyIfConverter::tryConvertIf(MachineBasicBlock *
MBB) {
1438 while (IfConv.canConvertIf(
MBB) && shouldConvertIf()) {
1441 SmallVector<MachineBasicBlock *, 4> RemoveBlocks;
1442 IfConv.convertIf(RemoveBlocks);
1444 updateDomTree(DomTree, IfConv, RemoveBlocks);
1445 updateLoops(
Loops, RemoveBlocks);
1448 NoCallBlocksCache.erase(IfConv.Head);
1449 for (MachineBasicBlock *
MBB : RemoveBlocks) {
1450 NoCallBlocksCache.erase(
MBB);
1458 LLVM_DEBUG(
dbgs() <<
"********** EARLY IF-CONVERSION **********\n"
1459 <<
"********** Function: " << MF.
getName() <<
'\n');
1479 if (tryConvertIf(DomNode->getBlock()))
1494 EarlyIfConverter Impl(MDT, LI, MTM, MBPI);
1506bool EarlyIfConverterLegacy::runOnMachineFunction(
MachineFunction &MF) {
1511 getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1512 MachineLoopInfo &LI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
1514 getAnalysis<MachineTraceMetricsWrapperPass>().getMTM();
1516 getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
1518 return EarlyIfConverter(MDT, LI, MTM, MBPI).run(MF);
1539 void getAnalysisUsage(AnalysisUsage &AU)
const override;
1541 StringRef getPassName()
const override {
return "Early If-predicator"; }
1544 bool tryConvertIf(MachineBasicBlock *);
1545 bool shouldConvertIf();
1550#define DEBUG_TYPE "early-if-predicator"
1552char EarlyIfPredicator::ID = 0;
1562void EarlyIfPredicator::getAnalysisUsage(
AnalysisUsage &AU)
const {
1572bool EarlyIfPredicator::shouldConvertIf() {
1574 if (IfConv.isTriangle()) {
1575 MachineBasicBlock &IfBlock =
1576 (IfConv.TBB == IfConv.Tail) ? *IfConv.FBB : *IfConv.
TBB;
1578 unsigned ExtraPredCost = 0;
1579 unsigned Cycles = 0;
1580 for (MachineInstr &
I : IfBlock) {
1581 unsigned NumCycles = SchedModel.computeInstrLatency(&
I,
false);
1583 Cycles += NumCycles - 1;
1584 ExtraPredCost +=
TII->getPredicationCost(
I);
1590 unsigned TExtra = 0;
1591 unsigned FExtra = 0;
1592 unsigned TCycle = 0;
1593 unsigned FCycle = 0;
1594 for (MachineInstr &
I : *IfConv.TBB) {
1595 unsigned NumCycles = SchedModel.computeInstrLatency(&
I,
false);
1597 TCycle += NumCycles - 1;
1598 TExtra +=
TII->getPredicationCost(
I);
1600 for (MachineInstr &
I : *IfConv.FBB) {
1601 unsigned NumCycles = SchedModel.computeInstrLatency(&
I,
false);
1603 FCycle += NumCycles - 1;
1604 FExtra +=
TII->getPredicationCost(
I);
1607 FCycle, FExtra, TrueProbability);
1612bool EarlyIfPredicator::tryConvertIf(MachineBasicBlock *
MBB) {
1614 while (IfConv.canConvertIf(
MBB,
true) && shouldConvertIf()) {
1616 SmallVector<MachineBasicBlock *, 4> RemoveBlocks;
1617 IfConv.convertIf(RemoveBlocks,
true);
1619 updateDomTree(DomTree, IfConv, RemoveBlocks);
1620 updateLoops(
Loops, RemoveBlocks);
1621 for (MachineBasicBlock *
MBB : RemoveBlocks)
1628 LLVM_DEBUG(
dbgs() <<
"********** EARLY IF-PREDICATOR **********\n"
1629 <<
"********** Function: " << MF.
getName() <<
'\n');
1637 SchedModel.
init(&STI);
1638 DomTree = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
1639 Loops = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
1640 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
1650 if (tryConvertIf(DomNode->getBlock()))
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements the BitVector class.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static unsigned InstrCount
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static cl::opt< unsigned > MaxRegionInstrs("early-ifcvt-max-region-instrs", cl::Hidden, cl::init(64), cl::desc("Limit the number of blocks and instructions examined when " "searching for calls between a load and the condition it feeds"))
static cl::opt< unsigned > MaxNumSteps("early-ifcvt-max-steps", cl::Hidden, cl::init(16), cl::desc("Limit the number of steps taken when searching for a " "recently loaded value"))
static cl::opt< unsigned > ColdEdgeThreshold("early-ifcvt-cold-edge-threshold", cl::Hidden, cl::init(1), cl::desc("Cold edge probability threshold in percent for using no " "critical-path extension budget (0 disables the threshold)"))
static bool hasSameValue(const MachineRegisterInfo &MRI, const TargetInstrInfo *TII, Register TReg, Register FReg)
static unsigned adjCycles(unsigned Cyc, int Delta)
static cl::opt< bool > Stress("stress-early-ifcvt", cl::Hidden, cl::desc("Turn all knobs to 11"))
static cl::opt< unsigned > BlockInstrLimit("early-ifcvt-limit", cl::init(30), cl::Hidden, cl::desc("Maximum number of instructions per speculated block."))
static bool isConstantPoolLoad(const MachineInstr *MI)
static cl::opt< bool > EnableDataDependentBranchAnalysis("enable-early-ifcvt-data-dependent", cl::Hidden, cl::init(false), cl::desc("Enable hard-to-predict branch analysis for if-conversion"))
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallPtrSet class.
This file defines the SparseSet class derived from the version described in Briggs,...
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
BitVector & reset()
Reset all bits in the bitvector.
BitVector & set()
Set all bits in the bitvector.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
void eraseNode(NodeT *BB)
eraseNode - Removes a node from the dominator tree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
LLVM_ABI PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
Remove the branching code at the end of the specific MBB.
bool isPredicated(const MachineInstr &MI) const override
Returns true if the instruction is already predicated.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
Reverses the branch condition of the specified condition list, returning false on success and true if...
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
Insert branch code into the end of the specified MachineBasicBlock.
bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, BranchProbability Probability) const override
Return true if it's profitable to predicate instructions with accumulated instruction latency of "Num...
bool PredicateInstruction(MachineInstr &MI, ArrayRef< MachineOperand > Cond) const override
Convert the instruction into a predicated instruction.
bool isPredicable(const MachineInstr &MI) const override
Return true if the specified instruction can be predicated.
unsigned pred_size() const
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
instr_iterator instr_begin()
succ_iterator succ_begin()
bool livein_empty() const
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned succ_size() const
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
LLVM_ABI bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< pred_iterator > predecessors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI void moveAfter(MachineBasicBlock *NewBefore)
LLVM_ABI BranchProbability getEdgeProbability(const MachineBasicBlock *Src, const MachineBasicBlock *Dst) const
Analysis pass which computes a MachineDominatorTree.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & back() const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
bool isTerminator(QueryType Type=AnyInBundle) const
Returns true if this instruction part of the terminator for a basic block.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
const MachineBasicBlock * getParent() const
LLVM_ABI bool isDereferenceableInvariantLoad() const
Return true if this load instruction never traps and points to a memory location whose value doesn't ...
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
mop_range uses()
Returns all operands which may be register uses.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
Analysis pass that exposes the MachineLoopInfo for a machine function.
A description of a memory reference used in the backend.
MachineOperand class - Representation of each machine instruction operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
LLVM_ABI unsigned getResourceLength(ArrayRef< const MachineBasicBlock * > Extrablocks={}, ArrayRef< const MCSchedClassDesc * > ExtraInstrs={}, ArrayRef< const MCSchedClassDesc * > RemoveInstrs={}) const
Return the resource length of the trace.
InstrCycles getInstrCycles(const MachineInstr &MI) const
Return the depth and height of MI.
LLVM_ABI unsigned getInstrSlack(const MachineInstr &MI) const
Return the slack of MI.
unsigned getCriticalPath() const
Return the length of the (data dependency) critical path through the trace.
LLVM_ABI unsigned getPHIDepth(const MachineInstr &PHI) const
Return the Depth of a PHI instruction in a trace center block successor.
LLVM_ABI void verifyAnalysis() const
LLVM_ABI void invalidate(const MachineBasicBlock *MBB)
Invalidate cached information about MBB.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
iterator erase(iterator I)
erase - Erases an existing element identified by a valid iterator.
void clear()
clear - Clears the set.
std::pair< iterator, bool > insert(const ValueT &Val)
insert - Attempts to insert a new element.
bool empty() const
empty - Returns true if the set is empty.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Provide an instruction scheduling machine model to CodeGen passes.
LLVM_ABI void init(const TargetSubtargetInfo *TSInfo, bool EnableSModel=true, bool EnableSItins=true)
Initialize the machine model for instruction scheduling.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual bool enableEarlyIfConversion() const
Enable the use of the early if conversion pass.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
self_iterator getIterator()
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI Printable printRegUnit(MCRegUnit Unit, const TargetRegisterInfo *TRI)
Create Printable object to print register units on a raw_ostream.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI char & EarlyIfConverterLegacyID
EarlyIfConverter - This pass performs if-conversion on SSA form by inserting cmov instructions.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
auto post_order(const T &G)
Post-order traversal of a graph.
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI char & EarlyIfPredicatorID
EarlyIfPredicator - This pass performs if-conversion on SSA form by predicating if/else block and ins...
DomTreeNodeBase< MachineBasicBlock > MachineDomTreeNode
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
unsigned Depth
Earliest issue cycle as determined by data dependencies and instruction latencies from the beginning ...
MachineInstr * ConditionDef