xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/R600MachineCFGStructurizer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
10781ad6265SDimitry Andric   R600MachineCFGStructurizer() : MachineFunctionPass(ID) {
10881ad6265SDimitry Andric     initializeR600MachineCFGStructurizerPass(*PassRegistry::getPassRegistry());
10981ad6265SDimitry Andric   }
11081ad6265SDimitry Andric 
11181ad6265SDimitry Andric   StringRef getPassName() const override {
11281ad6265SDimitry Andric     return "AMDGPU Control Flow Graph structurizer Pass";
11381ad6265SDimitry Andric   }
11481ad6265SDimitry Andric 
11581ad6265SDimitry 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 
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.
16281ad6265SDimitry 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 
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 
32381ad6265SDimitry 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 
33081ad6265SDimitry 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 
33881ad6265SDimitry 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 
34681ad6265SDimitry 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 
35381ad6265SDimitry 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 
36681ad6265SDimitry 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 
38481ad6265SDimitry 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 
39581ad6265SDimitry 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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
53281ad6265SDimitry Andric MachineBasicBlock *R600MachineCFGStructurizer::getTrueBranch(MachineInstr *MI) {
53381ad6265SDimitry Andric   return MI->getOperand(0).getMBB();
53481ad6265SDimitry Andric }
53581ad6265SDimitry Andric 
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 *
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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
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 
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 
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 
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 
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 
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 
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 
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 *
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 
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 *
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 
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 
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 
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 
160581ad6265SDimitry Andric void R600MachineCFGStructurizer::removeSuccessor(MachineBasicBlock *MBB) {
160681ad6265SDimitry Andric   while (MBB->succ_size())
160781ad6265SDimitry Andric     MBB->removeSuccessor(*MBB->succ_begin());
160881ad6265SDimitry Andric }
160981ad6265SDimitry Andric 
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 
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)
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