181ad6265SDimitry Andric //===- R600MachineCFGStructurizer.cpp - CFG Structurizer ------------------===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //==-----------------------------------------------------------------------===//
881ad6265SDimitry Andric
981ad6265SDimitry Andric #include "MCTargetDesc/R600MCTargetDesc.h"
1081ad6265SDimitry Andric #include "R600.h"
1181ad6265SDimitry Andric #include "R600RegisterInfo.h"
1281ad6265SDimitry Andric #include "R600Subtarget.h"
1381ad6265SDimitry Andric #include "llvm/ADT/DepthFirstIterator.h"
1481ad6265SDimitry Andric #include "llvm/ADT/SCCIterator.h"
1581ad6265SDimitry Andric #include "llvm/ADT/Statistic.h"
1681ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
1781ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
1881ad6265SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h"
1981ad6265SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
2081ad6265SDimitry Andric #include "llvm/CodeGen/MachinePostDominators.h"
2181ad6265SDimitry Andric #include "llvm/InitializePasses.h"
2281ad6265SDimitry Andric
2381ad6265SDimitry Andric using namespace llvm;
2481ad6265SDimitry Andric
2581ad6265SDimitry Andric #define DEBUG_TYPE "structcfg"
2681ad6265SDimitry Andric
27*0fca6ea1SDimitry Andric enum { DEFAULT_VEC_SLOTS = 8 };
2881ad6265SDimitry Andric
2981ad6265SDimitry Andric // TODO: move-begin.
3081ad6265SDimitry Andric
3181ad6265SDimitry Andric //===----------------------------------------------------------------------===//
3281ad6265SDimitry Andric //
3381ad6265SDimitry Andric // Statistics for CFGStructurizer.
3481ad6265SDimitry Andric //
3581ad6265SDimitry Andric //===----------------------------------------------------------------------===//
3681ad6265SDimitry Andric
3781ad6265SDimitry Andric STATISTIC(numSerialPatternMatch, "CFGStructurizer number of serial pattern "
3881ad6265SDimitry Andric "matched");
3981ad6265SDimitry Andric STATISTIC(numIfPatternMatch, "CFGStructurizer number of if pattern "
4081ad6265SDimitry Andric "matched");
4181ad6265SDimitry Andric STATISTIC(numClonedBlock, "CFGStructurizer cloned blocks");
4281ad6265SDimitry Andric STATISTIC(numClonedInstr, "CFGStructurizer cloned instructions");
4381ad6265SDimitry Andric
4481ad6265SDimitry Andric namespace llvm {
4581ad6265SDimitry Andric
4681ad6265SDimitry Andric void initializeR600MachineCFGStructurizerPass(PassRegistry &);
4781ad6265SDimitry Andric
4881ad6265SDimitry Andric } // end namespace llvm
4981ad6265SDimitry Andric
5081ad6265SDimitry Andric namespace {
5181ad6265SDimitry Andric
5281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
5381ad6265SDimitry Andric //
5481ad6265SDimitry Andric // Miscellaneous utility for CFGStructurizer.
5581ad6265SDimitry Andric //
5681ad6265SDimitry Andric //===----------------------------------------------------------------------===//
5781ad6265SDimitry Andric
5881ad6265SDimitry Andric #define SHOWNEWINSTR(i) LLVM_DEBUG(dbgs() << "New instr: " << *i << "\n");
5981ad6265SDimitry Andric
6081ad6265SDimitry Andric #define SHOWNEWBLK(b, msg) \
6181ad6265SDimitry Andric LLVM_DEBUG(dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
6281ad6265SDimitry Andric dbgs() << "\n";);
6381ad6265SDimitry Andric
6481ad6265SDimitry Andric #define SHOWBLK_DETAIL(b, msg) \
6581ad6265SDimitry Andric LLVM_DEBUG(if (b) { \
6681ad6265SDimitry Andric dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
6781ad6265SDimitry Andric b->print(dbgs()); \
6881ad6265SDimitry Andric dbgs() << "\n"; \
6981ad6265SDimitry Andric });
7081ad6265SDimitry Andric
7181ad6265SDimitry Andric #define INVALIDSCCNUM -1
7281ad6265SDimitry Andric
7381ad6265SDimitry Andric //===----------------------------------------------------------------------===//
7481ad6265SDimitry Andric //
7581ad6265SDimitry Andric // supporting data structure for CFGStructurizer
7681ad6265SDimitry Andric //
7781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
7881ad6265SDimitry Andric
7981ad6265SDimitry Andric class BlockInformation {
8081ad6265SDimitry Andric public:
8181ad6265SDimitry Andric bool IsRetired = false;
8281ad6265SDimitry Andric int SccNum = INVALIDSCCNUM;
8381ad6265SDimitry Andric
8481ad6265SDimitry Andric BlockInformation() = default;
8581ad6265SDimitry Andric };
8681ad6265SDimitry Andric
8781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
8881ad6265SDimitry Andric //
8981ad6265SDimitry Andric // CFGStructurizer
9081ad6265SDimitry Andric //
9181ad6265SDimitry Andric //===----------------------------------------------------------------------===//
9281ad6265SDimitry Andric
9381ad6265SDimitry Andric class R600MachineCFGStructurizer : public MachineFunctionPass {
9481ad6265SDimitry Andric public:
9581ad6265SDimitry Andric using MBBVector = SmallVector<MachineBasicBlock *, 32>;
9681ad6265SDimitry Andric using MBBInfoMap = std::map<MachineBasicBlock *, BlockInformation *>;
9781ad6265SDimitry Andric using LoopLandInfoMap = std::map<MachineLoop *, MachineBasicBlock *>;
9881ad6265SDimitry Andric
9981ad6265SDimitry Andric enum PathToKind {
10081ad6265SDimitry Andric Not_SinglePath = 0,
10181ad6265SDimitry Andric SinglePath_InPath = 1,
10281ad6265SDimitry Andric SinglePath_NotInPath = 2
10381ad6265SDimitry Andric };
10481ad6265SDimitry Andric
10581ad6265SDimitry Andric static char ID;
10681ad6265SDimitry Andric
R600MachineCFGStructurizer()10781ad6265SDimitry Andric R600MachineCFGStructurizer() : MachineFunctionPass(ID) {
10881ad6265SDimitry Andric initializeR600MachineCFGStructurizerPass(*PassRegistry::getPassRegistry());
10981ad6265SDimitry Andric }
11081ad6265SDimitry Andric
getPassName() const11181ad6265SDimitry Andric StringRef getPassName() const override {
11281ad6265SDimitry Andric return "AMDGPU Control Flow Graph structurizer Pass";
11381ad6265SDimitry Andric }
11481ad6265SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const11581ad6265SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
116*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>();
117*0fca6ea1SDimitry Andric AU.addRequired<MachinePostDominatorTreeWrapperPass>();
118*0fca6ea1SDimitry Andric AU.addRequired<MachineLoopInfoWrapperPass>();
11981ad6265SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
12081ad6265SDimitry Andric }
12181ad6265SDimitry Andric
12281ad6265SDimitry Andric /// Perform the CFG structurization
12381ad6265SDimitry Andric bool run();
12481ad6265SDimitry Andric
12581ad6265SDimitry Andric /// Perform the CFG preparation
12681ad6265SDimitry Andric /// This step will remove every unconditionnal/dead jump instructions and make
12781ad6265SDimitry Andric /// sure all loops have an exit block
12881ad6265SDimitry Andric bool prepare();
12981ad6265SDimitry Andric
runOnMachineFunction(MachineFunction & MF)13081ad6265SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override {
13181ad6265SDimitry Andric // FIXME: This pass causes verification failures.
13281ad6265SDimitry Andric MF.getProperties().set(
13381ad6265SDimitry Andric MachineFunctionProperties::Property::FailsVerification);
13481ad6265SDimitry Andric
13581ad6265SDimitry Andric TII = MF.getSubtarget<R600Subtarget>().getInstrInfo();
13681ad6265SDimitry Andric TRI = &TII->getRegisterInfo();
13781ad6265SDimitry Andric LLVM_DEBUG(MF.dump(););
13881ad6265SDimitry Andric OrderedBlks.clear();
13981ad6265SDimitry Andric Visited.clear();
14081ad6265SDimitry Andric FuncRep = &MF;
141*0fca6ea1SDimitry Andric MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
14281ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "LoopInfo:\n"; PrintLoopinfo(*MLI););
143*0fca6ea1SDimitry Andric MDT = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
144*0fca6ea1SDimitry Andric LLVM_DEBUG(MDT->print(dbgs()););
145*0fca6ea1SDimitry Andric PDT = &getAnalysis<MachinePostDominatorTreeWrapperPass>().getPostDomTree();
14681ad6265SDimitry Andric LLVM_DEBUG(PDT->print(dbgs()););
14781ad6265SDimitry Andric prepare();
14881ad6265SDimitry Andric run();
14981ad6265SDimitry Andric LLVM_DEBUG(MF.dump(););
15081ad6265SDimitry Andric return true;
15181ad6265SDimitry Andric }
15281ad6265SDimitry Andric
15381ad6265SDimitry Andric protected:
15481ad6265SDimitry Andric MachineDominatorTree *MDT;
15581ad6265SDimitry Andric MachinePostDominatorTree *PDT;
15681ad6265SDimitry Andric MachineLoopInfo *MLI;
15781ad6265SDimitry Andric const R600InstrInfo *TII = nullptr;
15881ad6265SDimitry Andric const R600RegisterInfo *TRI = nullptr;
15981ad6265SDimitry Andric
16081ad6265SDimitry Andric // PRINT FUNCTIONS
16181ad6265SDimitry Andric /// Print the ordered Blocks.
printOrderedBlocks() const16281ad6265SDimitry Andric void printOrderedBlocks() const {
16381ad6265SDimitry Andric size_t i = 0;
16481ad6265SDimitry Andric for (MBBVector::const_iterator iterBlk = OrderedBlks.begin(),
16581ad6265SDimitry Andric iterBlkEnd = OrderedBlks.end(); iterBlk != iterBlkEnd; ++iterBlk, ++i) {
16681ad6265SDimitry Andric dbgs() << "BB" << (*iterBlk)->getNumber();
16781ad6265SDimitry Andric dbgs() << "(" << getSCCNum(*iterBlk) << "," << (*iterBlk)->size() << ")";
16881ad6265SDimitry Andric if (i != 0 && i % 10 == 0) {
16981ad6265SDimitry Andric dbgs() << "\n";
17081ad6265SDimitry Andric } else {
17181ad6265SDimitry Andric dbgs() << " ";
17281ad6265SDimitry Andric }
17381ad6265SDimitry Andric }
17481ad6265SDimitry Andric }
17581ad6265SDimitry Andric
PrintLoopinfo(const MachineLoopInfo & LoopInfo)17681ad6265SDimitry Andric static void PrintLoopinfo(const MachineLoopInfo &LoopInfo) {
17781ad6265SDimitry Andric for (const MachineLoop *L : LoopInfo)
17881ad6265SDimitry Andric L->print(dbgs());
17981ad6265SDimitry Andric }
18081ad6265SDimitry Andric
18181ad6265SDimitry Andric // UTILITY FUNCTIONS
18281ad6265SDimitry Andric int getSCCNum(MachineBasicBlock *MBB) const;
18381ad6265SDimitry Andric MachineBasicBlock *getLoopLandInfo(MachineLoop *LoopRep) const;
18481ad6265SDimitry Andric bool hasBackEdge(MachineBasicBlock *MBB) const;
18581ad6265SDimitry Andric bool isRetiredBlock(MachineBasicBlock *MBB) const;
18681ad6265SDimitry Andric bool isActiveLoophead(MachineBasicBlock *MBB) const;
18781ad6265SDimitry Andric PathToKind singlePathTo(MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
18881ad6265SDimitry Andric bool AllowSideEntry = true) const;
18981ad6265SDimitry Andric int countActiveBlock(MBBVector::const_iterator It,
19081ad6265SDimitry Andric MBBVector::const_iterator E) const;
19181ad6265SDimitry Andric bool needMigrateBlock(MachineBasicBlock *MBB) const;
19281ad6265SDimitry Andric
19381ad6265SDimitry Andric // Utility Functions
19481ad6265SDimitry Andric void reversePredicateSetter(MachineBasicBlock::iterator I,
19581ad6265SDimitry Andric MachineBasicBlock &MBB);
19681ad6265SDimitry Andric /// Compute the reversed DFS post order of Blocks
19781ad6265SDimitry Andric void orderBlocks(MachineFunction *MF);
19881ad6265SDimitry Andric
19981ad6265SDimitry Andric // Function originally from CFGStructTraits
20081ad6265SDimitry Andric void insertInstrEnd(MachineBasicBlock *MBB, int NewOpcode,
20181ad6265SDimitry Andric const DebugLoc &DL = DebugLoc());
20281ad6265SDimitry Andric MachineInstr *insertInstrBefore(MachineBasicBlock *MBB, int NewOpcode,
20381ad6265SDimitry Andric const DebugLoc &DL = DebugLoc());
20481ad6265SDimitry Andric MachineInstr *insertInstrBefore(MachineBasicBlock::iterator I, int NewOpcode);
20581ad6265SDimitry Andric void insertCondBranchBefore(MachineBasicBlock::iterator I, int NewOpcode,
20681ad6265SDimitry Andric const DebugLoc &DL);
20781ad6265SDimitry Andric void insertCondBranchBefore(MachineBasicBlock *MBB,
20881ad6265SDimitry Andric MachineBasicBlock::iterator I, int NewOpcode,
20981ad6265SDimitry Andric int RegNum, const DebugLoc &DL);
21081ad6265SDimitry Andric
21181ad6265SDimitry Andric static int getBranchNzeroOpcode(int OldOpcode);
21281ad6265SDimitry Andric static int getBranchZeroOpcode(int OldOpcode);
21381ad6265SDimitry Andric static int getContinueNzeroOpcode(int OldOpcode);
21481ad6265SDimitry Andric static int getContinueZeroOpcode(int OldOpcode);
21581ad6265SDimitry Andric static MachineBasicBlock *getTrueBranch(MachineInstr *MI);
21681ad6265SDimitry Andric static void setTrueBranch(MachineInstr *MI, MachineBasicBlock *MBB);
21781ad6265SDimitry Andric static MachineBasicBlock *getFalseBranch(MachineBasicBlock *MBB,
21881ad6265SDimitry Andric MachineInstr *MI);
21981ad6265SDimitry Andric static bool isCondBranch(MachineInstr *MI);
22081ad6265SDimitry Andric static bool isUncondBranch(MachineInstr *MI);
22181ad6265SDimitry Andric static DebugLoc getLastDebugLocInBB(MachineBasicBlock *MBB);
22281ad6265SDimitry Andric static MachineInstr *getNormalBlockBranchInstr(MachineBasicBlock *MBB);
22381ad6265SDimitry Andric
22481ad6265SDimitry Andric /// The correct naming for this is getPossibleLoopendBlockBranchInstr.
22581ad6265SDimitry Andric ///
22681ad6265SDimitry Andric /// BB with backward-edge could have move instructions after the branch
22781ad6265SDimitry Andric /// instruction. Such move instruction "belong to" the loop backward-edge.
22881ad6265SDimitry Andric MachineInstr *getLoopendBlockBranchInstr(MachineBasicBlock *MBB);
22981ad6265SDimitry Andric
23081ad6265SDimitry Andric static MachineInstr *getReturnInstr(MachineBasicBlock *MBB);
23181ad6265SDimitry Andric static bool isReturnBlock(MachineBasicBlock *MBB);
23281ad6265SDimitry Andric static void cloneSuccessorList(MachineBasicBlock *DstMBB,
23381ad6265SDimitry Andric MachineBasicBlock *SrcMBB);
23481ad6265SDimitry Andric static MachineBasicBlock *clone(MachineBasicBlock *MBB);
23581ad6265SDimitry Andric
23681ad6265SDimitry Andric /// MachineBasicBlock::ReplaceUsesOfBlockWith doesn't serve the purpose
23781ad6265SDimitry Andric /// because the AMDGPU instruction is not recognized as terminator fix this
23881ad6265SDimitry Andric /// and retire this routine
23981ad6265SDimitry Andric void replaceInstrUseOfBlockWith(MachineBasicBlock *SrcMBB,
24081ad6265SDimitry Andric MachineBasicBlock *OldMBB, MachineBasicBlock *NewBlk);
24181ad6265SDimitry Andric
24281ad6265SDimitry Andric static void wrapup(MachineBasicBlock *MBB);
24381ad6265SDimitry Andric
24481ad6265SDimitry Andric int patternMatch(MachineBasicBlock *MBB);
24581ad6265SDimitry Andric int patternMatchGroup(MachineBasicBlock *MBB);
24681ad6265SDimitry Andric int serialPatternMatch(MachineBasicBlock *MBB);
24781ad6265SDimitry Andric int ifPatternMatch(MachineBasicBlock *MBB);
24881ad6265SDimitry Andric int loopendPatternMatch();
24981ad6265SDimitry Andric int mergeLoop(MachineLoop *LoopRep);
25081ad6265SDimitry Andric
25181ad6265SDimitry Andric /// return true iff src1Blk->succ_empty() && src1Blk and src2Blk are in
25281ad6265SDimitry Andric /// the same loop with LoopLandInfo without explicitly keeping track of
25381ad6265SDimitry Andric /// loopContBlks and loopBreakBlks, this is a method to get the information.
25481ad6265SDimitry Andric bool isSameloopDetachedContbreak(MachineBasicBlock *Src1MBB,
25581ad6265SDimitry Andric MachineBasicBlock *Src2MBB);
25681ad6265SDimitry Andric int handleJumpintoIf(MachineBasicBlock *HeadMBB,
25781ad6265SDimitry Andric MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
25881ad6265SDimitry Andric int handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
25981ad6265SDimitry Andric MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
26081ad6265SDimitry Andric int improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
26181ad6265SDimitry Andric MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
26281ad6265SDimitry Andric MachineBasicBlock **LandMBBPtr);
26381ad6265SDimitry Andric void showImproveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
26481ad6265SDimitry Andric MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
26581ad6265SDimitry Andric MachineBasicBlock *LandMBB, bool Detail = false);
26681ad6265SDimitry Andric int cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
26781ad6265SDimitry Andric MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB);
26881ad6265SDimitry Andric void mergeSerialBlock(MachineBasicBlock *DstMBB,
26981ad6265SDimitry Andric MachineBasicBlock *SrcMBB);
27081ad6265SDimitry Andric
27181ad6265SDimitry Andric void mergeIfthenelseBlock(MachineInstr *BranchMI,
27281ad6265SDimitry Andric MachineBasicBlock *MBB, MachineBasicBlock *TrueMBB,
27381ad6265SDimitry Andric MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB);
27481ad6265SDimitry Andric void mergeLooplandBlock(MachineBasicBlock *DstMBB,
27581ad6265SDimitry Andric MachineBasicBlock *LandMBB);
27681ad6265SDimitry Andric void mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
27781ad6265SDimitry Andric MachineBasicBlock *LandMBB);
27881ad6265SDimitry Andric void settleLoopcontBlock(MachineBasicBlock *ContingMBB,
27981ad6265SDimitry Andric MachineBasicBlock *ContMBB);
28081ad6265SDimitry Andric
28181ad6265SDimitry Andric /// normalizeInfiniteLoopExit change
28281ad6265SDimitry Andric /// B1:
28381ad6265SDimitry Andric /// uncond_br LoopHeader
28481ad6265SDimitry Andric ///
28581ad6265SDimitry Andric /// to
28681ad6265SDimitry Andric /// B1:
28781ad6265SDimitry Andric /// cond_br 1 LoopHeader dummyExit
28881ad6265SDimitry Andric /// and return the newly added dummy exit block
28981ad6265SDimitry Andric MachineBasicBlock *normalizeInfiniteLoopExit(MachineLoop *LoopRep);
29081ad6265SDimitry Andric void removeUnconditionalBranch(MachineBasicBlock *MBB);
29181ad6265SDimitry Andric
29281ad6265SDimitry Andric /// Remove duplicate branches instructions in a block.
29381ad6265SDimitry Andric /// For instance
29481ad6265SDimitry Andric /// B0:
29581ad6265SDimitry Andric /// cond_br X B1 B2
29681ad6265SDimitry Andric /// cond_br X B1 B2
29781ad6265SDimitry Andric /// is transformed to
29881ad6265SDimitry Andric /// B0:
29981ad6265SDimitry Andric /// cond_br X B1 B2
30081ad6265SDimitry Andric void removeRedundantConditionalBranch(MachineBasicBlock *MBB);
30181ad6265SDimitry Andric
30281ad6265SDimitry Andric void addDummyExitBlock(SmallVectorImpl<MachineBasicBlock *> &RetMBB);
30381ad6265SDimitry Andric void removeSuccessor(MachineBasicBlock *MBB);
30481ad6265SDimitry Andric MachineBasicBlock *cloneBlockForPredecessor(MachineBasicBlock *MBB,
30581ad6265SDimitry Andric MachineBasicBlock *PredMBB);
30681ad6265SDimitry Andric void migrateInstruction(MachineBasicBlock *SrcMBB,
30781ad6265SDimitry Andric MachineBasicBlock *DstMBB, MachineBasicBlock::iterator I);
30881ad6265SDimitry Andric void recordSccnum(MachineBasicBlock *MBB, int SCCNum);
30981ad6265SDimitry Andric void retireBlock(MachineBasicBlock *MBB);
31081ad6265SDimitry Andric
31181ad6265SDimitry Andric private:
31281ad6265SDimitry Andric MBBInfoMap BlockInfoMap;
31381ad6265SDimitry Andric LoopLandInfoMap LLInfoMap;
31481ad6265SDimitry Andric std::map<MachineLoop *, bool> Visited;
31581ad6265SDimitry Andric MachineFunction *FuncRep;
31681ad6265SDimitry Andric SmallVector<MachineBasicBlock *, DEFAULT_VEC_SLOTS> OrderedBlks;
31781ad6265SDimitry Andric };
31881ad6265SDimitry Andric
31981ad6265SDimitry Andric } // end anonymous namespace
32081ad6265SDimitry Andric
32181ad6265SDimitry Andric char R600MachineCFGStructurizer::ID = 0;
32281ad6265SDimitry Andric
getSCCNum(MachineBasicBlock * MBB) const32381ad6265SDimitry Andric int R600MachineCFGStructurizer::getSCCNum(MachineBasicBlock *MBB) const {
32481ad6265SDimitry Andric MBBInfoMap::const_iterator It = BlockInfoMap.find(MBB);
32581ad6265SDimitry Andric if (It == BlockInfoMap.end())
32681ad6265SDimitry Andric return INVALIDSCCNUM;
32781ad6265SDimitry Andric return (*It).second->SccNum;
32881ad6265SDimitry Andric }
32981ad6265SDimitry Andric
getLoopLandInfo(MachineLoop * LoopRep) const33081ad6265SDimitry Andric MachineBasicBlock *R600MachineCFGStructurizer::getLoopLandInfo(MachineLoop *LoopRep)
33181ad6265SDimitry Andric const {
33281ad6265SDimitry Andric LoopLandInfoMap::const_iterator It = LLInfoMap.find(LoopRep);
33381ad6265SDimitry Andric if (It == LLInfoMap.end())
33481ad6265SDimitry Andric return nullptr;
33581ad6265SDimitry Andric return (*It).second;
33681ad6265SDimitry Andric }
33781ad6265SDimitry Andric
hasBackEdge(MachineBasicBlock * MBB) const33881ad6265SDimitry Andric bool R600MachineCFGStructurizer::hasBackEdge(MachineBasicBlock *MBB) const {
33981ad6265SDimitry Andric MachineLoop *LoopRep = MLI->getLoopFor(MBB);
34081ad6265SDimitry Andric if (!LoopRep)
34181ad6265SDimitry Andric return false;
34281ad6265SDimitry Andric MachineBasicBlock *LoopHeader = LoopRep->getHeader();
34381ad6265SDimitry Andric return MBB->isSuccessor(LoopHeader);
34481ad6265SDimitry Andric }
34581ad6265SDimitry Andric
isRetiredBlock(MachineBasicBlock * MBB) const34681ad6265SDimitry Andric bool R600MachineCFGStructurizer::isRetiredBlock(MachineBasicBlock *MBB) const {
34781ad6265SDimitry Andric MBBInfoMap::const_iterator It = BlockInfoMap.find(MBB);
34881ad6265SDimitry Andric if (It == BlockInfoMap.end())
34981ad6265SDimitry Andric return false;
35081ad6265SDimitry Andric return (*It).second->IsRetired;
35181ad6265SDimitry Andric }
35281ad6265SDimitry Andric
isActiveLoophead(MachineBasicBlock * MBB) const35381ad6265SDimitry Andric bool R600MachineCFGStructurizer::isActiveLoophead(MachineBasicBlock *MBB) const {
35481ad6265SDimitry Andric MachineLoop *LoopRep = MLI->getLoopFor(MBB);
35581ad6265SDimitry Andric while (LoopRep && LoopRep->getHeader() == MBB) {
35681ad6265SDimitry Andric MachineBasicBlock *LoopLand = getLoopLandInfo(LoopRep);
35781ad6265SDimitry Andric if(!LoopLand)
35881ad6265SDimitry Andric return true;
35981ad6265SDimitry Andric if (!isRetiredBlock(LoopLand))
36081ad6265SDimitry Andric return true;
36181ad6265SDimitry Andric LoopRep = LoopRep->getParentLoop();
36281ad6265SDimitry Andric }
36381ad6265SDimitry Andric return false;
36481ad6265SDimitry Andric }
36581ad6265SDimitry Andric
singlePathTo(MachineBasicBlock * SrcMBB,MachineBasicBlock * DstMBB,bool AllowSideEntry) const36681ad6265SDimitry Andric R600MachineCFGStructurizer::PathToKind R600MachineCFGStructurizer::singlePathTo(
36781ad6265SDimitry Andric MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
36881ad6265SDimitry Andric bool AllowSideEntry) const {
36981ad6265SDimitry Andric assert(DstMBB);
37081ad6265SDimitry Andric if (SrcMBB == DstMBB)
37181ad6265SDimitry Andric return SinglePath_InPath;
37281ad6265SDimitry Andric while (SrcMBB && SrcMBB->succ_size() == 1) {
37381ad6265SDimitry Andric SrcMBB = *SrcMBB->succ_begin();
37481ad6265SDimitry Andric if (SrcMBB == DstMBB)
37581ad6265SDimitry Andric return SinglePath_InPath;
37681ad6265SDimitry Andric if (!AllowSideEntry && SrcMBB->pred_size() > 1)
37781ad6265SDimitry Andric return Not_SinglePath;
37881ad6265SDimitry Andric }
37981ad6265SDimitry Andric if (SrcMBB && SrcMBB->succ_size()==0)
38081ad6265SDimitry Andric return SinglePath_NotInPath;
38181ad6265SDimitry Andric return Not_SinglePath;
38281ad6265SDimitry Andric }
38381ad6265SDimitry Andric
countActiveBlock(MBBVector::const_iterator It,MBBVector::const_iterator E) const38481ad6265SDimitry Andric int R600MachineCFGStructurizer::countActiveBlock(MBBVector::const_iterator It,
38581ad6265SDimitry Andric MBBVector::const_iterator E) const {
38681ad6265SDimitry Andric int Count = 0;
38781ad6265SDimitry Andric while (It != E) {
38881ad6265SDimitry Andric if (!isRetiredBlock(*It))
38981ad6265SDimitry Andric ++Count;
39081ad6265SDimitry Andric ++It;
39181ad6265SDimitry Andric }
39281ad6265SDimitry Andric return Count;
39381ad6265SDimitry Andric }
39481ad6265SDimitry Andric
needMigrateBlock(MachineBasicBlock * MBB) const39581ad6265SDimitry Andric bool R600MachineCFGStructurizer::needMigrateBlock(MachineBasicBlock *MBB) const {
39681ad6265SDimitry Andric unsigned BlockSizeThreshold = 30;
39781ad6265SDimitry Andric unsigned CloneInstrThreshold = 100;
39881ad6265SDimitry Andric bool MultiplePreds = MBB && (MBB->pred_size() > 1);
39981ad6265SDimitry Andric
40081ad6265SDimitry Andric if(!MultiplePreds)
40181ad6265SDimitry Andric return false;
40281ad6265SDimitry Andric unsigned BlkSize = MBB->size();
40381ad6265SDimitry Andric return ((BlkSize > BlockSizeThreshold) &&
40481ad6265SDimitry Andric (BlkSize * (MBB->pred_size() - 1) > CloneInstrThreshold));
40581ad6265SDimitry Andric }
40681ad6265SDimitry Andric
reversePredicateSetter(MachineBasicBlock::iterator I,MachineBasicBlock & MBB)40781ad6265SDimitry Andric void R600MachineCFGStructurizer::reversePredicateSetter(
40881ad6265SDimitry Andric MachineBasicBlock::iterator I, MachineBasicBlock &MBB) {
40981ad6265SDimitry Andric assert(I.isValid() && "Expected valid iterator");
41081ad6265SDimitry Andric for (;; --I) {
41181ad6265SDimitry Andric if (I == MBB.end())
41281ad6265SDimitry Andric continue;
41381ad6265SDimitry Andric if (I->getOpcode() == R600::PRED_X) {
41481ad6265SDimitry Andric switch (I->getOperand(2).getImm()) {
41581ad6265SDimitry Andric case R600::PRED_SETE_INT:
41681ad6265SDimitry Andric I->getOperand(2).setImm(R600::PRED_SETNE_INT);
41781ad6265SDimitry Andric return;
41881ad6265SDimitry Andric case R600::PRED_SETNE_INT:
41981ad6265SDimitry Andric I->getOperand(2).setImm(R600::PRED_SETE_INT);
42081ad6265SDimitry Andric return;
42181ad6265SDimitry Andric case R600::PRED_SETE:
42281ad6265SDimitry Andric I->getOperand(2).setImm(R600::PRED_SETNE);
42381ad6265SDimitry Andric return;
42481ad6265SDimitry Andric case R600::PRED_SETNE:
42581ad6265SDimitry Andric I->getOperand(2).setImm(R600::PRED_SETE);
42681ad6265SDimitry Andric return;
42781ad6265SDimitry Andric default:
42881ad6265SDimitry Andric llvm_unreachable("PRED_X Opcode invalid!");
42981ad6265SDimitry Andric }
43081ad6265SDimitry Andric }
43181ad6265SDimitry Andric }
43281ad6265SDimitry Andric }
43381ad6265SDimitry Andric
insertInstrEnd(MachineBasicBlock * MBB,int NewOpcode,const DebugLoc & DL)43481ad6265SDimitry Andric void R600MachineCFGStructurizer::insertInstrEnd(MachineBasicBlock *MBB,
43581ad6265SDimitry Andric int NewOpcode, const DebugLoc &DL) {
43681ad6265SDimitry Andric MachineInstr *MI =
43781ad6265SDimitry Andric MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DL);
43881ad6265SDimitry Andric MBB->push_back(MI);
43981ad6265SDimitry Andric //assume the instruction doesn't take any reg operand ...
44081ad6265SDimitry Andric SHOWNEWINSTR(MI);
44181ad6265SDimitry Andric }
44281ad6265SDimitry Andric
insertInstrBefore(MachineBasicBlock * MBB,int NewOpcode,const DebugLoc & DL)44381ad6265SDimitry Andric MachineInstr *R600MachineCFGStructurizer::insertInstrBefore(MachineBasicBlock *MBB,
44481ad6265SDimitry Andric int NewOpcode,
44581ad6265SDimitry Andric const DebugLoc &DL) {
44681ad6265SDimitry Andric MachineInstr *MI =
44781ad6265SDimitry Andric MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DL);
44881ad6265SDimitry Andric if (!MBB->empty())
44981ad6265SDimitry Andric MBB->insert(MBB->begin(), MI);
45081ad6265SDimitry Andric else
45181ad6265SDimitry Andric MBB->push_back(MI);
45281ad6265SDimitry Andric SHOWNEWINSTR(MI);
45381ad6265SDimitry Andric return MI;
45481ad6265SDimitry Andric }
45581ad6265SDimitry Andric
insertInstrBefore(MachineBasicBlock::iterator I,int NewOpcode)45681ad6265SDimitry Andric MachineInstr *R600MachineCFGStructurizer::insertInstrBefore(
45781ad6265SDimitry Andric MachineBasicBlock::iterator I, int NewOpcode) {
45881ad6265SDimitry Andric MachineInstr *OldMI = &(*I);
45981ad6265SDimitry Andric MachineBasicBlock *MBB = OldMI->getParent();
46081ad6265SDimitry Andric MachineInstr *NewMBB =
46181ad6265SDimitry Andric MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DebugLoc());
46281ad6265SDimitry Andric MBB->insert(I, NewMBB);
46381ad6265SDimitry Andric //assume the instruction doesn't take any reg operand ...
46481ad6265SDimitry Andric SHOWNEWINSTR(NewMBB);
46581ad6265SDimitry Andric return NewMBB;
46681ad6265SDimitry Andric }
46781ad6265SDimitry Andric
insertCondBranchBefore(MachineBasicBlock::iterator I,int NewOpcode,const DebugLoc & DL)46881ad6265SDimitry Andric void R600MachineCFGStructurizer::insertCondBranchBefore(
46981ad6265SDimitry Andric MachineBasicBlock::iterator I, int NewOpcode, const DebugLoc &DL) {
47081ad6265SDimitry Andric MachineInstr *OldMI = &(*I);
47181ad6265SDimitry Andric MachineBasicBlock *MBB = OldMI->getParent();
47281ad6265SDimitry Andric MachineFunction *MF = MBB->getParent();
47381ad6265SDimitry Andric MachineInstr *NewMI = MF->CreateMachineInstr(TII->get(NewOpcode), DL);
47481ad6265SDimitry Andric MBB->insert(I, NewMI);
47581ad6265SDimitry Andric MachineInstrBuilder MIB(*MF, NewMI);
47681ad6265SDimitry Andric MIB.addReg(OldMI->getOperand(1).getReg(), false);
47781ad6265SDimitry Andric SHOWNEWINSTR(NewMI);
47881ad6265SDimitry Andric //erase later oldInstr->eraseFromParent();
47981ad6265SDimitry Andric }
48081ad6265SDimitry Andric
insertCondBranchBefore(MachineBasicBlock * blk,MachineBasicBlock::iterator I,int NewOpcode,int RegNum,const DebugLoc & DL)48181ad6265SDimitry Andric void R600MachineCFGStructurizer::insertCondBranchBefore(
48281ad6265SDimitry Andric MachineBasicBlock *blk, MachineBasicBlock::iterator I, int NewOpcode,
48381ad6265SDimitry Andric int RegNum, const DebugLoc &DL) {
48481ad6265SDimitry Andric MachineFunction *MF = blk->getParent();
48581ad6265SDimitry Andric MachineInstr *NewInstr = MF->CreateMachineInstr(TII->get(NewOpcode), DL);
48681ad6265SDimitry Andric //insert before
48781ad6265SDimitry Andric blk->insert(I, NewInstr);
48881ad6265SDimitry Andric MachineInstrBuilder(*MF, NewInstr).addReg(RegNum, false);
48981ad6265SDimitry Andric SHOWNEWINSTR(NewInstr);
49081ad6265SDimitry Andric }
49181ad6265SDimitry Andric
getBranchNzeroOpcode(int OldOpcode)49281ad6265SDimitry Andric int R600MachineCFGStructurizer::getBranchNzeroOpcode(int OldOpcode) {
49381ad6265SDimitry Andric switch(OldOpcode) {
49481ad6265SDimitry Andric case R600::JUMP_COND:
49581ad6265SDimitry Andric case R600::JUMP: return R600::IF_PREDICATE_SET;
49681ad6265SDimitry Andric case R600::BRANCH_COND_i32:
49781ad6265SDimitry Andric case R600::BRANCH_COND_f32: return R600::IF_LOGICALNZ_f32;
49881ad6265SDimitry Andric default: llvm_unreachable("internal error");
49981ad6265SDimitry Andric }
50081ad6265SDimitry Andric return -1;
50181ad6265SDimitry Andric }
50281ad6265SDimitry Andric
getBranchZeroOpcode(int OldOpcode)50381ad6265SDimitry Andric int R600MachineCFGStructurizer::getBranchZeroOpcode(int OldOpcode) {
50481ad6265SDimitry Andric switch(OldOpcode) {
50581ad6265SDimitry Andric case R600::JUMP_COND:
50681ad6265SDimitry Andric case R600::JUMP: return R600::IF_PREDICATE_SET;
50781ad6265SDimitry Andric case R600::BRANCH_COND_i32:
50881ad6265SDimitry Andric case R600::BRANCH_COND_f32: return R600::IF_LOGICALZ_f32;
50981ad6265SDimitry Andric default: llvm_unreachable("internal error");
51081ad6265SDimitry Andric }
51181ad6265SDimitry Andric return -1;
51281ad6265SDimitry Andric }
51381ad6265SDimitry Andric
getContinueNzeroOpcode(int OldOpcode)51481ad6265SDimitry Andric int R600MachineCFGStructurizer::getContinueNzeroOpcode(int OldOpcode) {
51581ad6265SDimitry Andric switch(OldOpcode) {
51681ad6265SDimitry Andric case R600::JUMP_COND:
51781ad6265SDimitry Andric case R600::JUMP: return R600::CONTINUE_LOGICALNZ_i32;
51881ad6265SDimitry Andric default: llvm_unreachable("internal error");
51981ad6265SDimitry Andric }
52081ad6265SDimitry Andric return -1;
52181ad6265SDimitry Andric }
52281ad6265SDimitry Andric
getContinueZeroOpcode(int OldOpcode)52381ad6265SDimitry Andric int R600MachineCFGStructurizer::getContinueZeroOpcode(int OldOpcode) {
52481ad6265SDimitry Andric switch(OldOpcode) {
52581ad6265SDimitry Andric case R600::JUMP_COND:
52681ad6265SDimitry Andric case R600::JUMP: return R600::CONTINUE_LOGICALZ_i32;
52781ad6265SDimitry Andric default: llvm_unreachable("internal error");
52881ad6265SDimitry Andric }
52981ad6265SDimitry Andric return -1;
53081ad6265SDimitry Andric }
53181ad6265SDimitry Andric
getTrueBranch(MachineInstr * MI)53281ad6265SDimitry Andric MachineBasicBlock *R600MachineCFGStructurizer::getTrueBranch(MachineInstr *MI) {
53381ad6265SDimitry Andric return MI->getOperand(0).getMBB();
53481ad6265SDimitry Andric }
53581ad6265SDimitry Andric
setTrueBranch(MachineInstr * MI,MachineBasicBlock * MBB)53681ad6265SDimitry Andric void R600MachineCFGStructurizer::setTrueBranch(MachineInstr *MI,
53781ad6265SDimitry Andric MachineBasicBlock *MBB) {
53881ad6265SDimitry Andric MI->getOperand(0).setMBB(MBB);
53981ad6265SDimitry Andric }
54081ad6265SDimitry Andric
54181ad6265SDimitry Andric MachineBasicBlock *
getFalseBranch(MachineBasicBlock * MBB,MachineInstr * MI)54281ad6265SDimitry Andric R600MachineCFGStructurizer::getFalseBranch(MachineBasicBlock *MBB,
54381ad6265SDimitry Andric MachineInstr *MI) {
54481ad6265SDimitry Andric assert(MBB->succ_size() == 2);
54581ad6265SDimitry Andric MachineBasicBlock *TrueBranch = getTrueBranch(MI);
54681ad6265SDimitry Andric MachineBasicBlock::succ_iterator It = MBB->succ_begin();
54781ad6265SDimitry Andric MachineBasicBlock::succ_iterator Next = It;
54881ad6265SDimitry Andric ++Next;
54981ad6265SDimitry Andric return (*It == TrueBranch) ? *Next : *It;
55081ad6265SDimitry Andric }
55181ad6265SDimitry Andric
isCondBranch(MachineInstr * MI)55281ad6265SDimitry Andric bool R600MachineCFGStructurizer::isCondBranch(MachineInstr *MI) {
55381ad6265SDimitry Andric switch (MI->getOpcode()) {
55481ad6265SDimitry Andric case R600::JUMP_COND:
55581ad6265SDimitry Andric case R600::BRANCH_COND_i32:
55681ad6265SDimitry Andric case R600::BRANCH_COND_f32: return true;
55781ad6265SDimitry Andric default:
55881ad6265SDimitry Andric return false;
55981ad6265SDimitry Andric }
56081ad6265SDimitry Andric return false;
56181ad6265SDimitry Andric }
56281ad6265SDimitry Andric
isUncondBranch(MachineInstr * MI)56381ad6265SDimitry Andric bool R600MachineCFGStructurizer::isUncondBranch(MachineInstr *MI) {
56481ad6265SDimitry Andric switch (MI->getOpcode()) {
56581ad6265SDimitry Andric case R600::JUMP:
56681ad6265SDimitry Andric case R600::BRANCH:
56781ad6265SDimitry Andric return true;
56881ad6265SDimitry Andric default:
56981ad6265SDimitry Andric return false;
57081ad6265SDimitry Andric }
57181ad6265SDimitry Andric return false;
57281ad6265SDimitry Andric }
57381ad6265SDimitry Andric
getLastDebugLocInBB(MachineBasicBlock * MBB)57481ad6265SDimitry Andric DebugLoc R600MachineCFGStructurizer::getLastDebugLocInBB(MachineBasicBlock *MBB) {
57581ad6265SDimitry Andric //get DebugLoc from the first MachineBasicBlock instruction with debug info
57681ad6265SDimitry Andric DebugLoc DL;
57781ad6265SDimitry Andric for (MachineInstr &MI : *MBB)
57881ad6265SDimitry Andric if (MI.getDebugLoc())
57981ad6265SDimitry Andric DL = MI.getDebugLoc();
58081ad6265SDimitry Andric return DL;
58181ad6265SDimitry Andric }
58281ad6265SDimitry Andric
getNormalBlockBranchInstr(MachineBasicBlock * MBB)58381ad6265SDimitry Andric MachineInstr *R600MachineCFGStructurizer::getNormalBlockBranchInstr(
58481ad6265SDimitry Andric MachineBasicBlock *MBB) {
58581ad6265SDimitry Andric MachineBasicBlock::reverse_iterator It = MBB->rbegin();
58681ad6265SDimitry Andric MachineInstr *MI = &*It;
58781ad6265SDimitry Andric if (MI && (isCondBranch(MI) || isUncondBranch(MI)))
58881ad6265SDimitry Andric return MI;
58981ad6265SDimitry Andric return nullptr;
59081ad6265SDimitry Andric }
59181ad6265SDimitry Andric
getLoopendBlockBranchInstr(MachineBasicBlock * MBB)59281ad6265SDimitry Andric MachineInstr *R600MachineCFGStructurizer::getLoopendBlockBranchInstr(
59381ad6265SDimitry Andric MachineBasicBlock *MBB) {
59481ad6265SDimitry Andric for (MachineBasicBlock::reverse_iterator It = MBB->rbegin(), E = MBB->rend();
59581ad6265SDimitry Andric It != E; ++It) {
59681ad6265SDimitry Andric // FIXME: Simplify
59781ad6265SDimitry Andric MachineInstr *MI = &*It;
59881ad6265SDimitry Andric if (MI) {
59981ad6265SDimitry Andric if (isCondBranch(MI) || isUncondBranch(MI))
60081ad6265SDimitry Andric return MI;
601*0fca6ea1SDimitry Andric if (!TII->isMov(MI->getOpcode()))
60281ad6265SDimitry Andric break;
60381ad6265SDimitry Andric }
60481ad6265SDimitry Andric }
60581ad6265SDimitry Andric return nullptr;
60681ad6265SDimitry Andric }
60781ad6265SDimitry Andric
getReturnInstr(MachineBasicBlock * MBB)60881ad6265SDimitry Andric MachineInstr *R600MachineCFGStructurizer::getReturnInstr(MachineBasicBlock *MBB) {
60981ad6265SDimitry Andric MachineBasicBlock::reverse_iterator It = MBB->rbegin();
61081ad6265SDimitry Andric if (It != MBB->rend()) {
61181ad6265SDimitry Andric MachineInstr *instr = &(*It);
61281ad6265SDimitry Andric if (instr->getOpcode() == R600::RETURN)
61381ad6265SDimitry Andric return instr;
61481ad6265SDimitry Andric }
61581ad6265SDimitry Andric return nullptr;
61681ad6265SDimitry Andric }
61781ad6265SDimitry Andric
isReturnBlock(MachineBasicBlock * MBB)61881ad6265SDimitry Andric bool R600MachineCFGStructurizer::isReturnBlock(MachineBasicBlock *MBB) {
61981ad6265SDimitry Andric MachineInstr *MI = getReturnInstr(MBB);
62081ad6265SDimitry Andric bool IsReturn = MBB->succ_empty();
62181ad6265SDimitry Andric if (MI)
62281ad6265SDimitry Andric assert(IsReturn);
62381ad6265SDimitry Andric else if (IsReturn)
62481ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "BB" << MBB->getNumber()
62581ad6265SDimitry Andric << " is return block without RETURN instr\n";);
62681ad6265SDimitry Andric return IsReturn;
62781ad6265SDimitry Andric }
62881ad6265SDimitry Andric
cloneSuccessorList(MachineBasicBlock * DstMBB,MachineBasicBlock * SrcMBB)62981ad6265SDimitry Andric void R600MachineCFGStructurizer::cloneSuccessorList(MachineBasicBlock *DstMBB,
63081ad6265SDimitry Andric MachineBasicBlock *SrcMBB) {
63181ad6265SDimitry Andric for (MachineBasicBlock *Succ : SrcMBB->successors())
63281ad6265SDimitry Andric DstMBB->addSuccessor(Succ); // *iter's predecessor is also taken care of
63381ad6265SDimitry Andric }
63481ad6265SDimitry Andric
clone(MachineBasicBlock * MBB)63581ad6265SDimitry Andric MachineBasicBlock *R600MachineCFGStructurizer::clone(MachineBasicBlock *MBB) {
63681ad6265SDimitry Andric MachineFunction *Func = MBB->getParent();
63781ad6265SDimitry Andric MachineBasicBlock *NewMBB = Func->CreateMachineBasicBlock();
63881ad6265SDimitry Andric Func->push_back(NewMBB); //insert to function
63981ad6265SDimitry Andric for (const MachineInstr &It : *MBB)
64081ad6265SDimitry Andric NewMBB->push_back(Func->CloneMachineInstr(&It));
64181ad6265SDimitry Andric return NewMBB;
64281ad6265SDimitry Andric }
64381ad6265SDimitry Andric
replaceInstrUseOfBlockWith(MachineBasicBlock * SrcMBB,MachineBasicBlock * OldMBB,MachineBasicBlock * NewBlk)64481ad6265SDimitry Andric void R600MachineCFGStructurizer::replaceInstrUseOfBlockWith(
64581ad6265SDimitry Andric MachineBasicBlock *SrcMBB, MachineBasicBlock *OldMBB,
64681ad6265SDimitry Andric MachineBasicBlock *NewBlk) {
64781ad6265SDimitry Andric MachineInstr *BranchMI = getLoopendBlockBranchInstr(SrcMBB);
64881ad6265SDimitry Andric if (BranchMI && isCondBranch(BranchMI) &&
64981ad6265SDimitry Andric getTrueBranch(BranchMI) == OldMBB)
65081ad6265SDimitry Andric setTrueBranch(BranchMI, NewBlk);
65181ad6265SDimitry Andric }
65281ad6265SDimitry Andric
wrapup(MachineBasicBlock * MBB)65381ad6265SDimitry Andric void R600MachineCFGStructurizer::wrapup(MachineBasicBlock *MBB) {
65481ad6265SDimitry Andric assert((!MBB->getParent()->getJumpTableInfo()
65581ad6265SDimitry Andric || MBB->getParent()->getJumpTableInfo()->isEmpty())
65681ad6265SDimitry Andric && "found a jump table");
65781ad6265SDimitry Andric
65881ad6265SDimitry Andric //collect continue right before endloop
65981ad6265SDimitry Andric SmallVector<MachineInstr *, DEFAULT_VEC_SLOTS> ContInstr;
66081ad6265SDimitry Andric MachineBasicBlock::iterator Pre = MBB->begin();
66181ad6265SDimitry Andric MachineBasicBlock::iterator E = MBB->end();
66281ad6265SDimitry Andric MachineBasicBlock::iterator It = Pre;
66381ad6265SDimitry Andric while (It != E) {
66481ad6265SDimitry Andric if (Pre->getOpcode() == R600::CONTINUE
66581ad6265SDimitry Andric && It->getOpcode() == R600::ENDLOOP)
66681ad6265SDimitry Andric ContInstr.push_back(&*Pre);
66781ad6265SDimitry Andric Pre = It;
66881ad6265SDimitry Andric ++It;
66981ad6265SDimitry Andric }
67081ad6265SDimitry Andric
67181ad6265SDimitry Andric //delete continue right before endloop
672*0fca6ea1SDimitry Andric for (auto *MI : ContInstr)
673*0fca6ea1SDimitry Andric MI->eraseFromParent();
67481ad6265SDimitry Andric
67581ad6265SDimitry Andric // TODO to fix up jump table so later phase won't be confused. if
67681ad6265SDimitry Andric // (jumpTableInfo->isEmpty() == false) { need to clean the jump table, but
67781ad6265SDimitry Andric // there isn't such an interface yet. alternatively, replace all the other
67881ad6265SDimitry Andric // blocks in the jump table with the entryBlk //}
67981ad6265SDimitry Andric }
68081ad6265SDimitry Andric
prepare()68181ad6265SDimitry Andric bool R600MachineCFGStructurizer::prepare() {
68281ad6265SDimitry Andric bool Changed = false;
68381ad6265SDimitry Andric
68481ad6265SDimitry Andric //FIXME: if not reducible flow graph, make it so ???
68581ad6265SDimitry Andric
68681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "R600MachineCFGStructurizer::prepare\n";);
68781ad6265SDimitry Andric
68881ad6265SDimitry Andric orderBlocks(FuncRep);
68981ad6265SDimitry Andric
69081ad6265SDimitry Andric SmallVector<MachineBasicBlock *, DEFAULT_VEC_SLOTS> RetBlks;
69181ad6265SDimitry Andric
69281ad6265SDimitry Andric // Add an ExitBlk to loop that don't have one
69381ad6265SDimitry Andric for (MachineLoop *LoopRep : *MLI) {
69481ad6265SDimitry Andric MBBVector ExitingMBBs;
69581ad6265SDimitry Andric LoopRep->getExitingBlocks(ExitingMBBs);
69681ad6265SDimitry Andric
69781ad6265SDimitry Andric if (ExitingMBBs.size() == 0) {
69881ad6265SDimitry Andric MachineBasicBlock* DummyExitBlk = normalizeInfiniteLoopExit(LoopRep);
69981ad6265SDimitry Andric if (DummyExitBlk)
70081ad6265SDimitry Andric RetBlks.push_back(DummyExitBlk);
70181ad6265SDimitry Andric }
70281ad6265SDimitry Andric }
70381ad6265SDimitry Andric
70481ad6265SDimitry Andric // Remove unconditional branch instr.
70581ad6265SDimitry Andric // Add dummy exit block iff there are multiple returns.
70681ad6265SDimitry Andric for (MachineBasicBlock *MBB : OrderedBlks) {
70781ad6265SDimitry Andric removeUnconditionalBranch(MBB);
70881ad6265SDimitry Andric removeRedundantConditionalBranch(MBB);
70981ad6265SDimitry Andric if (isReturnBlock(MBB)) {
71081ad6265SDimitry Andric RetBlks.push_back(MBB);
71181ad6265SDimitry Andric }
71281ad6265SDimitry Andric assert(MBB->succ_size() <= 2);
71381ad6265SDimitry Andric }
71481ad6265SDimitry Andric
71581ad6265SDimitry Andric if (RetBlks.size() >= 2) {
71681ad6265SDimitry Andric addDummyExitBlock(RetBlks);
71781ad6265SDimitry Andric Changed = true;
71881ad6265SDimitry Andric }
71981ad6265SDimitry Andric
72081ad6265SDimitry Andric return Changed;
72181ad6265SDimitry Andric }
72281ad6265SDimitry Andric
run()72381ad6265SDimitry Andric bool R600MachineCFGStructurizer::run() {
72481ad6265SDimitry Andric //Assume reducible CFG...
72581ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "R600MachineCFGStructurizer::run\n");
72681ad6265SDimitry Andric
72781ad6265SDimitry Andric #ifdef STRESSTEST
72881ad6265SDimitry Andric //Use the worse block ordering to test the algorithm.
72981ad6265SDimitry Andric ReverseVector(orderedBlks);
73081ad6265SDimitry Andric #endif
73181ad6265SDimitry Andric
73281ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Ordered blocks:\n"; printOrderedBlocks(););
73381ad6265SDimitry Andric int NumIter = 0;
73481ad6265SDimitry Andric bool Finish = false;
73581ad6265SDimitry Andric MachineBasicBlock *MBB;
73681ad6265SDimitry Andric bool MakeProgress = false;
73781ad6265SDimitry Andric int NumRemainedBlk = countActiveBlock(OrderedBlks.begin(),
73881ad6265SDimitry Andric OrderedBlks.end());
73981ad6265SDimitry Andric
74081ad6265SDimitry Andric do {
74181ad6265SDimitry Andric ++NumIter;
74281ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "numIter = " << NumIter
74381ad6265SDimitry Andric << ", numRemaintedBlk = " << NumRemainedBlk << "\n";);
74481ad6265SDimitry Andric (void)NumIter;
74581ad6265SDimitry Andric
74681ad6265SDimitry Andric SmallVectorImpl<MachineBasicBlock *>::const_iterator It =
74781ad6265SDimitry Andric OrderedBlks.begin();
74881ad6265SDimitry Andric SmallVectorImpl<MachineBasicBlock *>::const_iterator E =
74981ad6265SDimitry Andric OrderedBlks.end();
75081ad6265SDimitry Andric
75181ad6265SDimitry Andric SmallVectorImpl<MachineBasicBlock *>::const_iterator SccBeginIter =
75281ad6265SDimitry Andric It;
75381ad6265SDimitry Andric MachineBasicBlock *SccBeginMBB = nullptr;
75481ad6265SDimitry Andric int SccNumBlk = 0; // The number of active blocks, init to a
75581ad6265SDimitry Andric // maximum possible number.
75681ad6265SDimitry Andric int SccNumIter; // Number of iteration in this SCC.
75781ad6265SDimitry Andric
75881ad6265SDimitry Andric while (It != E) {
75981ad6265SDimitry Andric MBB = *It;
76081ad6265SDimitry Andric
76181ad6265SDimitry Andric if (!SccBeginMBB) {
76281ad6265SDimitry Andric SccBeginIter = It;
76381ad6265SDimitry Andric SccBeginMBB = MBB;
76481ad6265SDimitry Andric SccNumIter = 0;
76581ad6265SDimitry Andric SccNumBlk = NumRemainedBlk; // Init to maximum possible number.
76681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "start processing SCC" << getSCCNum(SccBeginMBB);
76781ad6265SDimitry Andric dbgs() << "\n";);
76881ad6265SDimitry Andric }
76981ad6265SDimitry Andric
77081ad6265SDimitry Andric if (!isRetiredBlock(MBB))
77181ad6265SDimitry Andric patternMatch(MBB);
77281ad6265SDimitry Andric
77381ad6265SDimitry Andric ++It;
77481ad6265SDimitry Andric
77581ad6265SDimitry Andric bool ContNextScc = true;
77681ad6265SDimitry Andric if (It == E
77781ad6265SDimitry Andric || getSCCNum(SccBeginMBB) != getSCCNum(*It)) {
77881ad6265SDimitry Andric // Just finish one scc.
77981ad6265SDimitry Andric ++SccNumIter;
78081ad6265SDimitry Andric int sccRemainedNumBlk = countActiveBlock(SccBeginIter, It);
78181ad6265SDimitry Andric if (sccRemainedNumBlk != 1 && sccRemainedNumBlk >= SccNumBlk) {
78281ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Can't reduce SCC " << getSCCNum(MBB)
78381ad6265SDimitry Andric << ", sccNumIter = " << SccNumIter;
78481ad6265SDimitry Andric dbgs() << "doesn't make any progress\n";);
78581ad6265SDimitry Andric (void)SccNumIter;
78681ad6265SDimitry Andric ContNextScc = true;
78781ad6265SDimitry Andric } else if (sccRemainedNumBlk != 1 && sccRemainedNumBlk < SccNumBlk) {
78881ad6265SDimitry Andric SccNumBlk = sccRemainedNumBlk;
78981ad6265SDimitry Andric It = SccBeginIter;
79081ad6265SDimitry Andric ContNextScc = false;
79181ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "repeat processing SCC" << getSCCNum(MBB)
79281ad6265SDimitry Andric << "sccNumIter = " << SccNumIter << '\n';);
79381ad6265SDimitry Andric } else {
79481ad6265SDimitry Andric // Finish the current scc.
79581ad6265SDimitry Andric ContNextScc = true;
79681ad6265SDimitry Andric }
79781ad6265SDimitry Andric } else {
79881ad6265SDimitry Andric // Continue on next component in the current scc.
79981ad6265SDimitry Andric ContNextScc = false;
80081ad6265SDimitry Andric }
80181ad6265SDimitry Andric
80281ad6265SDimitry Andric if (ContNextScc)
80381ad6265SDimitry Andric SccBeginMBB = nullptr;
80481ad6265SDimitry Andric } //while, "one iteration" over the function.
80581ad6265SDimitry Andric
80681ad6265SDimitry Andric MachineBasicBlock *EntryMBB =
80781ad6265SDimitry Andric *GraphTraits<MachineFunction *>::nodes_begin(FuncRep);
80881ad6265SDimitry Andric if (EntryMBB->succ_empty()) {
80981ad6265SDimitry Andric Finish = true;
81081ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Reduce to one block\n";);
81181ad6265SDimitry Andric } else {
81281ad6265SDimitry Andric int NewnumRemainedBlk
81381ad6265SDimitry Andric = countActiveBlock(OrderedBlks.begin(), OrderedBlks.end());
81481ad6265SDimitry Andric // consider cloned blocks ??
81581ad6265SDimitry Andric if (NewnumRemainedBlk == 1 || NewnumRemainedBlk < NumRemainedBlk) {
81681ad6265SDimitry Andric MakeProgress = true;
81781ad6265SDimitry Andric NumRemainedBlk = NewnumRemainedBlk;
81881ad6265SDimitry Andric } else {
81981ad6265SDimitry Andric MakeProgress = false;
82081ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "No progress\n";);
82181ad6265SDimitry Andric }
82281ad6265SDimitry Andric }
82381ad6265SDimitry Andric } while (!Finish && MakeProgress);
82481ad6265SDimitry Andric
82581ad6265SDimitry Andric // Misc wrap up to maintain the consistency of the Function representation.
82681ad6265SDimitry Andric wrapup(*GraphTraits<MachineFunction *>::nodes_begin(FuncRep));
82781ad6265SDimitry Andric
82881ad6265SDimitry Andric // Detach retired Block, release memory.
82981ad6265SDimitry Andric for (auto &It : BlockInfoMap) {
83081ad6265SDimitry Andric if (It.second && It.second->IsRetired) {
83181ad6265SDimitry Andric assert((It.first)->getNumber() != -1);
83281ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Erase BB" << (It.first)->getNumber() << "\n";);
83381ad6265SDimitry Andric It.first->eraseFromParent(); // Remove from the parent Function.
83481ad6265SDimitry Andric }
83581ad6265SDimitry Andric delete It.second;
83681ad6265SDimitry Andric }
83781ad6265SDimitry Andric BlockInfoMap.clear();
83881ad6265SDimitry Andric LLInfoMap.clear();
83981ad6265SDimitry Andric
84081ad6265SDimitry Andric if (!Finish) {
84181ad6265SDimitry Andric LLVM_DEBUG(FuncRep->viewCFG());
84281ad6265SDimitry Andric report_fatal_error("IRREDUCIBLE_CFG");
84381ad6265SDimitry Andric }
84481ad6265SDimitry Andric
84581ad6265SDimitry Andric return true;
84681ad6265SDimitry Andric }
84781ad6265SDimitry Andric
orderBlocks(MachineFunction * MF)84881ad6265SDimitry Andric void R600MachineCFGStructurizer::orderBlocks(MachineFunction *MF) {
84981ad6265SDimitry Andric int SccNum = 0;
85081ad6265SDimitry Andric for (scc_iterator<MachineFunction *> It = scc_begin(MF); !It.isAtEnd();
85181ad6265SDimitry Andric ++It, ++SccNum) {
85281ad6265SDimitry Andric const std::vector<MachineBasicBlock *> &SccNext = *It;
85381ad6265SDimitry Andric for (MachineBasicBlock *MBB : SccNext) {
85481ad6265SDimitry Andric OrderedBlks.push_back(MBB);
85581ad6265SDimitry Andric recordSccnum(MBB, SccNum);
85681ad6265SDimitry Andric }
85781ad6265SDimitry Andric }
85881ad6265SDimitry Andric
85981ad6265SDimitry Andric // walk through all the block in func to check for unreachable
86081ad6265SDimitry Andric for (auto *MBB : nodes(MF)) {
86181ad6265SDimitry Andric SccNum = getSCCNum(MBB);
86281ad6265SDimitry Andric if (SccNum == INVALIDSCCNUM)
86381ad6265SDimitry Andric dbgs() << "unreachable block BB" << MBB->getNumber() << "\n";
86481ad6265SDimitry Andric }
86581ad6265SDimitry Andric }
86681ad6265SDimitry Andric
patternMatch(MachineBasicBlock * MBB)86781ad6265SDimitry Andric int R600MachineCFGStructurizer::patternMatch(MachineBasicBlock *MBB) {
86881ad6265SDimitry Andric int NumMatch = 0;
86981ad6265SDimitry Andric int CurMatch;
87081ad6265SDimitry Andric
87181ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Begin patternMatch BB" << MBB->getNumber() << "\n";);
87281ad6265SDimitry Andric
87381ad6265SDimitry Andric while ((CurMatch = patternMatchGroup(MBB)) > 0)
87481ad6265SDimitry Andric NumMatch += CurMatch;
87581ad6265SDimitry Andric
87681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "End patternMatch BB" << MBB->getNumber()
87781ad6265SDimitry Andric << ", numMatch = " << NumMatch << "\n";);
87881ad6265SDimitry Andric
87981ad6265SDimitry Andric return NumMatch;
88081ad6265SDimitry Andric }
88181ad6265SDimitry Andric
patternMatchGroup(MachineBasicBlock * MBB)88281ad6265SDimitry Andric int R600MachineCFGStructurizer::patternMatchGroup(MachineBasicBlock *MBB) {
88381ad6265SDimitry Andric int NumMatch = 0;
88481ad6265SDimitry Andric NumMatch += loopendPatternMatch();
88581ad6265SDimitry Andric NumMatch += serialPatternMatch(MBB);
88681ad6265SDimitry Andric NumMatch += ifPatternMatch(MBB);
88781ad6265SDimitry Andric return NumMatch;
88881ad6265SDimitry Andric }
88981ad6265SDimitry Andric
serialPatternMatch(MachineBasicBlock * MBB)89081ad6265SDimitry Andric int R600MachineCFGStructurizer::serialPatternMatch(MachineBasicBlock *MBB) {
89181ad6265SDimitry Andric if (MBB->succ_size() != 1)
89281ad6265SDimitry Andric return 0;
89381ad6265SDimitry Andric
89481ad6265SDimitry Andric MachineBasicBlock *childBlk = *MBB->succ_begin();
89581ad6265SDimitry Andric if (childBlk->pred_size() != 1 || isActiveLoophead(childBlk))
89681ad6265SDimitry Andric return 0;
89781ad6265SDimitry Andric
89881ad6265SDimitry Andric mergeSerialBlock(MBB, childBlk);
89981ad6265SDimitry Andric ++numSerialPatternMatch;
90081ad6265SDimitry Andric return 1;
90181ad6265SDimitry Andric }
90281ad6265SDimitry Andric
ifPatternMatch(MachineBasicBlock * MBB)90381ad6265SDimitry Andric int R600MachineCFGStructurizer::ifPatternMatch(MachineBasicBlock *MBB) {
90481ad6265SDimitry Andric //two edges
90581ad6265SDimitry Andric if (MBB->succ_size() != 2)
90681ad6265SDimitry Andric return 0;
90781ad6265SDimitry Andric if (hasBackEdge(MBB))
90881ad6265SDimitry Andric return 0;
90981ad6265SDimitry Andric MachineInstr *BranchMI = getNormalBlockBranchInstr(MBB);
91081ad6265SDimitry Andric if (!BranchMI)
91181ad6265SDimitry Andric return 0;
91281ad6265SDimitry Andric
91381ad6265SDimitry Andric assert(isCondBranch(BranchMI));
91481ad6265SDimitry Andric int NumMatch = 0;
91581ad6265SDimitry Andric
91681ad6265SDimitry Andric MachineBasicBlock *TrueMBB = getTrueBranch(BranchMI);
91781ad6265SDimitry Andric NumMatch += serialPatternMatch(TrueMBB);
91881ad6265SDimitry Andric NumMatch += ifPatternMatch(TrueMBB);
91981ad6265SDimitry Andric MachineBasicBlock *FalseMBB = getFalseBranch(MBB, BranchMI);
92081ad6265SDimitry Andric NumMatch += serialPatternMatch(FalseMBB);
92181ad6265SDimitry Andric NumMatch += ifPatternMatch(FalseMBB);
92281ad6265SDimitry Andric MachineBasicBlock *LandBlk;
92381ad6265SDimitry Andric int Cloned = 0;
92481ad6265SDimitry Andric
92581ad6265SDimitry Andric assert (!TrueMBB->succ_empty() || !FalseMBB->succ_empty());
92681ad6265SDimitry Andric // TODO: Simplify
92781ad6265SDimitry Andric if (TrueMBB->succ_size() == 1 && FalseMBB->succ_size() == 1
92881ad6265SDimitry Andric && *TrueMBB->succ_begin() == *FalseMBB->succ_begin()) {
92981ad6265SDimitry Andric // Diamond pattern
93081ad6265SDimitry Andric LandBlk = *TrueMBB->succ_begin();
93181ad6265SDimitry Andric } else if (TrueMBB->succ_size() == 1 && *TrueMBB->succ_begin() == FalseMBB) {
93281ad6265SDimitry Andric // Triangle pattern, false is empty
93381ad6265SDimitry Andric LandBlk = FalseMBB;
93481ad6265SDimitry Andric FalseMBB = nullptr;
93581ad6265SDimitry Andric } else if (FalseMBB->succ_size() == 1
93681ad6265SDimitry Andric && *FalseMBB->succ_begin() == TrueMBB) {
93781ad6265SDimitry Andric // Triangle pattern, true is empty
93881ad6265SDimitry Andric // We reverse the predicate to make a triangle, empty false pattern;
93981ad6265SDimitry Andric std::swap(TrueMBB, FalseMBB);
94081ad6265SDimitry Andric reversePredicateSetter(MBB->end(), *MBB);
94181ad6265SDimitry Andric LandBlk = FalseMBB;
94281ad6265SDimitry Andric FalseMBB = nullptr;
94381ad6265SDimitry Andric } else if (FalseMBB->succ_size() == 1
94481ad6265SDimitry Andric && isSameloopDetachedContbreak(TrueMBB, FalseMBB)) {
94581ad6265SDimitry Andric LandBlk = *FalseMBB->succ_begin();
94681ad6265SDimitry Andric } else if (TrueMBB->succ_size() == 1
94781ad6265SDimitry Andric && isSameloopDetachedContbreak(FalseMBB, TrueMBB)) {
94881ad6265SDimitry Andric LandBlk = *TrueMBB->succ_begin();
94981ad6265SDimitry Andric } else {
95081ad6265SDimitry Andric return NumMatch + handleJumpintoIf(MBB, TrueMBB, FalseMBB);
95181ad6265SDimitry Andric }
95281ad6265SDimitry Andric
95381ad6265SDimitry Andric // improveSimpleJumpinfoIf can handle the case where landBlk == NULL but the
95481ad6265SDimitry Andric // new BB created for landBlk==NULL may introduce new challenge to the
95581ad6265SDimitry Andric // reduction process.
95681ad6265SDimitry Andric if (LandBlk &&
95781ad6265SDimitry Andric ((TrueMBB && TrueMBB->pred_size() > 1)
95881ad6265SDimitry Andric || (FalseMBB && FalseMBB->pred_size() > 1))) {
95981ad6265SDimitry Andric Cloned += improveSimpleJumpintoIf(MBB, TrueMBB, FalseMBB, &LandBlk);
96081ad6265SDimitry Andric }
96181ad6265SDimitry Andric
96281ad6265SDimitry Andric if (TrueMBB && TrueMBB->pred_size() > 1) {
96381ad6265SDimitry Andric TrueMBB = cloneBlockForPredecessor(TrueMBB, MBB);
96481ad6265SDimitry Andric ++Cloned;
96581ad6265SDimitry Andric }
96681ad6265SDimitry Andric
96781ad6265SDimitry Andric if (FalseMBB && FalseMBB->pred_size() > 1) {
96881ad6265SDimitry Andric FalseMBB = cloneBlockForPredecessor(FalseMBB, MBB);
96981ad6265SDimitry Andric ++Cloned;
97081ad6265SDimitry Andric }
97181ad6265SDimitry Andric
97281ad6265SDimitry Andric mergeIfthenelseBlock(BranchMI, MBB, TrueMBB, FalseMBB, LandBlk);
97381ad6265SDimitry Andric
97481ad6265SDimitry Andric ++numIfPatternMatch;
97581ad6265SDimitry Andric
97681ad6265SDimitry Andric numClonedBlock += Cloned;
97781ad6265SDimitry Andric
97881ad6265SDimitry Andric return 1 + Cloned + NumMatch;
97981ad6265SDimitry Andric }
98081ad6265SDimitry Andric
loopendPatternMatch()98181ad6265SDimitry Andric int R600MachineCFGStructurizer::loopendPatternMatch() {
98281ad6265SDimitry Andric std::deque<MachineLoop *> NestedLoops;
98381ad6265SDimitry Andric for (auto &It: *MLI)
98481ad6265SDimitry Andric for (MachineLoop *ML : depth_first(It))
98581ad6265SDimitry Andric NestedLoops.push_front(ML);
98681ad6265SDimitry Andric
98781ad6265SDimitry Andric if (NestedLoops.empty())
98881ad6265SDimitry Andric return 0;
98981ad6265SDimitry Andric
99081ad6265SDimitry Andric // Process nested loop outside->inside (we did push_front),
99181ad6265SDimitry Andric // so "continue" to a outside loop won't be mistaken as "break"
99281ad6265SDimitry Andric // of the current loop.
99381ad6265SDimitry Andric int Num = 0;
99481ad6265SDimitry Andric for (MachineLoop *ExaminedLoop : NestedLoops) {
99581ad6265SDimitry Andric if (ExaminedLoop->getNumBlocks() == 0 || Visited[ExaminedLoop])
99681ad6265SDimitry Andric continue;
99781ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Processing:\n"; ExaminedLoop->dump(););
99881ad6265SDimitry Andric int NumBreak = mergeLoop(ExaminedLoop);
99981ad6265SDimitry Andric if (NumBreak == -1)
100081ad6265SDimitry Andric break;
100181ad6265SDimitry Andric Num += NumBreak;
100281ad6265SDimitry Andric }
100381ad6265SDimitry Andric return Num;
100481ad6265SDimitry Andric }
100581ad6265SDimitry Andric
mergeLoop(MachineLoop * LoopRep)100681ad6265SDimitry Andric int R600MachineCFGStructurizer::mergeLoop(MachineLoop *LoopRep) {
100781ad6265SDimitry Andric MachineBasicBlock *LoopHeader = LoopRep->getHeader();
100881ad6265SDimitry Andric MBBVector ExitingMBBs;
100981ad6265SDimitry Andric LoopRep->getExitingBlocks(ExitingMBBs);
101081ad6265SDimitry Andric assert(!ExitingMBBs.empty() && "Infinite Loop not supported");
101181ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Loop has " << ExitingMBBs.size()
101281ad6265SDimitry Andric << " exiting blocks\n";);
101381ad6265SDimitry Andric // We assume a single ExitBlk
101481ad6265SDimitry Andric MBBVector ExitBlks;
101581ad6265SDimitry Andric LoopRep->getExitBlocks(ExitBlks);
101681ad6265SDimitry Andric SmallPtrSet<MachineBasicBlock *, 2> ExitBlkSet;
1017*0fca6ea1SDimitry Andric for (MachineBasicBlock *MBB : ExitBlks)
1018*0fca6ea1SDimitry Andric ExitBlkSet.insert(MBB);
101981ad6265SDimitry Andric assert(ExitBlkSet.size() == 1);
102081ad6265SDimitry Andric MachineBasicBlock *ExitBlk = *ExitBlks.begin();
102181ad6265SDimitry Andric assert(ExitBlk && "Loop has several exit block");
102281ad6265SDimitry Andric MBBVector LatchBlks;
102381ad6265SDimitry Andric for (auto *LB : inverse_children<MachineBasicBlock*>(LoopHeader))
102481ad6265SDimitry Andric if (LoopRep->contains(LB))
102581ad6265SDimitry Andric LatchBlks.push_back(LB);
102681ad6265SDimitry Andric
1027*0fca6ea1SDimitry Andric for (MachineBasicBlock *MBB : ExitingMBBs)
1028*0fca6ea1SDimitry Andric mergeLoopbreakBlock(MBB, ExitBlk);
1029*0fca6ea1SDimitry Andric for (MachineBasicBlock *MBB : LatchBlks)
1030*0fca6ea1SDimitry Andric settleLoopcontBlock(MBB, LoopHeader);
103181ad6265SDimitry Andric int Match = 0;
103281ad6265SDimitry Andric do {
103381ad6265SDimitry Andric Match = 0;
103481ad6265SDimitry Andric Match += serialPatternMatch(LoopHeader);
103581ad6265SDimitry Andric Match += ifPatternMatch(LoopHeader);
103681ad6265SDimitry Andric } while (Match > 0);
103781ad6265SDimitry Andric mergeLooplandBlock(LoopHeader, ExitBlk);
103881ad6265SDimitry Andric MachineLoop *ParentLoop = LoopRep->getParentLoop();
103981ad6265SDimitry Andric if (ParentLoop)
104081ad6265SDimitry Andric MLI->changeLoopFor(LoopHeader, ParentLoop);
104181ad6265SDimitry Andric else
104281ad6265SDimitry Andric MLI->removeBlock(LoopHeader);
104381ad6265SDimitry Andric Visited[LoopRep] = true;
104481ad6265SDimitry Andric return 1;
104581ad6265SDimitry Andric }
104681ad6265SDimitry Andric
isSameloopDetachedContbreak(MachineBasicBlock * Src1MBB,MachineBasicBlock * Src2MBB)104781ad6265SDimitry Andric bool R600MachineCFGStructurizer::isSameloopDetachedContbreak(
104881ad6265SDimitry Andric MachineBasicBlock *Src1MBB, MachineBasicBlock *Src2MBB) {
104981ad6265SDimitry Andric if (Src1MBB->succ_empty()) {
105081ad6265SDimitry Andric MachineLoop *LoopRep = MLI->getLoopFor(Src1MBB);
105181ad6265SDimitry Andric if (LoopRep&& LoopRep == MLI->getLoopFor(Src2MBB)) {
105281ad6265SDimitry Andric MachineBasicBlock *&TheEntry = LLInfoMap[LoopRep];
105381ad6265SDimitry Andric if (TheEntry) {
105481ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "isLoopContBreakBlock yes src1 = BB"
105581ad6265SDimitry Andric << Src1MBB->getNumber() << " src2 = BB"
105681ad6265SDimitry Andric << Src2MBB->getNumber() << "\n";);
105781ad6265SDimitry Andric return true;
105881ad6265SDimitry Andric }
105981ad6265SDimitry Andric }
106081ad6265SDimitry Andric }
106181ad6265SDimitry Andric return false;
106281ad6265SDimitry Andric }
106381ad6265SDimitry Andric
handleJumpintoIf(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB)106481ad6265SDimitry Andric int R600MachineCFGStructurizer::handleJumpintoIf(MachineBasicBlock *HeadMBB,
106581ad6265SDimitry Andric MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
106681ad6265SDimitry Andric int Num = handleJumpintoIfImp(HeadMBB, TrueMBB, FalseMBB);
106781ad6265SDimitry Andric if (Num == 0) {
106881ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "handleJumpintoIf swap trueBlk and FalseBlk"
106981ad6265SDimitry Andric << "\n";);
107081ad6265SDimitry Andric Num = handleJumpintoIfImp(HeadMBB, FalseMBB, TrueMBB);
107181ad6265SDimitry Andric }
107281ad6265SDimitry Andric return Num;
107381ad6265SDimitry Andric }
107481ad6265SDimitry Andric
handleJumpintoIfImp(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB)107581ad6265SDimitry Andric int R600MachineCFGStructurizer::handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
107681ad6265SDimitry Andric MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
107781ad6265SDimitry Andric int Num = 0;
107881ad6265SDimitry Andric MachineBasicBlock *DownBlk;
107981ad6265SDimitry Andric
108081ad6265SDimitry Andric //trueBlk could be the common post dominator
108181ad6265SDimitry Andric DownBlk = TrueMBB;
108281ad6265SDimitry Andric
108381ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "handleJumpintoIfImp head = BB" << HeadMBB->getNumber()
108481ad6265SDimitry Andric << " true = BB" << TrueMBB->getNumber()
108581ad6265SDimitry Andric << ", numSucc=" << TrueMBB->succ_size() << " false = BB"
108681ad6265SDimitry Andric << FalseMBB->getNumber() << "\n";);
108781ad6265SDimitry Andric
108881ad6265SDimitry Andric while (DownBlk) {
108981ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "check down = BB" << DownBlk->getNumber(););
109081ad6265SDimitry Andric
109181ad6265SDimitry Andric if (singlePathTo(FalseMBB, DownBlk) == SinglePath_InPath) {
109281ad6265SDimitry Andric LLVM_DEBUG(dbgs() << " working\n";);
109381ad6265SDimitry Andric
109481ad6265SDimitry Andric Num += cloneOnSideEntryTo(HeadMBB, TrueMBB, DownBlk);
109581ad6265SDimitry Andric Num += cloneOnSideEntryTo(HeadMBB, FalseMBB, DownBlk);
109681ad6265SDimitry Andric
109781ad6265SDimitry Andric numClonedBlock += Num;
109881ad6265SDimitry Andric Num += serialPatternMatch(*HeadMBB->succ_begin());
109981ad6265SDimitry Andric Num += serialPatternMatch(*std::next(HeadMBB->succ_begin()));
110081ad6265SDimitry Andric Num += ifPatternMatch(HeadMBB);
110181ad6265SDimitry Andric assert(Num > 0);
110281ad6265SDimitry Andric
110381ad6265SDimitry Andric break;
110481ad6265SDimitry Andric }
110581ad6265SDimitry Andric LLVM_DEBUG(dbgs() << " not working\n";);
110681ad6265SDimitry Andric DownBlk = (DownBlk->succ_size() == 1) ? (*DownBlk->succ_begin()) : nullptr;
110781ad6265SDimitry Andric } // walk down the postDomTree
110881ad6265SDimitry Andric
110981ad6265SDimitry Andric return Num;
111081ad6265SDimitry Andric }
111181ad6265SDimitry Andric
111281ad6265SDimitry Andric #ifndef NDEBUG
showImproveSimpleJumpintoIf(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB,MachineBasicBlock * LandMBB,bool Detail)111381ad6265SDimitry Andric void R600MachineCFGStructurizer::showImproveSimpleJumpintoIf(
111481ad6265SDimitry Andric MachineBasicBlock *HeadMBB, MachineBasicBlock *TrueMBB,
111581ad6265SDimitry Andric MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB, bool Detail) {
111681ad6265SDimitry Andric dbgs() << "head = BB" << HeadMBB->getNumber()
111781ad6265SDimitry Andric << " size = " << HeadMBB->size();
111881ad6265SDimitry Andric if (Detail) {
111981ad6265SDimitry Andric dbgs() << "\n";
112081ad6265SDimitry Andric HeadMBB->print(dbgs());
112181ad6265SDimitry Andric dbgs() << "\n";
112281ad6265SDimitry Andric }
112381ad6265SDimitry Andric
112481ad6265SDimitry Andric if (TrueMBB) {
112581ad6265SDimitry Andric dbgs() << ", true = BB" << TrueMBB->getNumber() << " size = "
112681ad6265SDimitry Andric << TrueMBB->size() << " numPred = " << TrueMBB->pred_size();
112781ad6265SDimitry Andric if (Detail) {
112881ad6265SDimitry Andric dbgs() << "\n";
112981ad6265SDimitry Andric TrueMBB->print(dbgs());
113081ad6265SDimitry Andric dbgs() << "\n";
113181ad6265SDimitry Andric }
113281ad6265SDimitry Andric }
113381ad6265SDimitry Andric if (FalseMBB) {
113481ad6265SDimitry Andric dbgs() << ", false = BB" << FalseMBB->getNumber() << " size = "
113581ad6265SDimitry Andric << FalseMBB->size() << " numPred = " << FalseMBB->pred_size();
113681ad6265SDimitry Andric if (Detail) {
113781ad6265SDimitry Andric dbgs() << "\n";
113881ad6265SDimitry Andric FalseMBB->print(dbgs());
113981ad6265SDimitry Andric dbgs() << "\n";
114081ad6265SDimitry Andric }
114181ad6265SDimitry Andric }
114281ad6265SDimitry Andric if (LandMBB) {
114381ad6265SDimitry Andric dbgs() << ", land = BB" << LandMBB->getNumber() << " size = "
114481ad6265SDimitry Andric << LandMBB->size() << " numPred = " << LandMBB->pred_size();
114581ad6265SDimitry Andric if (Detail) {
114681ad6265SDimitry Andric dbgs() << "\n";
114781ad6265SDimitry Andric LandMBB->print(dbgs());
114881ad6265SDimitry Andric dbgs() << "\n";
114981ad6265SDimitry Andric }
115081ad6265SDimitry Andric }
115181ad6265SDimitry Andric
115281ad6265SDimitry Andric dbgs() << "\n";
115381ad6265SDimitry Andric }
115481ad6265SDimitry Andric #endif
115581ad6265SDimitry Andric
improveSimpleJumpintoIf(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB,MachineBasicBlock ** LandMBBPtr)115681ad6265SDimitry Andric int R600MachineCFGStructurizer::improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
115781ad6265SDimitry Andric MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
115881ad6265SDimitry Andric MachineBasicBlock **LandMBBPtr) {
115981ad6265SDimitry Andric bool MigrateTrue = false;
116081ad6265SDimitry Andric bool MigrateFalse = false;
116181ad6265SDimitry Andric
116281ad6265SDimitry Andric MachineBasicBlock *LandBlk = *LandMBBPtr;
116381ad6265SDimitry Andric
116481ad6265SDimitry Andric assert((!TrueMBB || TrueMBB->succ_size() <= 1)
116581ad6265SDimitry Andric && (!FalseMBB || FalseMBB->succ_size() <= 1));
116681ad6265SDimitry Andric
116781ad6265SDimitry Andric if (TrueMBB == FalseMBB)
116881ad6265SDimitry Andric return 0;
116981ad6265SDimitry Andric
117081ad6265SDimitry Andric MigrateTrue = needMigrateBlock(TrueMBB);
117181ad6265SDimitry Andric MigrateFalse = needMigrateBlock(FalseMBB);
117281ad6265SDimitry Andric
117381ad6265SDimitry Andric if (!MigrateTrue && !MigrateFalse)
117481ad6265SDimitry Andric return 0;
117581ad6265SDimitry Andric
117681ad6265SDimitry Andric // If we need to migrate either trueBlk and falseBlk, migrate the rest that
117781ad6265SDimitry Andric // have more than one predecessors. without doing this, its predecessor
117881ad6265SDimitry Andric // rather than headBlk will have undefined value in initReg.
117981ad6265SDimitry Andric if (!MigrateTrue && TrueMBB && TrueMBB->pred_size() > 1)
118081ad6265SDimitry Andric MigrateTrue = true;
118181ad6265SDimitry Andric if (!MigrateFalse && FalseMBB && FalseMBB->pred_size() > 1)
118281ad6265SDimitry Andric MigrateFalse = true;
118381ad6265SDimitry Andric
118481ad6265SDimitry Andric LLVM_DEBUG(
118581ad6265SDimitry Andric dbgs() << "before improveSimpleJumpintoIf: ";
118681ad6265SDimitry Andric showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0););
118781ad6265SDimitry Andric
118881ad6265SDimitry Andric // org: headBlk => if () {trueBlk} else {falseBlk} => landBlk
118981ad6265SDimitry Andric //
119081ad6265SDimitry Andric // new: headBlk => if () {initReg = 1; org trueBlk branch} else
119181ad6265SDimitry Andric // {initReg = 0; org falseBlk branch }
119281ad6265SDimitry Andric // => landBlk => if (initReg) {org trueBlk} else {org falseBlk}
119381ad6265SDimitry Andric // => org landBlk
119481ad6265SDimitry Andric // if landBlk->pred_size() > 2, put the about if-else inside
119581ad6265SDimitry Andric // if (initReg !=2) {...}
119681ad6265SDimitry Andric //
119781ad6265SDimitry Andric // add initReg = initVal to headBlk
119881ad6265SDimitry Andric
119981ad6265SDimitry Andric const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
120081ad6265SDimitry Andric if (!MigrateTrue || !MigrateFalse) {
120181ad6265SDimitry Andric // XXX: We have an opportunity here to optimize the "branch into if" case
120281ad6265SDimitry Andric // here. Branch into if looks like this:
120381ad6265SDimitry Andric // entry
120481ad6265SDimitry Andric // / |
120581ad6265SDimitry Andric // diamond_head branch_from
120681ad6265SDimitry Andric // / \ |
120781ad6265SDimitry Andric // diamond_false diamond_true
120881ad6265SDimitry Andric // \ /
120981ad6265SDimitry Andric // done
121081ad6265SDimitry Andric //
121181ad6265SDimitry Andric // The diamond_head block begins the "if" and the diamond_true block
121281ad6265SDimitry Andric // is the block being "branched into".
121381ad6265SDimitry Andric //
121481ad6265SDimitry Andric // If MigrateTrue is true, then TrueBB is the block being "branched into"
121581ad6265SDimitry Andric // and if MigrateFalse is true, then FalseBB is the block being
121681ad6265SDimitry Andric // "branched into"
121781ad6265SDimitry Andric //
121881ad6265SDimitry Andric // Here is the pseudo code for how I think the optimization should work:
121981ad6265SDimitry Andric // 1. Insert MOV GPR0, 0 before the branch instruction in diamond_head.
122081ad6265SDimitry Andric // 2. Insert MOV GPR0, 1 before the branch instruction in branch_from.
122181ad6265SDimitry Andric // 3. Move the branch instruction from diamond_head into its own basic
122281ad6265SDimitry Andric // block (new_block).
122381ad6265SDimitry Andric // 4. Add an unconditional branch from diamond_head to new_block
122481ad6265SDimitry Andric // 5. Replace the branch instruction in branch_from with an unconditional
122581ad6265SDimitry Andric // branch to new_block. If branch_from has multiple predecessors, then
122681ad6265SDimitry Andric // we need to replace the True/False block in the branch
122781ad6265SDimitry Andric // instruction instead of replacing it.
122881ad6265SDimitry Andric // 6. Change the condition of the branch instruction in new_block from
122981ad6265SDimitry Andric // COND to (COND || GPR0)
123081ad6265SDimitry Andric //
123181ad6265SDimitry Andric // In order insert these MOV instruction, we will need to use the
123281ad6265SDimitry Andric // RegisterScavenger. Usually liveness stops being tracked during
123381ad6265SDimitry Andric // the late machine optimization passes, however if we implement
123481ad6265SDimitry Andric // bool TargetRegisterInfo::requiresRegisterScavenging(
123581ad6265SDimitry Andric // const MachineFunction &MF)
123681ad6265SDimitry Andric // and have it return true, liveness will be tracked correctly
123781ad6265SDimitry Andric // by generic optimization passes. We will also need to make sure that
123881ad6265SDimitry Andric // all of our target-specific passes that run after regalloc and before
123981ad6265SDimitry Andric // the CFGStructurizer track liveness and we will need to modify this pass
124081ad6265SDimitry Andric // to correctly track liveness.
124181ad6265SDimitry Andric //
124281ad6265SDimitry Andric // After the above changes, the new CFG should look like this:
124381ad6265SDimitry Andric // entry
124481ad6265SDimitry Andric // / |
124581ad6265SDimitry Andric // diamond_head branch_from
124681ad6265SDimitry Andric // \ /
124781ad6265SDimitry Andric // new_block
124881ad6265SDimitry Andric // / |
124981ad6265SDimitry Andric // diamond_false diamond_true
125081ad6265SDimitry Andric // \ /
125181ad6265SDimitry Andric // done
125281ad6265SDimitry Andric //
125381ad6265SDimitry Andric // Without this optimization, we are forced to duplicate the diamond_true
125481ad6265SDimitry Andric // block and we will end up with a CFG like this:
125581ad6265SDimitry Andric //
125681ad6265SDimitry Andric // entry
125781ad6265SDimitry Andric // / |
125881ad6265SDimitry Andric // diamond_head branch_from
125981ad6265SDimitry Andric // / \ |
126081ad6265SDimitry Andric // diamond_false diamond_true diamond_true (duplicate)
126181ad6265SDimitry Andric // \ / |
126281ad6265SDimitry Andric // done --------------------|
126381ad6265SDimitry Andric //
126481ad6265SDimitry Andric // Duplicating diamond_true can be very costly especially if it has a
126581ad6265SDimitry Andric // lot of instructions.
126681ad6265SDimitry Andric return 0;
126781ad6265SDimitry Andric }
126881ad6265SDimitry Andric
126981ad6265SDimitry Andric int NumNewBlk = 0;
127081ad6265SDimitry Andric
127181ad6265SDimitry Andric bool LandBlkHasOtherPred = (LandBlk->pred_size() > 2);
127281ad6265SDimitry Andric
127381ad6265SDimitry Andric //insert R600::ENDIF to avoid special case "input landBlk == NULL"
127481ad6265SDimitry Andric MachineBasicBlock::iterator I = insertInstrBefore(LandBlk, R600::ENDIF);
127581ad6265SDimitry Andric
127681ad6265SDimitry Andric if (LandBlkHasOtherPred) {
127781ad6265SDimitry Andric report_fatal_error("Extra register needed to handle CFG");
127881ad6265SDimitry Andric Register CmpResReg =
127981ad6265SDimitry Andric HeadMBB->getParent()->getRegInfo().createVirtualRegister(I32RC);
128081ad6265SDimitry Andric report_fatal_error("Extra compare instruction needed to handle CFG");
128181ad6265SDimitry Andric insertCondBranchBefore(LandBlk, I, R600::IF_PREDICATE_SET,
128281ad6265SDimitry Andric CmpResReg, DebugLoc());
128381ad6265SDimitry Andric }
128481ad6265SDimitry Andric
128581ad6265SDimitry Andric // XXX: We are running this after RA, so creating virtual registers will
128681ad6265SDimitry Andric // cause an assertion failure in the PostRA scheduling pass.
128781ad6265SDimitry Andric Register InitReg =
128881ad6265SDimitry Andric HeadMBB->getParent()->getRegInfo().createVirtualRegister(I32RC);
128981ad6265SDimitry Andric insertCondBranchBefore(LandBlk, I, R600::IF_PREDICATE_SET, InitReg,
129081ad6265SDimitry Andric DebugLoc());
129181ad6265SDimitry Andric
129281ad6265SDimitry Andric if (MigrateTrue) {
129381ad6265SDimitry Andric migrateInstruction(TrueMBB, LandBlk, I);
129481ad6265SDimitry Andric // need to uncondionally insert the assignment to ensure a path from its
129581ad6265SDimitry Andric // predecessor rather than headBlk has valid value in initReg if
129681ad6265SDimitry Andric // (initVal != 1).
129781ad6265SDimitry Andric report_fatal_error("Extra register needed to handle CFG");
129881ad6265SDimitry Andric }
129981ad6265SDimitry Andric insertInstrBefore(I, R600::ELSE);
130081ad6265SDimitry Andric
130181ad6265SDimitry Andric if (MigrateFalse) {
130281ad6265SDimitry Andric migrateInstruction(FalseMBB, LandBlk, I);
130381ad6265SDimitry Andric // need to uncondionally insert the assignment to ensure a path from its
130481ad6265SDimitry Andric // predecessor rather than headBlk has valid value in initReg if
130581ad6265SDimitry Andric // (initVal != 0)
130681ad6265SDimitry Andric report_fatal_error("Extra register needed to handle CFG");
130781ad6265SDimitry Andric }
130881ad6265SDimitry Andric
130981ad6265SDimitry Andric if (LandBlkHasOtherPred) {
131081ad6265SDimitry Andric // add endif
131181ad6265SDimitry Andric insertInstrBefore(I, R600::ENDIF);
131281ad6265SDimitry Andric
131381ad6265SDimitry Andric // put initReg = 2 to other predecessors of landBlk
131481ad6265SDimitry Andric for (MachineBasicBlock *MBB : LandBlk->predecessors())
131581ad6265SDimitry Andric if (MBB != TrueMBB && MBB != FalseMBB)
131681ad6265SDimitry Andric report_fatal_error("Extra register needed to handle CFG");
131781ad6265SDimitry Andric }
131881ad6265SDimitry Andric LLVM_DEBUG(
131981ad6265SDimitry Andric dbgs() << "result from improveSimpleJumpintoIf: ";
132081ad6265SDimitry Andric showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0););
132181ad6265SDimitry Andric
132281ad6265SDimitry Andric // update landBlk
132381ad6265SDimitry Andric *LandMBBPtr = LandBlk;
132481ad6265SDimitry Andric
132581ad6265SDimitry Andric return NumNewBlk;
132681ad6265SDimitry Andric }
132781ad6265SDimitry Andric
mergeSerialBlock(MachineBasicBlock * DstMBB,MachineBasicBlock * SrcMBB)132881ad6265SDimitry Andric void R600MachineCFGStructurizer::mergeSerialBlock(MachineBasicBlock *DstMBB,
132981ad6265SDimitry Andric MachineBasicBlock *SrcMBB) {
133081ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "serialPattern BB" << DstMBB->getNumber() << " <= BB"
133181ad6265SDimitry Andric << SrcMBB->getNumber() << "\n";);
133281ad6265SDimitry Andric DstMBB->splice(DstMBB->end(), SrcMBB, SrcMBB->begin(), SrcMBB->end());
133381ad6265SDimitry Andric
133481ad6265SDimitry Andric DstMBB->removeSuccessor(SrcMBB, true);
133581ad6265SDimitry Andric cloneSuccessorList(DstMBB, SrcMBB);
133681ad6265SDimitry Andric
133781ad6265SDimitry Andric removeSuccessor(SrcMBB);
133881ad6265SDimitry Andric MLI->removeBlock(SrcMBB);
133981ad6265SDimitry Andric retireBlock(SrcMBB);
134081ad6265SDimitry Andric }
134181ad6265SDimitry Andric
mergeIfthenelseBlock(MachineInstr * BranchMI,MachineBasicBlock * MBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB,MachineBasicBlock * LandMBB)134281ad6265SDimitry Andric void R600MachineCFGStructurizer::mergeIfthenelseBlock(MachineInstr *BranchMI,
134381ad6265SDimitry Andric MachineBasicBlock *MBB, MachineBasicBlock *TrueMBB,
134481ad6265SDimitry Andric MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB) {
134581ad6265SDimitry Andric assert (TrueMBB);
134681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "ifPattern BB" << MBB->getNumber(); dbgs() << "{ ";
134781ad6265SDimitry Andric if (TrueMBB) { dbgs() << "BB" << TrueMBB->getNumber(); } dbgs()
134881ad6265SDimitry Andric << " } else ";
134981ad6265SDimitry Andric dbgs() << "{ "; if (FalseMBB) {
135081ad6265SDimitry Andric dbgs() << "BB" << FalseMBB->getNumber();
135181ad6265SDimitry Andric } dbgs() << " }\n ";
135281ad6265SDimitry Andric dbgs() << "landBlock: "; if (!LandMBB) { dbgs() << "NULL"; } else {
135381ad6265SDimitry Andric dbgs() << "BB" << LandMBB->getNumber();
135481ad6265SDimitry Andric } dbgs() << "\n";);
135581ad6265SDimitry Andric
135681ad6265SDimitry Andric int OldOpcode = BranchMI->getOpcode();
135781ad6265SDimitry Andric DebugLoc BranchDL = BranchMI->getDebugLoc();
135881ad6265SDimitry Andric
135981ad6265SDimitry Andric // transform to
136081ad6265SDimitry Andric // if cond
136181ad6265SDimitry Andric // trueBlk
136281ad6265SDimitry Andric // else
136381ad6265SDimitry Andric // falseBlk
136481ad6265SDimitry Andric // endif
136581ad6265SDimitry Andric // landBlk
136681ad6265SDimitry Andric
136781ad6265SDimitry Andric MachineBasicBlock::iterator I = BranchMI;
136881ad6265SDimitry Andric insertCondBranchBefore(I, getBranchNzeroOpcode(OldOpcode),
136981ad6265SDimitry Andric BranchDL);
137081ad6265SDimitry Andric
137181ad6265SDimitry Andric if (TrueMBB) {
137281ad6265SDimitry Andric MBB->splice(I, TrueMBB, TrueMBB->begin(), TrueMBB->end());
137381ad6265SDimitry Andric MBB->removeSuccessor(TrueMBB, true);
137481ad6265SDimitry Andric if (LandMBB && TrueMBB->succ_size()!=0)
137581ad6265SDimitry Andric TrueMBB->removeSuccessor(LandMBB, true);
137681ad6265SDimitry Andric retireBlock(TrueMBB);
137781ad6265SDimitry Andric MLI->removeBlock(TrueMBB);
137881ad6265SDimitry Andric }
137981ad6265SDimitry Andric
138081ad6265SDimitry Andric if (FalseMBB) {
138181ad6265SDimitry Andric insertInstrBefore(I, R600::ELSE);
138281ad6265SDimitry Andric MBB->splice(I, FalseMBB, FalseMBB->begin(),
138381ad6265SDimitry Andric FalseMBB->end());
138481ad6265SDimitry Andric MBB->removeSuccessor(FalseMBB, true);
138581ad6265SDimitry Andric if (LandMBB && !FalseMBB->succ_empty())
138681ad6265SDimitry Andric FalseMBB->removeSuccessor(LandMBB, true);
138781ad6265SDimitry Andric retireBlock(FalseMBB);
138881ad6265SDimitry Andric MLI->removeBlock(FalseMBB);
138981ad6265SDimitry Andric }
139081ad6265SDimitry Andric insertInstrBefore(I, R600::ENDIF);
139181ad6265SDimitry Andric
139281ad6265SDimitry Andric BranchMI->eraseFromParent();
139381ad6265SDimitry Andric
139481ad6265SDimitry Andric if (LandMBB && TrueMBB && FalseMBB)
139581ad6265SDimitry Andric MBB->addSuccessor(LandMBB);
139681ad6265SDimitry Andric }
139781ad6265SDimitry Andric
mergeLooplandBlock(MachineBasicBlock * DstBlk,MachineBasicBlock * LandMBB)139881ad6265SDimitry Andric void R600MachineCFGStructurizer::mergeLooplandBlock(MachineBasicBlock *DstBlk,
139981ad6265SDimitry Andric MachineBasicBlock *LandMBB) {
140081ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "loopPattern header = BB" << DstBlk->getNumber()
140181ad6265SDimitry Andric << " land = BB" << LandMBB->getNumber() << "\n";);
140281ad6265SDimitry Andric
140381ad6265SDimitry Andric insertInstrBefore(DstBlk, R600::WHILELOOP, DebugLoc());
140481ad6265SDimitry Andric insertInstrEnd(DstBlk, R600::ENDLOOP, DebugLoc());
140581ad6265SDimitry Andric DstBlk->replaceSuccessor(DstBlk, LandMBB);
140681ad6265SDimitry Andric }
140781ad6265SDimitry Andric
mergeLoopbreakBlock(MachineBasicBlock * ExitingMBB,MachineBasicBlock * LandMBB)140881ad6265SDimitry Andric void R600MachineCFGStructurizer::mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
140981ad6265SDimitry Andric MachineBasicBlock *LandMBB) {
141081ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "loopbreakPattern exiting = BB"
141181ad6265SDimitry Andric << ExitingMBB->getNumber() << " land = BB"
141281ad6265SDimitry Andric << LandMBB->getNumber() << "\n";);
141381ad6265SDimitry Andric MachineInstr *BranchMI = getLoopendBlockBranchInstr(ExitingMBB);
141481ad6265SDimitry Andric assert(BranchMI && isCondBranch(BranchMI));
141581ad6265SDimitry Andric DebugLoc DL = BranchMI->getDebugLoc();
141681ad6265SDimitry Andric MachineBasicBlock *TrueBranch = getTrueBranch(BranchMI);
141781ad6265SDimitry Andric MachineBasicBlock::iterator I = BranchMI;
141881ad6265SDimitry Andric if (TrueBranch != LandMBB)
141981ad6265SDimitry Andric reversePredicateSetter(I, *I->getParent());
142081ad6265SDimitry Andric insertCondBranchBefore(ExitingMBB, I, R600::IF_PREDICATE_SET, R600::PREDICATE_BIT, DL);
142181ad6265SDimitry Andric insertInstrBefore(I, R600::BREAK);
142281ad6265SDimitry Andric insertInstrBefore(I, R600::ENDIF);
142381ad6265SDimitry Andric //now branchInst can be erase safely
142481ad6265SDimitry Andric BranchMI->eraseFromParent();
142581ad6265SDimitry Andric //now take care of successors, retire blocks
142681ad6265SDimitry Andric ExitingMBB->removeSuccessor(LandMBB, true);
142781ad6265SDimitry Andric }
142881ad6265SDimitry Andric
settleLoopcontBlock(MachineBasicBlock * ContingMBB,MachineBasicBlock * ContMBB)142981ad6265SDimitry Andric void R600MachineCFGStructurizer::settleLoopcontBlock(MachineBasicBlock *ContingMBB,
143081ad6265SDimitry Andric MachineBasicBlock *ContMBB) {
143181ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "settleLoopcontBlock conting = BB"
143281ad6265SDimitry Andric << ContingMBB->getNumber() << ", cont = BB"
143381ad6265SDimitry Andric << ContMBB->getNumber() << "\n";);
143481ad6265SDimitry Andric
143581ad6265SDimitry Andric MachineInstr *MI = getLoopendBlockBranchInstr(ContingMBB);
143681ad6265SDimitry Andric if (MI) {
143781ad6265SDimitry Andric assert(isCondBranch(MI));
143881ad6265SDimitry Andric MachineBasicBlock::iterator I = MI;
143981ad6265SDimitry Andric MachineBasicBlock *TrueBranch = getTrueBranch(MI);
144081ad6265SDimitry Andric int OldOpcode = MI->getOpcode();
144181ad6265SDimitry Andric DebugLoc DL = MI->getDebugLoc();
144281ad6265SDimitry Andric
144381ad6265SDimitry Andric bool UseContinueLogical = ((&*ContingMBB->rbegin()) == MI);
144481ad6265SDimitry Andric
144581ad6265SDimitry Andric if (!UseContinueLogical) {
144681ad6265SDimitry Andric int BranchOpcode =
144781ad6265SDimitry Andric TrueBranch == ContMBB ? getBranchNzeroOpcode(OldOpcode) :
144881ad6265SDimitry Andric getBranchZeroOpcode(OldOpcode);
144981ad6265SDimitry Andric insertCondBranchBefore(I, BranchOpcode, DL);
145081ad6265SDimitry Andric // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
145181ad6265SDimitry Andric insertInstrEnd(ContingMBB, R600::CONTINUE, DL);
145281ad6265SDimitry Andric insertInstrEnd(ContingMBB, R600::ENDIF, DL);
145381ad6265SDimitry Andric } else {
145481ad6265SDimitry Andric int BranchOpcode =
145581ad6265SDimitry Andric TrueBranch == ContMBB ? getContinueNzeroOpcode(OldOpcode) :
145681ad6265SDimitry Andric getContinueZeroOpcode(OldOpcode);
145781ad6265SDimitry Andric insertCondBranchBefore(I, BranchOpcode, DL);
145881ad6265SDimitry Andric }
145981ad6265SDimitry Andric
146081ad6265SDimitry Andric MI->eraseFromParent();
146181ad6265SDimitry Andric } else {
146281ad6265SDimitry Andric // if we've arrived here then we've already erased the branch instruction
146381ad6265SDimitry Andric // travel back up the basic block to see the last reference of our debug
146481ad6265SDimitry Andric // location we've just inserted that reference here so it should be
146581ad6265SDimitry Andric // representative insertEnd to ensure phi-moves, if exist, go before the
146681ad6265SDimitry Andric // continue-instr.
146781ad6265SDimitry Andric insertInstrEnd(ContingMBB, R600::CONTINUE,
146881ad6265SDimitry Andric getLastDebugLocInBB(ContingMBB));
146981ad6265SDimitry Andric }
147081ad6265SDimitry Andric }
147181ad6265SDimitry Andric
cloneOnSideEntryTo(MachineBasicBlock * PreMBB,MachineBasicBlock * SrcMBB,MachineBasicBlock * DstMBB)147281ad6265SDimitry Andric int R600MachineCFGStructurizer::cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
147381ad6265SDimitry Andric MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB) {
147481ad6265SDimitry Andric int Cloned = 0;
147581ad6265SDimitry Andric assert(PreMBB->isSuccessor(SrcMBB));
147681ad6265SDimitry Andric while (SrcMBB && SrcMBB != DstMBB) {
147781ad6265SDimitry Andric assert(SrcMBB->succ_size() == 1);
147881ad6265SDimitry Andric if (SrcMBB->pred_size() > 1) {
147981ad6265SDimitry Andric SrcMBB = cloneBlockForPredecessor(SrcMBB, PreMBB);
148081ad6265SDimitry Andric ++Cloned;
148181ad6265SDimitry Andric }
148281ad6265SDimitry Andric
148381ad6265SDimitry Andric PreMBB = SrcMBB;
148481ad6265SDimitry Andric SrcMBB = *SrcMBB->succ_begin();
148581ad6265SDimitry Andric }
148681ad6265SDimitry Andric
148781ad6265SDimitry Andric return Cloned;
148881ad6265SDimitry Andric }
148981ad6265SDimitry Andric
149081ad6265SDimitry Andric MachineBasicBlock *
cloneBlockForPredecessor(MachineBasicBlock * MBB,MachineBasicBlock * PredMBB)149181ad6265SDimitry Andric R600MachineCFGStructurizer::cloneBlockForPredecessor(MachineBasicBlock *MBB,
149281ad6265SDimitry Andric MachineBasicBlock *PredMBB) {
149381ad6265SDimitry Andric assert(PredMBB->isSuccessor(MBB) && "succBlk is not a predecessor of curBlk");
149481ad6265SDimitry Andric
149581ad6265SDimitry Andric MachineBasicBlock *CloneMBB = clone(MBB); //clone instructions
149681ad6265SDimitry Andric replaceInstrUseOfBlockWith(PredMBB, MBB, CloneMBB);
149781ad6265SDimitry Andric //srcBlk, oldBlk, newBlk
149881ad6265SDimitry Andric
149981ad6265SDimitry Andric PredMBB->replaceSuccessor(MBB, CloneMBB);
150081ad6265SDimitry Andric
150181ad6265SDimitry Andric // add all successor to cloneBlk
150281ad6265SDimitry Andric cloneSuccessorList(CloneMBB, MBB);
150381ad6265SDimitry Andric
150481ad6265SDimitry Andric numClonedInstr += MBB->size();
150581ad6265SDimitry Andric
150681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Cloned block: "
150781ad6265SDimitry Andric << "BB" << MBB->getNumber() << "size " << MBB->size()
150881ad6265SDimitry Andric << "\n";);
150981ad6265SDimitry Andric
151081ad6265SDimitry Andric SHOWNEWBLK(CloneMBB, "result of Cloned block: ");
151181ad6265SDimitry Andric
151281ad6265SDimitry Andric return CloneMBB;
151381ad6265SDimitry Andric }
151481ad6265SDimitry Andric
migrateInstruction(MachineBasicBlock * SrcMBB,MachineBasicBlock * DstMBB,MachineBasicBlock::iterator I)151581ad6265SDimitry Andric void R600MachineCFGStructurizer::migrateInstruction(MachineBasicBlock *SrcMBB,
151681ad6265SDimitry Andric MachineBasicBlock *DstMBB, MachineBasicBlock::iterator I) {
151781ad6265SDimitry Andric MachineBasicBlock::iterator SpliceEnd;
151881ad6265SDimitry Andric //look for the input branchinstr, not the AMDGPU branchinstr
151981ad6265SDimitry Andric MachineInstr *BranchMI = getNormalBlockBranchInstr(SrcMBB);
152081ad6265SDimitry Andric if (!BranchMI) {
152181ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "migrateInstruction don't see branch instr\n";);
152281ad6265SDimitry Andric SpliceEnd = SrcMBB->end();
152381ad6265SDimitry Andric } else {
152481ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "migrateInstruction see branch instr: " << *BranchMI);
152581ad6265SDimitry Andric SpliceEnd = BranchMI;
152681ad6265SDimitry Andric }
152781ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "migrateInstruction before splice dstSize = "
152881ad6265SDimitry Andric << DstMBB->size() << "srcSize = " << SrcMBB->size()
152981ad6265SDimitry Andric << "\n";);
153081ad6265SDimitry Andric
153181ad6265SDimitry Andric //splice insert before insertPos
153281ad6265SDimitry Andric DstMBB->splice(I, SrcMBB, SrcMBB->begin(), SpliceEnd);
153381ad6265SDimitry Andric
153481ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "migrateInstruction after splice dstSize = "
153581ad6265SDimitry Andric << DstMBB->size() << "srcSize = " << SrcMBB->size()
153681ad6265SDimitry Andric << '\n';);
153781ad6265SDimitry Andric }
153881ad6265SDimitry Andric
153981ad6265SDimitry Andric MachineBasicBlock *
normalizeInfiniteLoopExit(MachineLoop * LoopRep)154081ad6265SDimitry Andric R600MachineCFGStructurizer::normalizeInfiniteLoopExit(MachineLoop* LoopRep) {
154181ad6265SDimitry Andric MachineBasicBlock *LoopHeader = LoopRep->getHeader();
154281ad6265SDimitry Andric MachineBasicBlock *LoopLatch = LoopRep->getLoopLatch();
154381ad6265SDimitry Andric
154481ad6265SDimitry Andric if (!LoopHeader || !LoopLatch)
154581ad6265SDimitry Andric return nullptr;
154681ad6265SDimitry Andric MachineInstr *BranchMI = getLoopendBlockBranchInstr(LoopLatch);
154781ad6265SDimitry Andric // Is LoopRep an infinite loop ?
154881ad6265SDimitry Andric if (!BranchMI || !isUncondBranch(BranchMI))
154981ad6265SDimitry Andric return nullptr;
155081ad6265SDimitry Andric
155181ad6265SDimitry Andric MachineBasicBlock *DummyExitBlk = FuncRep->CreateMachineBasicBlock();
155281ad6265SDimitry Andric FuncRep->push_back(DummyExitBlk); //insert to function
155381ad6265SDimitry Andric SHOWNEWBLK(DummyExitBlk, "DummyExitBlock to normalize infiniteLoop: ");
155481ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Old branch instr: " << *BranchMI << "\n";);
155581ad6265SDimitry Andric LLVMContext &Ctx = LoopHeader->getParent()->getFunction().getContext();
155681ad6265SDimitry Andric Ctx.emitError("Extra register needed to handle CFG");
155781ad6265SDimitry Andric return nullptr;
155881ad6265SDimitry Andric }
155981ad6265SDimitry Andric
removeUnconditionalBranch(MachineBasicBlock * MBB)156081ad6265SDimitry Andric void R600MachineCFGStructurizer::removeUnconditionalBranch(MachineBasicBlock *MBB) {
156181ad6265SDimitry Andric MachineInstr *BranchMI;
156281ad6265SDimitry Andric
156381ad6265SDimitry Andric // I saw two unconditional branch in one basic block in example
156481ad6265SDimitry Andric // test_fc_do_while_or.c need to fix the upstream on this to remove the loop.
156581ad6265SDimitry Andric while ((BranchMI = getLoopendBlockBranchInstr(MBB))
156681ad6265SDimitry Andric && isUncondBranch(BranchMI)) {
156781ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Removing uncond branch instr: " << *BranchMI);
156881ad6265SDimitry Andric BranchMI->eraseFromParent();
156981ad6265SDimitry Andric }
157081ad6265SDimitry Andric }
157181ad6265SDimitry Andric
removeRedundantConditionalBranch(MachineBasicBlock * MBB)157281ad6265SDimitry Andric void R600MachineCFGStructurizer::removeRedundantConditionalBranch(
157381ad6265SDimitry Andric MachineBasicBlock *MBB) {
157481ad6265SDimitry Andric if (MBB->succ_size() != 2)
157581ad6265SDimitry Andric return;
157681ad6265SDimitry Andric MachineBasicBlock *MBB1 = *MBB->succ_begin();
157781ad6265SDimitry Andric MachineBasicBlock *MBB2 = *std::next(MBB->succ_begin());
157881ad6265SDimitry Andric if (MBB1 != MBB2)
157981ad6265SDimitry Andric return;
158081ad6265SDimitry Andric
158181ad6265SDimitry Andric MachineInstr *BranchMI = getNormalBlockBranchInstr(MBB);
158281ad6265SDimitry Andric assert(BranchMI && isCondBranch(BranchMI));
158381ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Removing unneeded cond branch instr: " << *BranchMI);
158481ad6265SDimitry Andric BranchMI->eraseFromParent();
158581ad6265SDimitry Andric SHOWNEWBLK(MBB1, "Removing redundant successor");
158681ad6265SDimitry Andric MBB->removeSuccessor(MBB1, true);
158781ad6265SDimitry Andric }
158881ad6265SDimitry Andric
addDummyExitBlock(SmallVectorImpl<MachineBasicBlock * > & RetMBB)158981ad6265SDimitry Andric void R600MachineCFGStructurizer::addDummyExitBlock(
159081ad6265SDimitry Andric SmallVectorImpl<MachineBasicBlock*> &RetMBB) {
159181ad6265SDimitry Andric MachineBasicBlock *DummyExitBlk = FuncRep->CreateMachineBasicBlock();
159281ad6265SDimitry Andric FuncRep->push_back(DummyExitBlk); //insert to function
159381ad6265SDimitry Andric insertInstrEnd(DummyExitBlk, R600::RETURN);
159481ad6265SDimitry Andric
159581ad6265SDimitry Andric for (MachineBasicBlock *MBB : RetMBB) {
159681ad6265SDimitry Andric if (MachineInstr *MI = getReturnInstr(MBB))
159781ad6265SDimitry Andric MI->eraseFromParent();
159881ad6265SDimitry Andric MBB->addSuccessor(DummyExitBlk);
159981ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Add dummyExitBlock to BB" << MBB->getNumber()
160081ad6265SDimitry Andric << " successors\n";);
160181ad6265SDimitry Andric }
160281ad6265SDimitry Andric SHOWNEWBLK(DummyExitBlk, "DummyExitBlock: ");
160381ad6265SDimitry Andric }
160481ad6265SDimitry Andric
removeSuccessor(MachineBasicBlock * MBB)160581ad6265SDimitry Andric void R600MachineCFGStructurizer::removeSuccessor(MachineBasicBlock *MBB) {
160681ad6265SDimitry Andric while (MBB->succ_size())
160781ad6265SDimitry Andric MBB->removeSuccessor(*MBB->succ_begin());
160881ad6265SDimitry Andric }
160981ad6265SDimitry Andric
recordSccnum(MachineBasicBlock * MBB,int SccNum)161081ad6265SDimitry Andric void R600MachineCFGStructurizer::recordSccnum(MachineBasicBlock *MBB,
161181ad6265SDimitry Andric int SccNum) {
161281ad6265SDimitry Andric BlockInformation *&srcBlkInfo = BlockInfoMap[MBB];
161381ad6265SDimitry Andric if (!srcBlkInfo)
161481ad6265SDimitry Andric srcBlkInfo = new BlockInformation();
161581ad6265SDimitry Andric srcBlkInfo->SccNum = SccNum;
161681ad6265SDimitry Andric }
161781ad6265SDimitry Andric
retireBlock(MachineBasicBlock * MBB)161881ad6265SDimitry Andric void R600MachineCFGStructurizer::retireBlock(MachineBasicBlock *MBB) {
161981ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Retiring BB" << MBB->getNumber() << "\n";);
162081ad6265SDimitry Andric
162181ad6265SDimitry Andric BlockInformation *&SrcBlkInfo = BlockInfoMap[MBB];
162281ad6265SDimitry Andric
162381ad6265SDimitry Andric if (!SrcBlkInfo)
162481ad6265SDimitry Andric SrcBlkInfo = new BlockInformation();
162581ad6265SDimitry Andric
162681ad6265SDimitry Andric SrcBlkInfo->IsRetired = true;
162781ad6265SDimitry Andric assert(MBB->succ_empty() && MBB->pred_empty() && "can't retire block yet");
162881ad6265SDimitry Andric }
162981ad6265SDimitry Andric
163081ad6265SDimitry Andric INITIALIZE_PASS_BEGIN(R600MachineCFGStructurizer, "amdgpustructurizer",
163181ad6265SDimitry Andric "AMDGPU CFG Structurizer", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)1632*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
1633*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTreeWrapperPass)
1634*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
163581ad6265SDimitry Andric INITIALIZE_PASS_END(R600MachineCFGStructurizer, "amdgpustructurizer",
163681ad6265SDimitry Andric "AMDGPU CFG Structurizer", false, false)
163781ad6265SDimitry Andric
163881ad6265SDimitry Andric FunctionPass *llvm::createR600MachineCFGStructurizerPass() {
163981ad6265SDimitry Andric return new R600MachineCFGStructurizer();
164081ad6265SDimitry Andric }
1641