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");
52#define SHOWNEWINSTR(i) LLVM_DEBUG(dbgs() << "New instr: " << *i << "\n");
54#define SHOWNEWBLK(b, msg) \
55 LLVM_DEBUG(dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
58#define SHOWBLK_DETAIL(b, msg) \
60 dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
65#define INVALIDSCCNUM -1
73class BlockInformation {
75 bool IsRetired =
false;
78 BlockInformation() =
default;
89 using MBBVector = SmallVector<MachineBasicBlock *, 32>;
90 using MBBInfoMap = std::map<MachineBasicBlock *, BlockInformation *>;
91 using LoopLandInfoMap = std::map<MachineLoop *, MachineBasicBlock *>;
95 SinglePath_InPath = 1,
96 SinglePath_NotInPath = 2
101 R600MachineCFGStructurizer() : MachineFunctionPass(ID) {}
103 StringRef getPassName()
const override {
104 return "AMDGPU Control Flow Graph structurizer Pass";
107 void getAnalysisUsage(AnalysisUsage &AU)
const override {
109 AU.
addRequired<MachinePostDominatorTreeWrapperPass>();
122 bool runOnMachineFunction(MachineFunction &MF)
override {
127 TRI = &TII->getRegisterInfo();
132 MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
134 MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
136 PDT = &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree();
145 MachineDominatorTree *MDT;
146 MachinePostDominatorTree *PDT;
147 MachineLoopInfo *MLI;
148 const R600InstrInfo *TII =
nullptr;
149 const R600RegisterInfo *TRI =
nullptr;
153 void printOrderedBlocks()
const {
156 iterBlkEnd = OrderedBlks.end(); iterBlk != iterBlkEnd; ++iterBlk, ++i) {
157 dbgs() <<
"BB" << (*iterBlk)->getNumber();
158 dbgs() <<
"(" << getSCCNum(*iterBlk) <<
"," << (*iterBlk)->size() <<
")";
159 if (i != 0 && i % 10 == 0) {
167 static void PrintLoopinfo(
const MachineLoopInfo &LoopInfo) {
168 for (
const MachineLoop *L : LoopInfo)
173 int getSCCNum(MachineBasicBlock *
MBB)
const;
174 MachineBasicBlock *getLoopLandInfo(MachineLoop *LoopRep)
const;
175 bool hasBackEdge(MachineBasicBlock *
MBB)
const;
176 bool isRetiredBlock(MachineBasicBlock *
MBB)
const;
177 bool isActiveLoophead(MachineBasicBlock *
MBB)
const;
178 PathToKind singlePathTo(MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
179 bool AllowSideEntry =
true)
const;
182 bool needMigrateBlock(MachineBasicBlock *
MBB)
const;
186 MachineBasicBlock &
MBB);
188 void orderBlocks(MachineFunction *MF);
191 void insertInstrEnd(MachineBasicBlock *
MBB,
int NewOpcode,
193 MachineInstr *insertInstrBefore(MachineBasicBlock *
MBB,
int NewOpcode,
198 void insertCondBranchBefore(MachineBasicBlock *
MBB,
202 static int getBranchNzeroOpcode(
int OldOpcode);
203 static int getBranchZeroOpcode(
int OldOpcode);
204 static int getContinueNzeroOpcode(
int OldOpcode);
205 static int getContinueZeroOpcode(
int OldOpcode);
206 static MachineBasicBlock *getTrueBranch(MachineInstr *
MI);
207 static void setTrueBranch(MachineInstr *
MI, MachineBasicBlock *
MBB);
208 static MachineBasicBlock *getFalseBranch(MachineBasicBlock *
MBB,
210 static bool isCondBranch(MachineInstr *
MI);
211 static bool isUncondBranch(MachineInstr *
MI);
212 static DebugLoc getLastDebugLocInBB(MachineBasicBlock *
MBB);
213 static MachineInstr *getNormalBlockBranchInstr(MachineBasicBlock *
MBB);
219 MachineInstr *getLoopendBlockBranchInstr(MachineBasicBlock *
MBB);
221 static MachineInstr *getReturnInstr(MachineBasicBlock *
MBB);
222 static bool isReturnBlock(MachineBasicBlock *
MBB);
223 static void cloneSuccessorList(MachineBasicBlock *DstMBB,
224 MachineBasicBlock *SrcMBB);
225 static MachineBasicBlock *clone(MachineBasicBlock *
MBB);
230 void replaceInstrUseOfBlockWith(MachineBasicBlock *SrcMBB,
231 MachineBasicBlock *OldMBB, MachineBasicBlock *NewBlk);
233 static void wrapup(MachineBasicBlock *
MBB);
235 int patternMatch(MachineBasicBlock *
MBB);
236 int patternMatchGroup(MachineBasicBlock *
MBB);
237 int serialPatternMatch(MachineBasicBlock *
MBB);
238 int ifPatternMatch(MachineBasicBlock *
MBB);
239 int loopendPatternMatch();
240 int mergeLoop(MachineLoop *LoopRep);
245 bool isSameloopDetachedContbreak(MachineBasicBlock *Src1MBB,
246 MachineBasicBlock *Src2MBB);
247 int handleJumpintoIf(MachineBasicBlock *HeadMBB,
248 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
249 int handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
250 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
251 int improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
252 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
253 MachineBasicBlock **LandMBBPtr);
254 void showImproveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
255 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
256 MachineBasicBlock *LandMBB,
bool Detail =
false);
257 int cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
258 MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB);
259 void mergeSerialBlock(MachineBasicBlock *DstMBB,
260 MachineBasicBlock *SrcMBB);
262 void mergeIfthenelseBlock(MachineInstr *BranchMI,
263 MachineBasicBlock *
MBB, MachineBasicBlock *TrueMBB,
264 MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB);
265 void mergeLooplandBlock(MachineBasicBlock *DstMBB,
266 MachineBasicBlock *LandMBB);
267 void mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
268 MachineBasicBlock *LandMBB);
269 void settleLoopcontBlock(MachineBasicBlock *ContingMBB,
270 MachineBasicBlock *ContMBB);
280 MachineBasicBlock *normalizeInfiniteLoopExit(MachineLoop *LoopRep);
281 void removeUnconditionalBranch(MachineBasicBlock *
MBB);
291 void removeRedundantConditionalBranch(MachineBasicBlock *
MBB);
293 void addDummyExitBlock(SmallVectorImpl<MachineBasicBlock *> &RetMBB);
294 void removeSuccessor(MachineBasicBlock *
MBB);
295 MachineBasicBlock *cloneBlockForPredecessor(MachineBasicBlock *
MBB,
296 MachineBasicBlock *PredMBB);
297 void migrateInstruction(MachineBasicBlock *SrcMBB,
299 void recordSccnum(MachineBasicBlock *
MBB,
int SCCNum);
300 void retireBlock(MachineBasicBlock *
MBB);
303 MBBInfoMap BlockInfoMap;
304 LoopLandInfoMap LLInfoMap;
305 std::map<MachineLoop *, bool> Visited;
306 MachineFunction *FuncRep;
312char R600MachineCFGStructurizer::ID = 0;
315 MBBInfoMap::const_iterator It = BlockInfoMap.find(
MBB);
316 if (It == BlockInfoMap.end())
318 return (*It).second->SccNum;
321MachineBasicBlock *R600MachineCFGStructurizer::getLoopLandInfo(MachineLoop *LoopRep)
323 LoopLandInfoMap::const_iterator It = LLInfoMap.find(LoopRep);
324 if (It == LLInfoMap.end())
329bool R600MachineCFGStructurizer::hasBackEdge(MachineBasicBlock *
MBB)
const {
333 MachineBasicBlock *LoopHeader = LoopRep->
getHeader();
337bool R600MachineCFGStructurizer::isRetiredBlock(MachineBasicBlock *
MBB)
const {
338 MBBInfoMap::const_iterator It = BlockInfoMap.find(
MBB);
339 if (It == BlockInfoMap.end())
341 return (*It).second->IsRetired;
344bool R600MachineCFGStructurizer::isActiveLoophead(MachineBasicBlock *
MBB)
const {
347 MachineBasicBlock *LoopLand = getLoopLandInfo(LoopRep);
350 if (!isRetiredBlock(LoopLand))
357R600MachineCFGStructurizer::PathToKind R600MachineCFGStructurizer::singlePathTo(
358 MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
359 bool AllowSideEntry)
const {
361 if (SrcMBB == DstMBB)
362 return SinglePath_InPath;
363 while (SrcMBB && SrcMBB->
succ_size() == 1) {
365 if (SrcMBB == DstMBB)
366 return SinglePath_InPath;
367 if (!AllowSideEntry && SrcMBB->
pred_size() > 1)
368 return Not_SinglePath;
371 return SinglePath_NotInPath;
372 return Not_SinglePath;
379 if (!isRetiredBlock(*It))
386bool R600MachineCFGStructurizer::needMigrateBlock(MachineBasicBlock *
MBB)
const {
387 unsigned BlockSizeThreshold = 30;
388 unsigned CloneInstrThreshold = 100;
393 unsigned BlkSize =
MBB->
size();
394 return ((BlkSize > BlockSizeThreshold) &&
395 (BlkSize * (
MBB->
pred_size() - 1) > CloneInstrThreshold));
398void R600MachineCFGStructurizer::reversePredicateSetter(
400 assert(
I.isValid() &&
"Expected valid iterator");
404 if (
I->getOpcode() == R600::PRED_X) {
405 switch (
I->getOperand(2).getImm()) {
406 case R600::PRED_SETE_INT:
407 I->getOperand(2).setImm(R600::PRED_SETNE_INT);
409 case R600::PRED_SETNE_INT:
410 I->getOperand(2).setImm(R600::PRED_SETE_INT);
412 case R600::PRED_SETE:
413 I->getOperand(2).setImm(R600::PRED_SETNE);
415 case R600::PRED_SETNE:
416 I->getOperand(2).setImm(R600::PRED_SETE);
425void R600MachineCFGStructurizer::insertInstrEnd(MachineBasicBlock *
MBB,
434MachineInstr *R600MachineCFGStructurizer::insertInstrBefore(MachineBasicBlock *
MBB,
447MachineInstr *R600MachineCFGStructurizer::insertInstrBefore(
449 MachineInstr *OldMI = &(*I);
451 MachineInstr *NewMBB =
459void R600MachineCFGStructurizer::insertCondBranchBefore(
461 MachineInstr *OldMI = &(*I);
464 MachineInstr *NewMI = MF->CreateMachineInstr(
TII->get(NewOpcode),
DL);
466 MachineInstrBuilder MIB(*MF, NewMI);
472void R600MachineCFGStructurizer::insertCondBranchBefore(
475 MachineFunction *MF =
blk->getParent();
476 MachineInstr *NewInstr = MF->CreateMachineInstr(
TII->get(NewOpcode),
DL);
478 blk->insert(
I, NewInstr);
479 MachineInstrBuilder(*MF, NewInstr).addReg(RegNum,
false);
483int R600MachineCFGStructurizer::getBranchNzeroOpcode(
int OldOpcode) {
485 case R600::JUMP_COND:
486 case R600::JUMP:
return R600::IF_PREDICATE_SET;
487 case R600::BRANCH_COND_i32:
488 case R600::BRANCH_COND_f32:
return R600::IF_LOGICALNZ_f32;
494int R600MachineCFGStructurizer::getBranchZeroOpcode(
int OldOpcode) {
496 case R600::JUMP_COND:
497 case R600::JUMP:
return R600::IF_PREDICATE_SET;
498 case R600::BRANCH_COND_i32:
499 case R600::BRANCH_COND_f32:
return R600::IF_LOGICALZ_f32;
505int R600MachineCFGStructurizer::getContinueNzeroOpcode(
int OldOpcode) {
507 case R600::JUMP_COND:
508 case R600::JUMP:
return R600::CONTINUE_LOGICALNZ_i32;
514int R600MachineCFGStructurizer::getContinueZeroOpcode(
int OldOpcode) {
516 case R600::JUMP_COND:
517 case R600::JUMP:
return R600::CONTINUE_LOGICALZ_i32;
523MachineBasicBlock *R600MachineCFGStructurizer::getTrueBranch(MachineInstr *
MI) {
524 return MI->getOperand(0).getMBB();
527void R600MachineCFGStructurizer::setTrueBranch(MachineInstr *
MI,
528 MachineBasicBlock *
MBB) {
529 MI->getOperand(0).setMBB(
MBB);
533R600MachineCFGStructurizer::getFalseBranch(MachineBasicBlock *
MBB,
536 MachineBasicBlock *TrueBranch = getTrueBranch(
MI);
540 return (*It == TrueBranch) ? *
Next : *It;
543bool R600MachineCFGStructurizer::isCondBranch(MachineInstr *
MI) {
544 switch (
MI->getOpcode()) {
545 case R600::JUMP_COND:
546 case R600::BRANCH_COND_i32:
547 case R600::BRANCH_COND_f32:
return true;
554bool R600MachineCFGStructurizer::isUncondBranch(MachineInstr *
MI) {
555 switch (
MI->getOpcode()) {
565DebugLoc R600MachineCFGStructurizer::getLastDebugLocInBB(MachineBasicBlock *
MBB) {
568 for (MachineInstr &
MI : *
MBB)
569 if (
MI.getDebugLoc())
570 DL =
MI.getDebugLoc();
574MachineInstr *R600MachineCFGStructurizer::getNormalBlockBranchInstr(
575 MachineBasicBlock *
MBB) {
577 MachineInstr *
MI = &*It;
578 if (
MI && (isCondBranch(
MI) || isUncondBranch(
MI)))
583MachineInstr *R600MachineCFGStructurizer::getLoopendBlockBranchInstr(
584 MachineBasicBlock *
MBB) {
588 MachineInstr *
MI = &*It;
590 if (isCondBranch(
MI) || isUncondBranch(
MI))
592 if (!
TII->isMov(
MI->getOpcode()))
599MachineInstr *R600MachineCFGStructurizer::getReturnInstr(MachineBasicBlock *
MBB) {
602 MachineInstr *
instr = &(*It);
603 if (
instr->getOpcode() == R600::RETURN)
609bool R600MachineCFGStructurizer::isReturnBlock(MachineBasicBlock *
MBB) {
610 MachineInstr *
MI = getReturnInstr(
MBB);
616 <<
" is return block without RETURN instr\n";);
620void R600MachineCFGStructurizer::cloneSuccessorList(MachineBasicBlock *DstMBB,
621 MachineBasicBlock *SrcMBB) {
622 for (MachineBasicBlock *Succ : SrcMBB->
successors())
626MachineBasicBlock *R600MachineCFGStructurizer::clone(MachineBasicBlock *
MBB) {
628 MachineBasicBlock *NewMBB =
Func->CreateMachineBasicBlock();
629 Func->push_back(NewMBB);
630 for (
const MachineInstr &It : *
MBB)
635void R600MachineCFGStructurizer::replaceInstrUseOfBlockWith(
636 MachineBasicBlock *SrcMBB, MachineBasicBlock *OldMBB,
637 MachineBasicBlock *NewBlk) {
638 MachineInstr *BranchMI = getLoopendBlockBranchInstr(SrcMBB);
639 if (BranchMI && isCondBranch(BranchMI) &&
640 getTrueBranch(BranchMI) == OldMBB)
641 setTrueBranch(BranchMI, NewBlk);
644void R600MachineCFGStructurizer::wrapup(MachineBasicBlock *
MBB) {
647 &&
"found a jump table");
655 if (Pre->getOpcode() == R600::CONTINUE
656 && It->getOpcode() == R600::ENDLOOP)
663 for (
auto *
MI : ContInstr)
664 MI->eraseFromParent();
672bool R600MachineCFGStructurizer::prepare() {
679 orderBlocks(FuncRep);
684 for (MachineLoop *LoopRep : *MLI) {
688 if (ExitingMBBs.
size() == 0) {
689 MachineBasicBlock* DummyExitBlk = normalizeInfiniteLoopExit(LoopRep);
697 for (MachineBasicBlock *
MBB : OrderedBlks) {
698 removeUnconditionalBranch(
MBB);
699 removeRedundantConditionalBranch(
MBB);
700 if (isReturnBlock(
MBB)) {
706 if (RetBlks.
size() >= 2) {
707 addDummyExitBlock(RetBlks);
714bool R600MachineCFGStructurizer::run() {
720 ReverseVector(orderedBlks);
726 MachineBasicBlock *
MBB;
727 bool MakeProgress =
false;
728 int NumRemainedBlk = countActiveBlock(OrderedBlks.begin(),
734 <<
", numRemaintedBlk = " << NumRemainedBlk <<
"\n";);
744 MachineBasicBlock *SccBeginMBB =
nullptr;
756 SccNumBlk = NumRemainedBlk;
757 LLVM_DEBUG(
dbgs() <<
"start processing SCC" << getSCCNum(SccBeginMBB);
761 if (!isRetiredBlock(
MBB))
766 bool ContNextScc =
true;
768 || getSCCNum(SccBeginMBB) != getSCCNum(*It)) {
771 int sccRemainedNumBlk = countActiveBlock(SccBeginIter, It);
772 if (sccRemainedNumBlk != 1 && sccRemainedNumBlk >= SccNumBlk) {
774 <<
", sccNumIter = " << SccNumIter;
775 dbgs() <<
"doesn't make any progress\n";);
778 }
else if (sccRemainedNumBlk != 1 && sccRemainedNumBlk < SccNumBlk) {
779 SccNumBlk = sccRemainedNumBlk;
783 <<
"sccNumIter = " << SccNumIter <<
'\n';);
794 SccBeginMBB =
nullptr;
797 MachineBasicBlock *EntryMBB =
803 int NewnumRemainedBlk
804 = countActiveBlock(OrderedBlks.begin(), OrderedBlks.end());
806 if (NewnumRemainedBlk == 1 || NewnumRemainedBlk < NumRemainedBlk) {
808 NumRemainedBlk = NewnumRemainedBlk;
810 MakeProgress =
false;
814 }
while (!Finish && MakeProgress);
820 for (
auto &It : BlockInfoMap) {
821 if (It.second && It.second->IsRetired) {
822 assert((It.first)->getNumber() != -1);
823 LLVM_DEBUG(
dbgs() <<
"Erase BB" << (It.first)->getNumber() <<
"\n";);
824 It.first->eraseFromParent();
828 BlockInfoMap.clear();
839void R600MachineCFGStructurizer::orderBlocks(MachineFunction *MF) {
841 for (scc_iterator<MachineFunction *> It =
scc_begin(MF); !It.isAtEnd();
843 const std::vector<MachineBasicBlock *> &SccNext = *It;
844 for (MachineBasicBlock *
MBB : SccNext) {
845 OrderedBlks.push_back(
MBB);
846 recordSccnum(
MBB, SccNum);
852 SccNum = getSCCNum(
MBB);
858int R600MachineCFGStructurizer::patternMatch(MachineBasicBlock *
MBB) {
864 while ((CurMatch = patternMatchGroup(
MBB)) > 0)
865 NumMatch += CurMatch;
868 <<
", numMatch = " << NumMatch <<
"\n";);
873int R600MachineCFGStructurizer::patternMatchGroup(MachineBasicBlock *
MBB) {
875 NumMatch += loopendPatternMatch();
876 NumMatch += serialPatternMatch(
MBB);
877 NumMatch += ifPatternMatch(
MBB);
881int R600MachineCFGStructurizer::serialPatternMatch(MachineBasicBlock *
MBB) {
886 if (childBlk->
pred_size() != 1 || isActiveLoophead(childBlk))
889 mergeSerialBlock(
MBB, childBlk);
890 ++numSerialPatternMatch;
894int R600MachineCFGStructurizer::ifPatternMatch(MachineBasicBlock *
MBB) {
898 if (hasBackEdge(
MBB))
900 MachineInstr *BranchMI = getNormalBlockBranchInstr(
MBB);
904 assert(isCondBranch(BranchMI));
907 MachineBasicBlock *TrueMBB = getTrueBranch(BranchMI);
908 NumMatch += serialPatternMatch(TrueMBB);
909 NumMatch += ifPatternMatch(TrueMBB);
910 MachineBasicBlock *FalseMBB = getFalseBranch(
MBB, BranchMI);
911 NumMatch += serialPatternMatch(FalseMBB);
912 NumMatch += ifPatternMatch(FalseMBB);
913 MachineBasicBlock *LandBlk;
931 reversePredicateSetter(
MBB->
end(), *
MBB);
935 && isSameloopDetachedContbreak(TrueMBB, FalseMBB)) {
938 && isSameloopDetachedContbreak(FalseMBB, TrueMBB)) {
941 return NumMatch + handleJumpintoIf(
MBB, TrueMBB, FalseMBB);
949 || (FalseMBB && FalseMBB->
pred_size() > 1))) {
950 Cloned += improveSimpleJumpintoIf(
MBB, TrueMBB, FalseMBB, &LandBlk);
953 if (TrueMBB && TrueMBB->
pred_size() > 1) {
954 TrueMBB = cloneBlockForPredecessor(TrueMBB,
MBB);
958 if (FalseMBB && FalseMBB->
pred_size() > 1) {
959 FalseMBB = cloneBlockForPredecessor(FalseMBB,
MBB);
963 mergeIfthenelseBlock(BranchMI,
MBB, TrueMBB, FalseMBB, LandBlk);
967 numClonedBlock += Cloned;
969 return 1 + Cloned + NumMatch;
972int R600MachineCFGStructurizer::loopendPatternMatch() {
973 std::deque<MachineLoop *> NestedLoops;
976 NestedLoops.push_front(
ML);
978 if (NestedLoops.empty())
985 for (MachineLoop *ExaminedLoop : NestedLoops) {
986 if (ExaminedLoop->getNumBlocks() == 0 || Visited[ExaminedLoop])
989 int NumBreak = mergeLoop(ExaminedLoop);
997int R600MachineCFGStructurizer::mergeLoop(MachineLoop *LoopRep) {
998 MachineBasicBlock *LoopHeader = LoopRep->
getHeader();
1001 assert(!ExitingMBBs.
empty() &&
"Infinite Loop not supported");
1003 <<
" exiting blocks\n";);
1007 SmallPtrSet<MachineBasicBlock *, 2> ExitBlkSet(
llvm::from_range, ExitBlks);
1008 assert(ExitBlkSet.size() == 1);
1009 MachineBasicBlock *ExitBlk = *ExitBlks.
begin();
1010 assert(ExitBlk &&
"Loop has several exit block");
1016 for (MachineBasicBlock *
MBB : ExitingMBBs)
1017 mergeLoopbreakBlock(
MBB, ExitBlk);
1018 for (MachineBasicBlock *
MBB : LatchBlks)
1019 settleLoopcontBlock(
MBB, LoopHeader);
1023 Match += serialPatternMatch(LoopHeader);
1024 Match += ifPatternMatch(LoopHeader);
1025 }
while (Match > 0);
1026 mergeLooplandBlock(LoopHeader, ExitBlk);
1029 MLI->changeLoopFor(LoopHeader, ParentLoop);
1031 MLI->removeBlock(LoopHeader);
1032 Visited[LoopRep] =
true;
1036bool R600MachineCFGStructurizer::isSameloopDetachedContbreak(
1037 MachineBasicBlock *Src1MBB, MachineBasicBlock *Src2MBB) {
1039 MachineLoop *LoopRep = MLI->getLoopFor(Src1MBB);
1040 if (LoopRep&& LoopRep == MLI->getLoopFor(Src2MBB)) {
1041 MachineBasicBlock *&TheEntry = LLInfoMap[LoopRep];
1053int R600MachineCFGStructurizer::handleJumpintoIf(MachineBasicBlock *HeadMBB,
1054 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
1055 int Num = handleJumpintoIfImp(HeadMBB, TrueMBB, FalseMBB);
1057 LLVM_DEBUG(
dbgs() <<
"handleJumpintoIf swap trueBlk and FalseBlk"
1059 Num = handleJumpintoIfImp(HeadMBB, FalseMBB, TrueMBB);
1064int R600MachineCFGStructurizer::handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
1065 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
1067 MachineBasicBlock *DownBlk;
1074 <<
", numSucc=" << TrueMBB->
succ_size() <<
" false = BB"
1080 if (singlePathTo(FalseMBB, DownBlk) == SinglePath_InPath) {
1083 Num += cloneOnSideEntryTo(HeadMBB, TrueMBB, DownBlk);
1084 Num += cloneOnSideEntryTo(HeadMBB, FalseMBB, DownBlk);
1086 numClonedBlock += Num;
1087 Num += serialPatternMatch(*HeadMBB->
succ_begin());
1088 Num += serialPatternMatch(*std::next(HeadMBB->
succ_begin()));
1089 Num += ifPatternMatch(HeadMBB);
1095 DownBlk = (DownBlk->succ_size() == 1) ? (*DownBlk->succ_begin()) :
nullptr;
1102void R600MachineCFGStructurizer::showImproveSimpleJumpintoIf(
1103 MachineBasicBlock *HeadMBB, MachineBasicBlock *TrueMBB,
1104 MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB,
bool Detail) {
1106 <<
" size = " << HeadMBB->
size();
1114 dbgs() <<
", true = BB" << TrueMBB->
getNumber() <<
" size = "
1115 << TrueMBB->
size() <<
" numPred = " << TrueMBB->
pred_size();
1123 dbgs() <<
", false = BB" << FalseMBB->
getNumber() <<
" size = "
1124 << FalseMBB->
size() <<
" numPred = " << FalseMBB->
pred_size();
1132 dbgs() <<
", land = BB" << LandMBB->
getNumber() <<
" size = "
1133 << LandMBB->
size() <<
" numPred = " << LandMBB->
pred_size();
1145int R600MachineCFGStructurizer::improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
1146 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
1147 MachineBasicBlock **LandMBBPtr) {
1148 bool MigrateTrue =
false;
1149 bool MigrateFalse =
false;
1151 MachineBasicBlock *LandBlk = *LandMBBPtr;
1154 && (!FalseMBB || FalseMBB->
succ_size() <= 1));
1156 if (TrueMBB == FalseMBB)
1159 MigrateTrue = needMigrateBlock(TrueMBB);
1160 MigrateFalse = needMigrateBlock(FalseMBB);
1162 if (!MigrateTrue && !MigrateFalse)
1168 if (!MigrateTrue && TrueMBB && TrueMBB->
pred_size() > 1)
1170 if (!MigrateFalse && FalseMBB && FalseMBB->
pred_size() > 1)
1171 MigrateFalse =
true;
1174 dbgs() <<
"before improveSimpleJumpintoIf: ";
1175 showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0););
1188 const TargetRegisterClass * I32RC =
TRI->getCFGStructurizerRegClass(MVT::i32);
1189 if (!MigrateTrue || !MigrateFalse) {
1260 bool LandBlkHasOtherPred = (LandBlk->
pred_size() > 2);
1265 if (LandBlkHasOtherPred) {
1270 insertCondBranchBefore(LandBlk,
I, R600::IF_PREDICATE_SET,
1278 insertCondBranchBefore(LandBlk,
I, R600::IF_PREDICATE_SET, InitReg,
1282 migrateInstruction(TrueMBB, LandBlk,
I);
1288 insertInstrBefore(
I, R600::ELSE);
1291 migrateInstruction(FalseMBB, LandBlk,
I);
1298 if (LandBlkHasOtherPred) {
1300 insertInstrBefore(
I, R600::ENDIF);
1304 if (
MBB != TrueMBB &&
MBB != FalseMBB)
1308 dbgs() <<
"result from improveSimpleJumpintoIf: ";
1309 showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0););
1312 *LandMBBPtr = LandBlk;
1317void R600MachineCFGStructurizer::mergeSerialBlock(MachineBasicBlock *DstMBB,
1318 MachineBasicBlock *SrcMBB) {
1324 cloneSuccessorList(DstMBB, SrcMBB);
1326 removeSuccessor(SrcMBB);
1327 MLI->removeBlock(SrcMBB);
1328 retireBlock(SrcMBB);
1331void R600MachineCFGStructurizer::mergeIfthenelseBlock(MachineInstr *BranchMI,
1332 MachineBasicBlock *
MBB, MachineBasicBlock *TrueMBB,
1333 MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB) {
1338 dbgs() <<
"{ ";
if (FalseMBB) {
1340 }
dbgs() <<
" }\n ";
1341 dbgs() <<
"landBlock: ";
if (!LandMBB) {
dbgs() <<
"NULL"; }
else {
1357 insertCondBranchBefore(
I, getBranchNzeroOpcode(OldOpcode),
1365 retireBlock(TrueMBB);
1366 MLI->removeBlock(TrueMBB);
1370 insertInstrBefore(
I, R600::ELSE);
1376 retireBlock(FalseMBB);
1377 MLI->removeBlock(FalseMBB);
1379 insertInstrBefore(
I, R600::ENDIF);
1383 if (LandMBB && TrueMBB && FalseMBB)
1387void R600MachineCFGStructurizer::mergeLooplandBlock(MachineBasicBlock *DstBlk,
1388 MachineBasicBlock *LandMBB) {
1390 <<
" land = BB" << LandMBB->
getNumber() <<
"\n";);
1392 insertInstrBefore(DstBlk, R600::WHILELOOP,
DebugLoc());
1393 insertInstrEnd(DstBlk, R600::ENDLOOP,
DebugLoc());
1397void R600MachineCFGStructurizer::mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
1398 MachineBasicBlock *LandMBB) {
1400 << ExitingMBB->
getNumber() <<
" land = BB"
1402 MachineInstr *BranchMI = getLoopendBlockBranchInstr(ExitingMBB);
1403 assert(BranchMI && isCondBranch(BranchMI));
1405 MachineBasicBlock *TrueBranch = getTrueBranch(BranchMI);
1407 if (TrueBranch != LandMBB)
1408 reversePredicateSetter(
I, *
I->getParent());
1409 insertCondBranchBefore(ExitingMBB,
I, R600::IF_PREDICATE_SET, R600::PREDICATE_BIT,
DL);
1410 insertInstrBefore(
I, R600::BREAK);
1411 insertInstrBefore(
I, R600::ENDIF);
1418void R600MachineCFGStructurizer::settleLoopcontBlock(MachineBasicBlock *ContingMBB,
1419 MachineBasicBlock *ContMBB) {
1421 << ContingMBB->
getNumber() <<
", cont = BB"
1424 MachineInstr *
MI = getLoopendBlockBranchInstr(ContingMBB);
1428 MachineBasicBlock *TrueBranch = getTrueBranch(
MI);
1429 int OldOpcode =
MI->getOpcode();
1432 bool UseContinueLogical = ((&*ContingMBB->
rbegin()) ==
MI);
1434 if (!UseContinueLogical) {
1436 TrueBranch == ContMBB ? getBranchNzeroOpcode(OldOpcode) :
1437 getBranchZeroOpcode(OldOpcode);
1438 insertCondBranchBefore(
I, BranchOpcode,
DL);
1440 insertInstrEnd(ContingMBB, R600::CONTINUE,
DL);
1441 insertInstrEnd(ContingMBB, R600::ENDIF,
DL);
1444 TrueBranch == ContMBB ? getContinueNzeroOpcode(OldOpcode) :
1445 getContinueZeroOpcode(OldOpcode);
1446 insertCondBranchBefore(
I, BranchOpcode,
DL);
1449 MI->eraseFromParent();
1456 insertInstrEnd(ContingMBB, R600::CONTINUE,
1457 getLastDebugLocInBB(ContingMBB));
1461int R600MachineCFGStructurizer::cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
1462 MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB) {
1465 while (SrcMBB && SrcMBB != DstMBB) {
1468 SrcMBB = cloneBlockForPredecessor(SrcMBB, PreMBB);
1480R600MachineCFGStructurizer::cloneBlockForPredecessor(MachineBasicBlock *
MBB,
1481 MachineBasicBlock *PredMBB) {
1484 MachineBasicBlock *CloneMBB = clone(
MBB);
1485 replaceInstrUseOfBlockWith(PredMBB,
MBB, CloneMBB);
1491 cloneSuccessorList(CloneMBB,
MBB);
1493 numClonedInstr +=
MBB->
size();
1499 SHOWNEWBLK(CloneMBB,
"result of Cloned block: ");
1504void R600MachineCFGStructurizer::migrateInstruction(MachineBasicBlock *SrcMBB,
1508 MachineInstr *BranchMI = getNormalBlockBranchInstr(SrcMBB);
1510 LLVM_DEBUG(
dbgs() <<
"migrateInstruction don't see branch instr\n";);
1511 SpliceEnd = SrcMBB->
end();
1513 LLVM_DEBUG(
dbgs() <<
"migrateInstruction see branch instr: " << *BranchMI);
1514 SpliceEnd = BranchMI;
1516 LLVM_DEBUG(
dbgs() <<
"migrateInstruction before splice dstSize = "
1517 << DstMBB->
size() <<
"srcSize = " << SrcMBB->
size()
1523 LLVM_DEBUG(
dbgs() <<
"migrateInstruction after splice dstSize = "
1524 << DstMBB->
size() <<
"srcSize = " << SrcMBB->
size()
1529R600MachineCFGStructurizer::normalizeInfiniteLoopExit(MachineLoop* LoopRep) {
1530 MachineBasicBlock *LoopHeader = LoopRep->
getHeader();
1531 MachineBasicBlock *LoopLatch = LoopRep->
getLoopLatch();
1533 if (!LoopHeader || !LoopLatch)
1535 MachineInstr *BranchMI = getLoopendBlockBranchInstr(LoopLatch);
1537 if (!BranchMI || !isUncondBranch(BranchMI))
1542 SHOWNEWBLK(DummyExitBlk,
"DummyExitBlock to normalize infiniteLoop: ");
1543 LLVM_DEBUG(
dbgs() <<
"Old branch instr: " << *BranchMI <<
"\n";);
1545 Ctx.
emitError(
"Extra register needed to handle CFG");
1549void R600MachineCFGStructurizer::removeUnconditionalBranch(MachineBasicBlock *
MBB) {
1550 MachineInstr *BranchMI;
1554 while ((BranchMI = getLoopendBlockBranchInstr(
MBB))
1555 && isUncondBranch(BranchMI)) {
1556 LLVM_DEBUG(
dbgs() <<
"Removing uncond branch instr: " << *BranchMI);
1561void R600MachineCFGStructurizer::removeRedundantConditionalBranch(
1562 MachineBasicBlock *
MBB) {
1570 MachineInstr *BranchMI = getNormalBlockBranchInstr(
MBB);
1571 assert(BranchMI && isCondBranch(BranchMI));
1572 LLVM_DEBUG(
dbgs() <<
"Removing unneeded cond branch instr: " << *BranchMI);
1574 SHOWNEWBLK(MBB1,
"Removing redundant successor");
1578void R600MachineCFGStructurizer::addDummyExitBlock(
1579 SmallVectorImpl<MachineBasicBlock*> &RetMBB) {
1582 insertInstrEnd(DummyExitBlk, R600::RETURN);
1584 for (MachineBasicBlock *
MBB : RetMBB) {
1585 if (MachineInstr *
MI = getReturnInstr(
MBB))
1586 MI->eraseFromParent();
1589 <<
" successors\n";);
1591 SHOWNEWBLK(DummyExitBlk,
"DummyExitBlock: ");
1594void R600MachineCFGStructurizer::removeSuccessor(MachineBasicBlock *
MBB) {
1599void R600MachineCFGStructurizer::recordSccnum(MachineBasicBlock *
MBB,
1601 BlockInformation *&srcBlkInfo = BlockInfoMap[
MBB];
1603 srcBlkInfo =
new BlockInformation();
1604 srcBlkInfo->SccNum = SccNum;
1607void R600MachineCFGStructurizer::retireBlock(MachineBasicBlock *
MBB) {
1610 BlockInformation *&SrcBlkInfo = BlockInfoMap[
MBB];
1613 SrcBlkInfo =
new BlockInformation();
1615 SrcBlkInfo->IsRetired =
true;
1620 "AMDGPU CFG Structurizer",
false,
false)
1628 return new R600MachineCFGStructurizer();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Unify divergent function exit nodes
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
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)
SmallVector< MachineBasicBlock *, 4 > MBBVector
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)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
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.
LLVM_ABI void emitError(const Instruction *I, 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
LLVM_ABI void replaceSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New)
Replace successor OLD with NEW and update probability info.
LLVM_ABI 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
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
SmallVectorImpl< MachineBasicBlock * >::iterator succ_iterator
LLVM_ABI void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
LLVM_ABI void print(raw_ostream &OS, const SlotIndexes *=nullptr, bool IsStandalone=true) const
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
reverse_iterator rbegin()
LLVM_ABI 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 '...
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
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.
void dump() const
dump - Print the current MachineFunction to cerr, useful for debugger use.
void push_back(MachineBasicBlock *MBB)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
void viewCFG() const
viewCFG - This function is meant for use from the debugger.
const MachineFunctionProperties & getProperties() const
Get the function properties.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
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.
LLVM_ABI 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.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
typename SuperClass::const_iterator const_iterator
void push_back(const T &Elt)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
constexpr from_range_t from_range
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
iterator_range< typename GraphTraits< Inverse< GraphType > >::ChildIteratorType > inverse_children(const typename GraphTraits< GraphType >::NodeRef &G)
FunctionAddr VTableAddr Next
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.
static nodes_iterator nodes_begin(MachineFunction *F)