25#define DEBUG_TYPE "structcfg"
37STATISTIC(numSerialPatternMatch,
"CFGStructurizer number of serial pattern "
39STATISTIC(numIfPatternMatch,
"CFGStructurizer number of if pattern "
41STATISTIC(numClonedBlock,
"CFGStructurizer cloned blocks");
42STATISTIC(numClonedInstr,
"CFGStructurizer cloned instructions");
58#define SHOWNEWINSTR(i) LLVM_DEBUG(dbgs() << "New instr: " << *i << "\n");
60#define SHOWNEWBLK(b, msg) \
61 LLVM_DEBUG(dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
64#define SHOWBLK_DETAIL(b, msg) \
66 dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
71#define INVALIDSCCNUM -1
79class BlockInformation {
81 bool IsRetired =
false;
84 BlockInformation() =
default;
96 using MBBInfoMap = std::map<MachineBasicBlock *, BlockInformation *>;
97 using LoopLandInfoMap = std::map<MachineLoop *, MachineBasicBlock *>;
101 SinglePath_InPath = 1,
102 SinglePath_NotInPath = 2
112 return "AMDGPU Control Flow Graph structurizer Pass";
133 MachineFunctionProperties::Property::FailsVerification);
136 TRI = &
TII->getRegisterInfo();
141 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
143 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
145 PDT = &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree();
162 void printOrderedBlocks()
const {
165 iterBlkEnd = OrderedBlks.end(); iterBlk != iterBlkEnd; ++iterBlk, ++i) {
166 dbgs() <<
"BB" << (*iterBlk)->getNumber();
167 dbgs() <<
"(" << getSCCNum(*iterBlk) <<
"," << (*iterBlk)->size() <<
")";
168 if (i != 0 && i % 10 == 0) {
188 bool AllowSideEntry =
true)
const;
211 static int getBranchNzeroOpcode(
int OldOpcode);
212 static int getBranchZeroOpcode(
int OldOpcode);
213 static int getContinueNzeroOpcode(
int OldOpcode);
214 static int getContinueZeroOpcode(
int OldOpcode);
248 int loopendPatternMatch();
312 MBBInfoMap BlockInfoMap;
313 LoopLandInfoMap LLInfoMap;
314 std::map<MachineLoop *, bool> Visited;
321char R600MachineCFGStructurizer::ID = 0;
324 MBBInfoMap::const_iterator It = BlockInfoMap.find(
MBB);
325 if (It == BlockInfoMap.end())
327 return (*It).second->SccNum;
332 LoopLandInfoMap::const_iterator It = LLInfoMap.find(LoopRep);
333 if (It == LLInfoMap.end())
347 MBBInfoMap::const_iterator It = BlockInfoMap.find(
MBB);
348 if (It == BlockInfoMap.end())
350 return (*It).second->IsRetired;
359 if (!isRetiredBlock(LoopLand))
366R600MachineCFGStructurizer::PathToKind R600MachineCFGStructurizer::singlePathTo(
368 bool AllowSideEntry)
const {
370 if (SrcMBB == DstMBB)
371 return SinglePath_InPath;
372 while (SrcMBB && SrcMBB->
succ_size() == 1) {
374 if (SrcMBB == DstMBB)
375 return SinglePath_InPath;
376 if (!AllowSideEntry && SrcMBB->
pred_size() > 1)
377 return Not_SinglePath;
380 return SinglePath_NotInPath;
381 return Not_SinglePath;
388 if (!isRetiredBlock(*It))
396 unsigned BlockSizeThreshold = 30;
397 unsigned CloneInstrThreshold = 100;
402 unsigned BlkSize =
MBB->
size();
403 return ((BlkSize > BlockSizeThreshold) &&
404 (BlkSize * (
MBB->
pred_size() - 1) > CloneInstrThreshold));
407void R600MachineCFGStructurizer::reversePredicateSetter(
409 assert(
I.isValid() &&
"Expected valid iterator");
413 if (
I->getOpcode() == R600::PRED_X) {
414 switch (
I->getOperand(2).getImm()) {
415 case R600::PRED_SETE_INT:
416 I->getOperand(2).setImm(R600::PRED_SETNE_INT);
418 case R600::PRED_SETNE_INT:
419 I->getOperand(2).setImm(R600::PRED_SETE_INT);
421 case R600::PRED_SETE:
422 I->getOperand(2).setImm(R600::PRED_SETNE);
424 case R600::PRED_SETNE:
425 I->getOperand(2).setImm(R600::PRED_SETE);
456MachineInstr *R600MachineCFGStructurizer::insertInstrBefore(
468void R600MachineCFGStructurizer::insertCondBranchBefore(
481void R600MachineCFGStructurizer::insertCondBranchBefore(
487 blk->insert(
I, NewInstr);
492int R600MachineCFGStructurizer::getBranchNzeroOpcode(
int OldOpcode) {
494 case R600::JUMP_COND:
495 case R600::JUMP:
return R600::IF_PREDICATE_SET;
496 case R600::BRANCH_COND_i32:
497 case R600::BRANCH_COND_f32:
return R600::IF_LOGICALNZ_f32;
503int R600MachineCFGStructurizer::getBranchZeroOpcode(
int OldOpcode) {
505 case R600::JUMP_COND:
506 case R600::JUMP:
return R600::IF_PREDICATE_SET;
507 case R600::BRANCH_COND_i32:
508 case R600::BRANCH_COND_f32:
return R600::IF_LOGICALZ_f32;
514int R600MachineCFGStructurizer::getContinueNzeroOpcode(
int OldOpcode) {
516 case R600::JUMP_COND:
517 case R600::JUMP:
return R600::CONTINUE_LOGICALNZ_i32;
523int R600MachineCFGStructurizer::getContinueZeroOpcode(
int OldOpcode) {
525 case R600::JUMP_COND:
526 case R600::JUMP:
return R600::CONTINUE_LOGICALZ_i32;
533 return MI->getOperand(0).getMBB();
538 MI->getOperand(0).setMBB(
MBB);
549 return (*It == TrueBranch) ? *Next : *It;
553 switch (
MI->getOpcode()) {
554 case R600::JUMP_COND:
555 case R600::BRANCH_COND_i32:
556 case R600::BRANCH_COND_f32:
return true;
563bool R600MachineCFGStructurizer::isUncondBranch(
MachineInstr *
MI) {
564 switch (
MI->getOpcode()) {
578 if (
MI.getDebugLoc())
579 DL =
MI.getDebugLoc();
583MachineInstr *R600MachineCFGStructurizer::getNormalBlockBranchInstr(
587 if (
MI && (isCondBranch(
MI) || isUncondBranch(
MI)))
592MachineInstr *R600MachineCFGStructurizer::getLoopendBlockBranchInstr(
599 if (isCondBranch(
MI) || isUncondBranch(
MI))
601 if (!
TII->isMov(
MI->getOpcode()))
612 if (
instr->getOpcode() == R600::RETURN)
625 <<
" is return block without RETURN instr\n";);
638 Func->push_back(NewMBB);
644void R600MachineCFGStructurizer::replaceInstrUseOfBlockWith(
647 MachineInstr *BranchMI = getLoopendBlockBranchInstr(SrcMBB);
648 if (BranchMI && isCondBranch(BranchMI) &&
649 getTrueBranch(BranchMI) == OldMBB)
650 setTrueBranch(BranchMI, NewBlk);
656 &&
"found a jump table");
664 if (Pre->getOpcode() == R600::CONTINUE
665 && It->getOpcode() == R600::ENDLOOP)
672 for (
auto *
MI : ContInstr)
673 MI->eraseFromParent();
681bool R600MachineCFGStructurizer::prepare() {
682 bool Changed =
false;
688 orderBlocks(FuncRep);
697 if (ExitingMBBs.
size() == 0) {
707 removeUnconditionalBranch(
MBB);
708 removeRedundantConditionalBranch(
MBB);
709 if (isReturnBlock(
MBB)) {
715 if (RetBlks.
size() >= 2) {
716 addDummyExitBlock(RetBlks);
723bool R600MachineCFGStructurizer::run() {
729 ReverseVector(orderedBlks);
736 bool MakeProgress =
false;
737 int NumRemainedBlk = countActiveBlock(OrderedBlks.begin(),
743 <<
", numRemaintedBlk = " << NumRemainedBlk <<
"\n";);
765 SccNumBlk = NumRemainedBlk;
766 LLVM_DEBUG(
dbgs() <<
"start processing SCC" << getSCCNum(SccBeginMBB);
770 if (!isRetiredBlock(
MBB))
775 bool ContNextScc =
true;
777 || getSCCNum(SccBeginMBB) != getSCCNum(*It)) {
780 int sccRemainedNumBlk = countActiveBlock(SccBeginIter, It);
781 if (sccRemainedNumBlk != 1 && sccRemainedNumBlk >= SccNumBlk) {
783 <<
", sccNumIter = " << SccNumIter;
784 dbgs() <<
"doesn't make any progress\n";);
787 }
else if (sccRemainedNumBlk != 1 && sccRemainedNumBlk < SccNumBlk) {
788 SccNumBlk = sccRemainedNumBlk;
792 <<
"sccNumIter = " << SccNumIter <<
'\n';);
803 SccBeginMBB =
nullptr;
812 int NewnumRemainedBlk
813 = countActiveBlock(OrderedBlks.begin(), OrderedBlks.end());
815 if (NewnumRemainedBlk == 1 || NewnumRemainedBlk < NumRemainedBlk) {
817 NumRemainedBlk = NewnumRemainedBlk;
819 MakeProgress =
false;
823 }
while (!Finish && MakeProgress);
829 for (
auto &It : BlockInfoMap) {
830 if (It.second && It.second->IsRetired) {
831 assert((It.first)->getNumber() != -1);
832 LLVM_DEBUG(
dbgs() <<
"Erase BB" << (It.first)->getNumber() <<
"\n";);
833 It.first->eraseFromParent();
837 BlockInfoMap.clear();
852 const std::vector<MachineBasicBlock *> &SccNext = *It;
854 OrderedBlks.push_back(
MBB);
855 recordSccnum(
MBB, SccNum);
861 SccNum = getSCCNum(
MBB);
873 while ((CurMatch = patternMatchGroup(
MBB)) > 0)
874 NumMatch += CurMatch;
877 <<
", numMatch = " << NumMatch <<
"\n";);
884 NumMatch += loopendPatternMatch();
885 NumMatch += serialPatternMatch(
MBB);
886 NumMatch += ifPatternMatch(
MBB);
895 if (childBlk->
pred_size() != 1 || isActiveLoophead(childBlk))
898 mergeSerialBlock(
MBB, childBlk);
899 ++numSerialPatternMatch;
907 if (hasBackEdge(
MBB))
913 assert(isCondBranch(BranchMI));
917 NumMatch += serialPatternMatch(TrueMBB);
918 NumMatch += ifPatternMatch(TrueMBB);
920 NumMatch += serialPatternMatch(FalseMBB);
921 NumMatch += ifPatternMatch(FalseMBB);
940 reversePredicateSetter(
MBB->
end(), *
MBB);
944 && isSameloopDetachedContbreak(TrueMBB, FalseMBB)) {
947 && isSameloopDetachedContbreak(FalseMBB, TrueMBB)) {
950 return NumMatch + handleJumpintoIf(
MBB, TrueMBB, FalseMBB);
958 || (FalseMBB && FalseMBB->
pred_size() > 1))) {
959 Cloned += improveSimpleJumpintoIf(
MBB, TrueMBB, FalseMBB, &LandBlk);
962 if (TrueMBB && TrueMBB->
pred_size() > 1) {
963 TrueMBB = cloneBlockForPredecessor(TrueMBB,
MBB);
967 if (FalseMBB && FalseMBB->
pred_size() > 1) {
968 FalseMBB = cloneBlockForPredecessor(FalseMBB,
MBB);
972 mergeIfthenelseBlock(BranchMI,
MBB, TrueMBB, FalseMBB, LandBlk);
976 numClonedBlock += Cloned;
978 return 1 + Cloned + NumMatch;
981int R600MachineCFGStructurizer::loopendPatternMatch() {
982 std::deque<MachineLoop *> NestedLoops;
985 NestedLoops.push_front(
ML);
987 if (NestedLoops.empty())
995 if (ExaminedLoop->getNumBlocks() == 0 || Visited[ExaminedLoop])
998 int NumBreak = mergeLoop(ExaminedLoop);
1006int R600MachineCFGStructurizer::mergeLoop(
MachineLoop *LoopRep) {
1010 assert(!ExitingMBBs.
empty() &&
"Infinite Loop not supported");
1012 <<
" exiting blocks\n";);
1021 assert(ExitBlk &&
"Loop has several exit block");
1023 for (
auto *LB : inverse_children<MachineBasicBlock*>(LoopHeader))
1028 mergeLoopbreakBlock(
MBB, ExitBlk);
1030 settleLoopcontBlock(
MBB, LoopHeader);
1034 Match += serialPatternMatch(LoopHeader);
1035 Match += ifPatternMatch(LoopHeader);
1036 }
while (
Match > 0);
1037 mergeLooplandBlock(LoopHeader, ExitBlk);
1040 MLI->changeLoopFor(LoopHeader, ParentLoop);
1042 MLI->removeBlock(LoopHeader);
1043 Visited[LoopRep] =
true;
1047bool R600MachineCFGStructurizer::isSameloopDetachedContbreak(
1051 if (LoopRep&& LoopRep == MLI->getLoopFor(Src2MBB)) {
1066 int Num = handleJumpintoIfImp(HeadMBB, TrueMBB, FalseMBB);
1068 LLVM_DEBUG(
dbgs() <<
"handleJumpintoIf swap trueBlk and FalseBlk"
1070 Num = handleJumpintoIfImp(HeadMBB, FalseMBB, TrueMBB);
1085 <<
", numSucc=" << TrueMBB->
succ_size() <<
" false = BB"
1091 if (singlePathTo(FalseMBB, DownBlk) == SinglePath_InPath) {
1094 Num += cloneOnSideEntryTo(HeadMBB, TrueMBB, DownBlk);
1095 Num += cloneOnSideEntryTo(HeadMBB, FalseMBB, DownBlk);
1097 numClonedBlock += Num;
1098 Num += serialPatternMatch(*HeadMBB->
succ_begin());
1099 Num += serialPatternMatch(*std::next(HeadMBB->
succ_begin()));
1100 Num += ifPatternMatch(HeadMBB);
1106 DownBlk = (DownBlk->succ_size() == 1) ? (*DownBlk->succ_begin()) :
nullptr;
1113void R600MachineCFGStructurizer::showImproveSimpleJumpintoIf(
1117 <<
" size = " << HeadMBB->
size();
1125 dbgs() <<
", true = BB" << TrueMBB->
getNumber() <<
" size = "
1126 << TrueMBB->
size() <<
" numPred = " << TrueMBB->
pred_size();
1134 dbgs() <<
", false = BB" << FalseMBB->
getNumber() <<
" size = "
1135 << FalseMBB->
size() <<
" numPred = " << FalseMBB->
pred_size();
1143 dbgs() <<
", land = BB" << LandMBB->
getNumber() <<
" size = "
1144 << LandMBB->
size() <<
" numPred = " << LandMBB->
pred_size();
1156int R600MachineCFGStructurizer::improveSimpleJumpintoIf(
MachineBasicBlock *HeadMBB,
1159 bool MigrateTrue =
false;
1160 bool MigrateFalse =
false;
1165 && (!FalseMBB || FalseMBB->
succ_size() <= 1));
1167 if (TrueMBB == FalseMBB)
1170 MigrateTrue = needMigrateBlock(TrueMBB);
1171 MigrateFalse = needMigrateBlock(FalseMBB);
1173 if (!MigrateTrue && !MigrateFalse)
1179 if (!MigrateTrue && TrueMBB && TrueMBB->
pred_size() > 1)
1181 if (!MigrateFalse && FalseMBB && FalseMBB->
pred_size() > 1)
1182 MigrateFalse =
true;
1185 dbgs() <<
"before improveSimpleJumpintoIf: ";
1186 showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0););
1200 if (!MigrateTrue || !MigrateFalse) {
1271 bool LandBlkHasOtherPred = (LandBlk->
pred_size() > 2);
1276 if (LandBlkHasOtherPred) {
1281 insertCondBranchBefore(LandBlk,
I, R600::IF_PREDICATE_SET,
1289 insertCondBranchBefore(LandBlk,
I, R600::IF_PREDICATE_SET, InitReg,
1293 migrateInstruction(TrueMBB, LandBlk,
I);
1299 insertInstrBefore(
I, R600::ELSE);
1302 migrateInstruction(FalseMBB, LandBlk,
I);
1309 if (LandBlkHasOtherPred) {
1311 insertInstrBefore(
I, R600::ENDIF);
1315 if (
MBB != TrueMBB &&
MBB != FalseMBB)
1319 dbgs() <<
"result from improveSimpleJumpintoIf: ";
1320 showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0););
1323 *LandMBBPtr = LandBlk;
1335 cloneSuccessorList(DstMBB, SrcMBB);
1337 removeSuccessor(SrcMBB);
1338 MLI->removeBlock(SrcMBB);
1339 retireBlock(SrcMBB);
1342void R600MachineCFGStructurizer::mergeIfthenelseBlock(
MachineInstr *BranchMI,
1349 dbgs() <<
"{ ";
if (FalseMBB) {
1351 }
dbgs() <<
" }\n ";
1352 dbgs() <<
"landBlock: ";
if (!LandMBB) {
dbgs() <<
"NULL"; }
else {
1368 insertCondBranchBefore(
I, getBranchNzeroOpcode(OldOpcode),
1376 retireBlock(TrueMBB);
1377 MLI->removeBlock(TrueMBB);
1381 insertInstrBefore(
I, R600::ELSE);
1387 retireBlock(FalseMBB);
1388 MLI->removeBlock(FalseMBB);
1390 insertInstrBefore(
I, R600::ENDIF);
1394 if (LandMBB && TrueMBB && FalseMBB)
1401 <<
" land = BB" << LandMBB->
getNumber() <<
"\n";);
1403 insertInstrBefore(DstBlk, R600::WHILELOOP,
DebugLoc());
1404 insertInstrEnd(DstBlk, R600::ENDLOOP,
DebugLoc());
1408void R600MachineCFGStructurizer::mergeLoopbreakBlock(
MachineBasicBlock *ExitingMBB,
1411 << ExitingMBB->
getNumber() <<
" land = BB"
1413 MachineInstr *BranchMI = getLoopendBlockBranchInstr(ExitingMBB);
1414 assert(BranchMI && isCondBranch(BranchMI));
1418 if (TrueBranch != LandMBB)
1419 reversePredicateSetter(
I, *
I->getParent());
1420 insertCondBranchBefore(ExitingMBB,
I, R600::IF_PREDICATE_SET, R600::PREDICATE_BIT,
DL);
1421 insertInstrBefore(
I, R600::BREAK);
1422 insertInstrBefore(
I, R600::ENDIF);
1429void R600MachineCFGStructurizer::settleLoopcontBlock(
MachineBasicBlock *ContingMBB,
1432 << ContingMBB->
getNumber() <<
", cont = BB"
1440 int OldOpcode =
MI->getOpcode();
1443 bool UseContinueLogical = ((&*ContingMBB->
rbegin()) ==
MI);
1445 if (!UseContinueLogical) {
1447 TrueBranch == ContMBB ? getBranchNzeroOpcode(OldOpcode) :
1448 getBranchZeroOpcode(OldOpcode);
1449 insertCondBranchBefore(
I, BranchOpcode,
DL);
1451 insertInstrEnd(ContingMBB, R600::CONTINUE,
DL);
1452 insertInstrEnd(ContingMBB, R600::ENDIF,
DL);
1455 TrueBranch == ContMBB ? getContinueNzeroOpcode(OldOpcode) :
1456 getContinueZeroOpcode(OldOpcode);
1457 insertCondBranchBefore(
I, BranchOpcode,
DL);
1460 MI->eraseFromParent();
1467 insertInstrEnd(ContingMBB, R600::CONTINUE,
1468 getLastDebugLocInBB(ContingMBB));
1476 while (SrcMBB && SrcMBB != DstMBB) {
1479 SrcMBB = cloneBlockForPredecessor(SrcMBB, PreMBB);
1496 replaceInstrUseOfBlockWith(PredMBB,
MBB, CloneMBB);
1502 cloneSuccessorList(CloneMBB,
MBB);
1504 numClonedInstr +=
MBB->
size();
1510 SHOWNEWBLK(CloneMBB,
"result of Cloned block: ");
1519 MachineInstr *BranchMI = getNormalBlockBranchInstr(SrcMBB);
1521 LLVM_DEBUG(
dbgs() <<
"migrateInstruction don't see branch instr\n";);
1522 SpliceEnd = SrcMBB->
end();
1524 LLVM_DEBUG(
dbgs() <<
"migrateInstruction see branch instr: " << *BranchMI);
1525 SpliceEnd = BranchMI;
1527 LLVM_DEBUG(
dbgs() <<
"migrateInstruction before splice dstSize = "
1528 << DstMBB->
size() <<
"srcSize = " << SrcMBB->
size()
1534 LLVM_DEBUG(
dbgs() <<
"migrateInstruction after splice dstSize = "
1535 << DstMBB->
size() <<
"srcSize = " << SrcMBB->
size()
1540R600MachineCFGStructurizer::normalizeInfiniteLoopExit(
MachineLoop* LoopRep) {
1544 if (!LoopHeader || !LoopLatch)
1546 MachineInstr *BranchMI = getLoopendBlockBranchInstr(LoopLatch);
1548 if (!BranchMI || !isUncondBranch(BranchMI))
1553 SHOWNEWBLK(DummyExitBlk,
"DummyExitBlock to normalize infiniteLoop: ");
1554 LLVM_DEBUG(
dbgs() <<
"Old branch instr: " << *BranchMI <<
"\n";);
1556 Ctx.
emitError(
"Extra register needed to handle CFG");
1565 while ((BranchMI = getLoopendBlockBranchInstr(
MBB))
1566 && isUncondBranch(BranchMI)) {
1567 LLVM_DEBUG(
dbgs() <<
"Removing uncond branch instr: " << *BranchMI);
1572void R600MachineCFGStructurizer::removeRedundantConditionalBranch(
1582 assert(BranchMI && isCondBranch(BranchMI));
1583 LLVM_DEBUG(
dbgs() <<
"Removing unneeded cond branch instr: " << *BranchMI);
1585 SHOWNEWBLK(MBB1,
"Removing redundant successor");
1589void R600MachineCFGStructurizer::addDummyExitBlock(
1593 insertInstrEnd(DummyExitBlk, R600::RETURN);
1597 MI->eraseFromParent();
1600 <<
" successors\n";);
1602 SHOWNEWBLK(DummyExitBlk,
"DummyExitBlock: ");
1612 BlockInformation *&srcBlkInfo = BlockInfoMap[
MBB];
1614 srcBlkInfo =
new BlockInformation();
1615 srcBlkInfo->SccNum = SccNum;
1621 BlockInformation *&SrcBlkInfo = BlockInfoMap[
MBB];
1624 SrcBlkInfo =
new BlockInformation();
1626 SrcBlkInfo->IsRetired =
true;
1631 "AMDGPU CFG Structurizer",
false,
false)
1639 return new R600MachineCFGStructurizer();
Unify divergent function exit nodes
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
const HexagonInstrInfo * TII
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Provides R600 specific target descriptions.
#define SHOWNEWBLK(b, msg)
Interface definition for R600RegisterInfo.
AMDGPU R600 specific subclass of TargetSubtarget.
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
static uint32_t blk(uint32_t *Buf, int I)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
FunctionPass class - This class is used to implement most global optimizations.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
This is an important class for using LLVM in a threaded context.
void emitError(uint64_t LocCookie, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
bool contains(const LoopT *L) const
Return true if the specified loop is contained within in this loop.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
void getExitBlocks(SmallVectorImpl< BlockT * > &ExitBlocks) const
Return all of the successor blocks of this loop.
void getExitingBlocks(SmallVectorImpl< BlockT * > &ExitingBlocks) const
Return all blocks inside the loop that have successors outside of the loop.
BlockT * getHeader() const
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
unsigned pred_size() const
void replaceSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New)
Replace successor OLD with NEW and update probability info.
instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
void push_back(MachineInstr *MI)
succ_iterator succ_begin()
unsigned succ_size() const
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
SmallVectorImpl< MachineBasicBlock * >::iterator succ_iterator
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
void print(raw_ostream &OS, const SlotIndexes *=nullptr, bool IsStandalone=true) const
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
reverse_iterator rbegin()
bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this 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 '...
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
MachineFunctionProperties & set(Property P)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void dump() const
dump - Print the current MachineFunction to cerr, useful for debugger use.
MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImplicit=false)
CreateMachineInstr - Allocate a new MachineInstr.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineFunctionProperties & getProperties() const
Get the function properties.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
bool isEmpty() const
isEmpty - Return true if there are no jump tables.
Register getReg() const
getReg - Returns the register number.
MachinePostDominatorTree - an analysis pass wrapper for DominatorTree used to compute the post-domina...
Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
typename SuperClass::const_iterator const_iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
void initializeR600MachineCFGStructurizerPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
iterator_range< df_iterator< T > > depth_first(const T &G)
FunctionPass * createR600MachineCFGStructurizerPass()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.