xref: /aosp_15_r20/external/llvm/lib/Target/AMDGPU/AMDILCFGStructurizer.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- AMDILCFGStructurizer.cpp - CFG Structurizer -----------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker /// \file
9*9880d681SAndroid Build Coastguard Worker //==-----------------------------------------------------------------------===//
10*9880d681SAndroid Build Coastguard Worker 
11*9880d681SAndroid Build Coastguard Worker #include "AMDGPU.h"
12*9880d681SAndroid Build Coastguard Worker #include "AMDGPUInstrInfo.h"
13*9880d681SAndroid Build Coastguard Worker #include "AMDGPUSubtarget.h"
14*9880d681SAndroid Build Coastguard Worker #include "R600InstrInfo.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DepthFirstIterator.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SCCIterator.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallVector.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineDominators.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionAnalysis.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineJumpTableInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineLoopInfo.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachinePostDominators.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Dominators.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
33*9880d681SAndroid Build Coastguard Worker #include <deque>
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker using namespace llvm;
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "structcfg"
38*9880d681SAndroid Build Coastguard Worker 
39*9880d681SAndroid Build Coastguard Worker #define DEFAULT_VEC_SLOTS 8
40*9880d681SAndroid Build Coastguard Worker 
41*9880d681SAndroid Build Coastguard Worker // TODO: move-begin.
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
44*9880d681SAndroid Build Coastguard Worker //
45*9880d681SAndroid Build Coastguard Worker // Statistics for CFGStructurizer.
46*9880d681SAndroid Build Coastguard Worker //
47*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker STATISTIC(numSerialPatternMatch,    "CFGStructurizer number of serial pattern "
50*9880d681SAndroid Build Coastguard Worker     "matched");
51*9880d681SAndroid Build Coastguard Worker STATISTIC(numIfPatternMatch,        "CFGStructurizer number of if pattern "
52*9880d681SAndroid Build Coastguard Worker     "matched");
53*9880d681SAndroid Build Coastguard Worker STATISTIC(numClonedBlock,           "CFGStructurizer cloned blocks");
54*9880d681SAndroid Build Coastguard Worker STATISTIC(numClonedInstr,           "CFGStructurizer cloned instructions");
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker namespace llvm {
57*9880d681SAndroid Build Coastguard Worker   void initializeAMDGPUCFGStructurizerPass(PassRegistry&);
58*9880d681SAndroid Build Coastguard Worker }
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
61*9880d681SAndroid Build Coastguard Worker //
62*9880d681SAndroid Build Coastguard Worker // Miscellaneous utility for CFGStructurizer.
63*9880d681SAndroid Build Coastguard Worker //
64*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
65*9880d681SAndroid Build Coastguard Worker namespace {
66*9880d681SAndroid Build Coastguard Worker #define SHOWNEWINSTR(i) \
67*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "New instr: " << *i << "\n");
68*9880d681SAndroid Build Coastguard Worker 
69*9880d681SAndroid Build Coastguard Worker #define SHOWNEWBLK(b, msg) \
70*9880d681SAndroid Build Coastguard Worker DEBUG( \
71*9880d681SAndroid Build Coastguard Worker   dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
72*9880d681SAndroid Build Coastguard Worker   dbgs() << "\n"; \
73*9880d681SAndroid Build Coastguard Worker );
74*9880d681SAndroid Build Coastguard Worker 
75*9880d681SAndroid Build Coastguard Worker #define SHOWBLK_DETAIL(b, msg) \
76*9880d681SAndroid Build Coastguard Worker DEBUG( \
77*9880d681SAndroid Build Coastguard Worker   if (b) { \
78*9880d681SAndroid Build Coastguard Worker   dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
79*9880d681SAndroid Build Coastguard Worker   b->print(dbgs()); \
80*9880d681SAndroid Build Coastguard Worker   dbgs() << "\n"; \
81*9880d681SAndroid Build Coastguard Worker   } \
82*9880d681SAndroid Build Coastguard Worker );
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker #define INVALIDSCCNUM -1
85*9880d681SAndroid Build Coastguard Worker 
86*9880d681SAndroid Build Coastguard Worker template<class NodeT>
ReverseVector(SmallVectorImpl<NodeT * > & Src)87*9880d681SAndroid Build Coastguard Worker void ReverseVector(SmallVectorImpl<NodeT *> &Src) {
88*9880d681SAndroid Build Coastguard Worker   size_t sz = Src.size();
89*9880d681SAndroid Build Coastguard Worker   for (size_t i = 0; i < sz/2; ++i) {
90*9880d681SAndroid Build Coastguard Worker     NodeT *t = Src[i];
91*9880d681SAndroid Build Coastguard Worker     Src[i] = Src[sz - i - 1];
92*9880d681SAndroid Build Coastguard Worker     Src[sz - i - 1] = t;
93*9880d681SAndroid Build Coastguard Worker   }
94*9880d681SAndroid Build Coastguard Worker }
95*9880d681SAndroid Build Coastguard Worker 
96*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
97*9880d681SAndroid Build Coastguard Worker 
98*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
99*9880d681SAndroid Build Coastguard Worker //
100*9880d681SAndroid Build Coastguard Worker // supporting data structure for CFGStructurizer
101*9880d681SAndroid Build Coastguard Worker //
102*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker 
105*9880d681SAndroid Build Coastguard Worker namespace {
106*9880d681SAndroid Build Coastguard Worker 
107*9880d681SAndroid Build Coastguard Worker class BlockInformation {
108*9880d681SAndroid Build Coastguard Worker public:
109*9880d681SAndroid Build Coastguard Worker   bool IsRetired;
110*9880d681SAndroid Build Coastguard Worker   int  SccNum;
BlockInformation()111*9880d681SAndroid Build Coastguard Worker   BlockInformation() : IsRetired(false), SccNum(INVALIDSCCNUM) {}
112*9880d681SAndroid Build Coastguard Worker };
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
117*9880d681SAndroid Build Coastguard Worker //
118*9880d681SAndroid Build Coastguard Worker // CFGStructurizer
119*9880d681SAndroid Build Coastguard Worker //
120*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker namespace {
123*9880d681SAndroid Build Coastguard Worker class AMDGPUCFGStructurizer : public MachineFunctionPass {
124*9880d681SAndroid Build Coastguard Worker public:
125*9880d681SAndroid Build Coastguard Worker   typedef SmallVector<MachineBasicBlock *, 32> MBBVector;
126*9880d681SAndroid Build Coastguard Worker   typedef std::map<MachineBasicBlock *, BlockInformation *> MBBInfoMap;
127*9880d681SAndroid Build Coastguard Worker   typedef std::map<MachineLoop *, MachineBasicBlock *> LoopLandInfoMap;
128*9880d681SAndroid Build Coastguard Worker 
129*9880d681SAndroid Build Coastguard Worker   enum PathToKind {
130*9880d681SAndroid Build Coastguard Worker     Not_SinglePath = 0,
131*9880d681SAndroid Build Coastguard Worker     SinglePath_InPath = 1,
132*9880d681SAndroid Build Coastguard Worker     SinglePath_NotInPath = 2
133*9880d681SAndroid Build Coastguard Worker   };
134*9880d681SAndroid Build Coastguard Worker 
135*9880d681SAndroid Build Coastguard Worker   static char ID;
136*9880d681SAndroid Build Coastguard Worker 
AMDGPUCFGStructurizer()137*9880d681SAndroid Build Coastguard Worker   AMDGPUCFGStructurizer() :
138*9880d681SAndroid Build Coastguard Worker       MachineFunctionPass(ID), TII(nullptr), TRI(nullptr) {
139*9880d681SAndroid Build Coastguard Worker     initializeAMDGPUCFGStructurizerPass(*PassRegistry::getPassRegistry());
140*9880d681SAndroid Build Coastguard Worker   }
141*9880d681SAndroid Build Coastguard Worker 
getPassName() const142*9880d681SAndroid Build Coastguard Worker    const char *getPassName() const override {
143*9880d681SAndroid Build Coastguard Worker     return "AMDGPU Control Flow Graph structurizer Pass";
144*9880d681SAndroid Build Coastguard Worker   }
145*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const146*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage &AU) const override {
147*9880d681SAndroid Build Coastguard Worker     AU.addPreserved<MachineFunctionAnalysis>();
148*9880d681SAndroid Build Coastguard Worker     AU.addRequired<MachineFunctionAnalysis>();
149*9880d681SAndroid Build Coastguard Worker     AU.addRequired<MachineDominatorTree>();
150*9880d681SAndroid Build Coastguard Worker     AU.addRequired<MachinePostDominatorTree>();
151*9880d681SAndroid Build Coastguard Worker     AU.addRequired<MachineLoopInfo>();
152*9880d681SAndroid Build Coastguard Worker   }
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker   /// Perform the CFG structurization
155*9880d681SAndroid Build Coastguard Worker   bool run();
156*9880d681SAndroid Build Coastguard Worker 
157*9880d681SAndroid Build Coastguard Worker   /// Perform the CFG preparation
158*9880d681SAndroid Build Coastguard Worker   /// This step will remove every unconditionnal/dead jump instructions and make
159*9880d681SAndroid Build Coastguard Worker   /// sure all loops have an exit block
160*9880d681SAndroid Build Coastguard Worker   bool prepare();
161*9880d681SAndroid Build Coastguard Worker 
runOnMachineFunction(MachineFunction & MF)162*9880d681SAndroid Build Coastguard Worker   bool runOnMachineFunction(MachineFunction &MF) override {
163*9880d681SAndroid Build Coastguard Worker     TII = MF.getSubtarget<R600Subtarget>().getInstrInfo();
164*9880d681SAndroid Build Coastguard Worker     TRI = &TII->getRegisterInfo();
165*9880d681SAndroid Build Coastguard Worker     DEBUG(MF.dump(););
166*9880d681SAndroid Build Coastguard Worker     OrderedBlks.clear();
167*9880d681SAndroid Build Coastguard Worker     Visited.clear();
168*9880d681SAndroid Build Coastguard Worker     FuncRep = &MF;
169*9880d681SAndroid Build Coastguard Worker     MLI = &getAnalysis<MachineLoopInfo>();
170*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "LoopInfo:\n"; PrintLoopinfo(*MLI););
171*9880d681SAndroid Build Coastguard Worker     MDT = &getAnalysis<MachineDominatorTree>();
172*9880d681SAndroid Build Coastguard Worker     DEBUG(MDT->print(dbgs(), (const llvm::Module*)nullptr););
173*9880d681SAndroid Build Coastguard Worker     PDT = &getAnalysis<MachinePostDominatorTree>();
174*9880d681SAndroid Build Coastguard Worker     DEBUG(PDT->print(dbgs()););
175*9880d681SAndroid Build Coastguard Worker     prepare();
176*9880d681SAndroid Build Coastguard Worker     run();
177*9880d681SAndroid Build Coastguard Worker     DEBUG(MF.dump(););
178*9880d681SAndroid Build Coastguard Worker     return true;
179*9880d681SAndroid Build Coastguard Worker   }
180*9880d681SAndroid Build Coastguard Worker 
181*9880d681SAndroid Build Coastguard Worker protected:
182*9880d681SAndroid Build Coastguard Worker   MachineDominatorTree *MDT;
183*9880d681SAndroid Build Coastguard Worker   MachinePostDominatorTree *PDT;
184*9880d681SAndroid Build Coastguard Worker   MachineLoopInfo *MLI;
185*9880d681SAndroid Build Coastguard Worker   const R600InstrInfo *TII;
186*9880d681SAndroid Build Coastguard Worker   const R600RegisterInfo *TRI;
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker   // PRINT FUNCTIONS
189*9880d681SAndroid Build Coastguard Worker   /// Print the ordered Blocks.
printOrderedBlocks() const190*9880d681SAndroid Build Coastguard Worker   void printOrderedBlocks() const {
191*9880d681SAndroid Build Coastguard Worker     size_t i = 0;
192*9880d681SAndroid Build Coastguard Worker     for (MBBVector::const_iterator iterBlk = OrderedBlks.begin(),
193*9880d681SAndroid Build Coastguard Worker         iterBlkEnd = OrderedBlks.end(); iterBlk != iterBlkEnd; ++iterBlk, ++i) {
194*9880d681SAndroid Build Coastguard Worker       dbgs() << "BB" << (*iterBlk)->getNumber();
195*9880d681SAndroid Build Coastguard Worker       dbgs() << "(" << getSCCNum(*iterBlk) << "," << (*iterBlk)->size() << ")";
196*9880d681SAndroid Build Coastguard Worker       if (i != 0 && i % 10 == 0) {
197*9880d681SAndroid Build Coastguard Worker         dbgs() << "\n";
198*9880d681SAndroid Build Coastguard Worker       } else {
199*9880d681SAndroid Build Coastguard Worker         dbgs() << " ";
200*9880d681SAndroid Build Coastguard Worker       }
201*9880d681SAndroid Build Coastguard Worker     }
202*9880d681SAndroid Build Coastguard Worker   }
PrintLoopinfo(const MachineLoopInfo & LoopInfo)203*9880d681SAndroid Build Coastguard Worker   static void PrintLoopinfo(const MachineLoopInfo &LoopInfo) {
204*9880d681SAndroid Build Coastguard Worker     for (MachineLoop::iterator iter = LoopInfo.begin(),
205*9880d681SAndroid Build Coastguard Worker          iterEnd = LoopInfo.end(); iter != iterEnd; ++iter) {
206*9880d681SAndroid Build Coastguard Worker       (*iter)->print(dbgs(), 0);
207*9880d681SAndroid Build Coastguard Worker     }
208*9880d681SAndroid Build Coastguard Worker   }
209*9880d681SAndroid Build Coastguard Worker 
210*9880d681SAndroid Build Coastguard Worker   // UTILITY FUNCTIONS
211*9880d681SAndroid Build Coastguard Worker   int getSCCNum(MachineBasicBlock *MBB) const;
212*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *getLoopLandInfo(MachineLoop *LoopRep) const;
213*9880d681SAndroid Build Coastguard Worker   bool hasBackEdge(MachineBasicBlock *MBB) const;
214*9880d681SAndroid Build Coastguard Worker   bool isRetiredBlock(MachineBasicBlock *MBB) const;
215*9880d681SAndroid Build Coastguard Worker   bool isActiveLoophead(MachineBasicBlock *MBB) const;
216*9880d681SAndroid Build Coastguard Worker   PathToKind singlePathTo(MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
217*9880d681SAndroid Build Coastguard Worker       bool AllowSideEntry = true) const;
218*9880d681SAndroid Build Coastguard Worker   int countActiveBlock(MBBVector::const_iterator It,
219*9880d681SAndroid Build Coastguard Worker       MBBVector::const_iterator E) const;
220*9880d681SAndroid Build Coastguard Worker   bool needMigrateBlock(MachineBasicBlock *MBB) const;
221*9880d681SAndroid Build Coastguard Worker 
222*9880d681SAndroid Build Coastguard Worker   // Utility Functions
223*9880d681SAndroid Build Coastguard Worker   void reversePredicateSetter(MachineBasicBlock::iterator I);
224*9880d681SAndroid Build Coastguard Worker   /// Compute the reversed DFS post order of Blocks
225*9880d681SAndroid Build Coastguard Worker   void orderBlocks(MachineFunction *MF);
226*9880d681SAndroid Build Coastguard Worker 
227*9880d681SAndroid Build Coastguard Worker   // Function originally from CFGStructTraits
228*9880d681SAndroid Build Coastguard Worker   void insertInstrEnd(MachineBasicBlock *MBB, int NewOpcode,
229*9880d681SAndroid Build Coastguard Worker                       const DebugLoc &DL = DebugLoc());
230*9880d681SAndroid Build Coastguard Worker   MachineInstr *insertInstrBefore(MachineBasicBlock *MBB, int NewOpcode,
231*9880d681SAndroid Build Coastguard Worker                                   const DebugLoc &DL = DebugLoc());
232*9880d681SAndroid Build Coastguard Worker   MachineInstr *insertInstrBefore(MachineBasicBlock::iterator I, int NewOpcode);
233*9880d681SAndroid Build Coastguard Worker   void insertCondBranchBefore(MachineBasicBlock::iterator I, int NewOpcode,
234*9880d681SAndroid Build Coastguard Worker                               const DebugLoc &DL);
235*9880d681SAndroid Build Coastguard Worker   void insertCondBranchBefore(MachineBasicBlock *MBB,
236*9880d681SAndroid Build Coastguard Worker                               MachineBasicBlock::iterator I, int NewOpcode,
237*9880d681SAndroid Build Coastguard Worker                               int RegNum, const DebugLoc &DL);
238*9880d681SAndroid Build Coastguard Worker   static int getBranchNzeroOpcode(int OldOpcode);
239*9880d681SAndroid Build Coastguard Worker   static int getBranchZeroOpcode(int OldOpcode);
240*9880d681SAndroid Build Coastguard Worker   static int getContinueNzeroOpcode(int OldOpcode);
241*9880d681SAndroid Build Coastguard Worker   static int getContinueZeroOpcode(int OldOpcode);
242*9880d681SAndroid Build Coastguard Worker   static MachineBasicBlock *getTrueBranch(MachineInstr *MI);
243*9880d681SAndroid Build Coastguard Worker   static void setTrueBranch(MachineInstr *MI, MachineBasicBlock *MBB);
244*9880d681SAndroid Build Coastguard Worker   static MachineBasicBlock *getFalseBranch(MachineBasicBlock *MBB,
245*9880d681SAndroid Build Coastguard Worker       MachineInstr *MI);
246*9880d681SAndroid Build Coastguard Worker   static bool isCondBranch(MachineInstr *MI);
247*9880d681SAndroid Build Coastguard Worker   static bool isUncondBranch(MachineInstr *MI);
248*9880d681SAndroid Build Coastguard Worker   static DebugLoc getLastDebugLocInBB(MachineBasicBlock *MBB);
249*9880d681SAndroid Build Coastguard Worker   static MachineInstr *getNormalBlockBranchInstr(MachineBasicBlock *MBB);
250*9880d681SAndroid Build Coastguard Worker   /// The correct naming for this is getPossibleLoopendBlockBranchInstr.
251*9880d681SAndroid Build Coastguard Worker   ///
252*9880d681SAndroid Build Coastguard Worker   /// BB with backward-edge could have move instructions after the branch
253*9880d681SAndroid Build Coastguard Worker   /// instruction.  Such move instruction "belong to" the loop backward-edge.
254*9880d681SAndroid Build Coastguard Worker   MachineInstr *getLoopendBlockBranchInstr(MachineBasicBlock *MBB);
255*9880d681SAndroid Build Coastguard Worker   static MachineInstr *getReturnInstr(MachineBasicBlock *MBB);
256*9880d681SAndroid Build Coastguard Worker   static bool isReturnBlock(MachineBasicBlock *MBB);
257*9880d681SAndroid Build Coastguard Worker   static void cloneSuccessorList(MachineBasicBlock *DstMBB,
258*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *SrcMBB) ;
259*9880d681SAndroid Build Coastguard Worker   static MachineBasicBlock *clone(MachineBasicBlock *MBB);
260*9880d681SAndroid Build Coastguard Worker   /// MachineBasicBlock::ReplaceUsesOfBlockWith doesn't serve the purpose
261*9880d681SAndroid Build Coastguard Worker   /// because the AMDGPU instruction is not recognized as terminator fix this
262*9880d681SAndroid Build Coastguard Worker   /// and retire this routine
263*9880d681SAndroid Build Coastguard Worker   void replaceInstrUseOfBlockWith(MachineBasicBlock *SrcMBB,
264*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *OldMBB, MachineBasicBlock *NewBlk);
265*9880d681SAndroid Build Coastguard Worker   static void wrapup(MachineBasicBlock *MBB);
266*9880d681SAndroid Build Coastguard Worker 
267*9880d681SAndroid Build Coastguard Worker 
268*9880d681SAndroid Build Coastguard Worker   int patternMatch(MachineBasicBlock *MBB);
269*9880d681SAndroid Build Coastguard Worker   int patternMatchGroup(MachineBasicBlock *MBB);
270*9880d681SAndroid Build Coastguard Worker   int serialPatternMatch(MachineBasicBlock *MBB);
271*9880d681SAndroid Build Coastguard Worker   int ifPatternMatch(MachineBasicBlock *MBB);
272*9880d681SAndroid Build Coastguard Worker   int loopendPatternMatch();
273*9880d681SAndroid Build Coastguard Worker   int mergeLoop(MachineLoop *LoopRep);
274*9880d681SAndroid Build Coastguard Worker 
275*9880d681SAndroid Build Coastguard Worker   /// return true iff src1Blk->succ_size() == 0 && src1Blk and src2Blk are in
276*9880d681SAndroid Build Coastguard Worker   /// the same loop with LoopLandInfo without explicitly keeping track of
277*9880d681SAndroid Build Coastguard Worker   /// loopContBlks and loopBreakBlks, this is a method to get the information.
278*9880d681SAndroid Build Coastguard Worker   bool isSameloopDetachedContbreak(MachineBasicBlock *Src1MBB,
279*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *Src2MBB);
280*9880d681SAndroid Build Coastguard Worker   int handleJumpintoIf(MachineBasicBlock *HeadMBB,
281*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
282*9880d681SAndroid Build Coastguard Worker   int handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
283*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
284*9880d681SAndroid Build Coastguard Worker   int improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
285*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
286*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock **LandMBBPtr);
287*9880d681SAndroid Build Coastguard Worker   void showImproveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
288*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
289*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *LandMBB, bool Detail = false);
290*9880d681SAndroid Build Coastguard Worker   int cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
291*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB);
292*9880d681SAndroid Build Coastguard Worker   void mergeSerialBlock(MachineBasicBlock *DstMBB,
293*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *SrcMBB);
294*9880d681SAndroid Build Coastguard Worker 
295*9880d681SAndroid Build Coastguard Worker   void mergeIfthenelseBlock(MachineInstr *BranchMI,
296*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *MBB, MachineBasicBlock *TrueMBB,
297*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB);
298*9880d681SAndroid Build Coastguard Worker   void mergeLooplandBlock(MachineBasicBlock *DstMBB,
299*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *LandMBB);
300*9880d681SAndroid Build Coastguard Worker   void mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
301*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *LandMBB);
302*9880d681SAndroid Build Coastguard Worker   void settleLoopcontBlock(MachineBasicBlock *ContingMBB,
303*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *ContMBB);
304*9880d681SAndroid Build Coastguard Worker   /// normalizeInfiniteLoopExit change
305*9880d681SAndroid Build Coastguard Worker   ///   B1:
306*9880d681SAndroid Build Coastguard Worker   ///        uncond_br LoopHeader
307*9880d681SAndroid Build Coastguard Worker   ///
308*9880d681SAndroid Build Coastguard Worker   /// to
309*9880d681SAndroid Build Coastguard Worker   ///   B1:
310*9880d681SAndroid Build Coastguard Worker   ///        cond_br 1 LoopHeader dummyExit
311*9880d681SAndroid Build Coastguard Worker   /// and return the newly added dummy exit block
312*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *normalizeInfiniteLoopExit(MachineLoop *LoopRep);
313*9880d681SAndroid Build Coastguard Worker   void removeUnconditionalBranch(MachineBasicBlock *MBB);
314*9880d681SAndroid Build Coastguard Worker   /// Remove duplicate branches instructions in a block.
315*9880d681SAndroid Build Coastguard Worker   /// For instance
316*9880d681SAndroid Build Coastguard Worker   /// B0:
317*9880d681SAndroid Build Coastguard Worker   ///    cond_br X B1 B2
318*9880d681SAndroid Build Coastguard Worker   ///    cond_br X B1 B2
319*9880d681SAndroid Build Coastguard Worker   /// is transformed to
320*9880d681SAndroid Build Coastguard Worker   /// B0:
321*9880d681SAndroid Build Coastguard Worker   ///    cond_br X B1 B2
322*9880d681SAndroid Build Coastguard Worker   void removeRedundantConditionalBranch(MachineBasicBlock *MBB);
323*9880d681SAndroid Build Coastguard Worker   void addDummyExitBlock(SmallVectorImpl<MachineBasicBlock *> &RetMBB);
324*9880d681SAndroid Build Coastguard Worker   void removeSuccessor(MachineBasicBlock *MBB);
325*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *cloneBlockForPredecessor(MachineBasicBlock *MBB,
326*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *PredMBB);
327*9880d681SAndroid Build Coastguard Worker   void migrateInstruction(MachineBasicBlock *SrcMBB,
328*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *DstMBB, MachineBasicBlock::iterator I);
329*9880d681SAndroid Build Coastguard Worker   void recordSccnum(MachineBasicBlock *MBB, int SCCNum);
330*9880d681SAndroid Build Coastguard Worker   void retireBlock(MachineBasicBlock *MBB);
331*9880d681SAndroid Build Coastguard Worker 
332*9880d681SAndroid Build Coastguard Worker 
333*9880d681SAndroid Build Coastguard Worker private:
334*9880d681SAndroid Build Coastguard Worker   MBBInfoMap BlockInfoMap;
335*9880d681SAndroid Build Coastguard Worker   LoopLandInfoMap LLInfoMap;
336*9880d681SAndroid Build Coastguard Worker   std::map<MachineLoop *, bool> Visited;
337*9880d681SAndroid Build Coastguard Worker   MachineFunction *FuncRep;
338*9880d681SAndroid Build Coastguard Worker   SmallVector<MachineBasicBlock *, DEFAULT_VEC_SLOTS> OrderedBlks;
339*9880d681SAndroid Build Coastguard Worker };
340*9880d681SAndroid Build Coastguard Worker 
getSCCNum(MachineBasicBlock * MBB) const341*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::getSCCNum(MachineBasicBlock *MBB) const {
342*9880d681SAndroid Build Coastguard Worker   MBBInfoMap::const_iterator It = BlockInfoMap.find(MBB);
343*9880d681SAndroid Build Coastguard Worker   if (It == BlockInfoMap.end())
344*9880d681SAndroid Build Coastguard Worker     return INVALIDSCCNUM;
345*9880d681SAndroid Build Coastguard Worker   return (*It).second->SccNum;
346*9880d681SAndroid Build Coastguard Worker }
347*9880d681SAndroid Build Coastguard Worker 
getLoopLandInfo(MachineLoop * LoopRep) const348*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *AMDGPUCFGStructurizer::getLoopLandInfo(MachineLoop *LoopRep)
349*9880d681SAndroid Build Coastguard Worker     const {
350*9880d681SAndroid Build Coastguard Worker   LoopLandInfoMap::const_iterator It = LLInfoMap.find(LoopRep);
351*9880d681SAndroid Build Coastguard Worker   if (It == LLInfoMap.end())
352*9880d681SAndroid Build Coastguard Worker     return nullptr;
353*9880d681SAndroid Build Coastguard Worker   return (*It).second;
354*9880d681SAndroid Build Coastguard Worker }
355*9880d681SAndroid Build Coastguard Worker 
hasBackEdge(MachineBasicBlock * MBB) const356*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::hasBackEdge(MachineBasicBlock *MBB) const {
357*9880d681SAndroid Build Coastguard Worker   MachineLoop *LoopRep = MLI->getLoopFor(MBB);
358*9880d681SAndroid Build Coastguard Worker   if (!LoopRep)
359*9880d681SAndroid Build Coastguard Worker     return false;
360*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *LoopHeader = LoopRep->getHeader();
361*9880d681SAndroid Build Coastguard Worker   return MBB->isSuccessor(LoopHeader);
362*9880d681SAndroid Build Coastguard Worker }
363*9880d681SAndroid Build Coastguard Worker 
isRetiredBlock(MachineBasicBlock * MBB) const364*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::isRetiredBlock(MachineBasicBlock *MBB) const {
365*9880d681SAndroid Build Coastguard Worker   MBBInfoMap::const_iterator It = BlockInfoMap.find(MBB);
366*9880d681SAndroid Build Coastguard Worker   if (It == BlockInfoMap.end())
367*9880d681SAndroid Build Coastguard Worker     return false;
368*9880d681SAndroid Build Coastguard Worker   return (*It).second->IsRetired;
369*9880d681SAndroid Build Coastguard Worker }
370*9880d681SAndroid Build Coastguard Worker 
isActiveLoophead(MachineBasicBlock * MBB) const371*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::isActiveLoophead(MachineBasicBlock *MBB) const {
372*9880d681SAndroid Build Coastguard Worker   MachineLoop *LoopRep = MLI->getLoopFor(MBB);
373*9880d681SAndroid Build Coastguard Worker   while (LoopRep && LoopRep->getHeader() == MBB) {
374*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *LoopLand = getLoopLandInfo(LoopRep);
375*9880d681SAndroid Build Coastguard Worker     if(!LoopLand)
376*9880d681SAndroid Build Coastguard Worker       return true;
377*9880d681SAndroid Build Coastguard Worker     if (!isRetiredBlock(LoopLand))
378*9880d681SAndroid Build Coastguard Worker       return true;
379*9880d681SAndroid Build Coastguard Worker     LoopRep = LoopRep->getParentLoop();
380*9880d681SAndroid Build Coastguard Worker   }
381*9880d681SAndroid Build Coastguard Worker   return false;
382*9880d681SAndroid Build Coastguard Worker }
singlePathTo(MachineBasicBlock * SrcMBB,MachineBasicBlock * DstMBB,bool AllowSideEntry) const383*9880d681SAndroid Build Coastguard Worker AMDGPUCFGStructurizer::PathToKind AMDGPUCFGStructurizer::singlePathTo(
384*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
385*9880d681SAndroid Build Coastguard Worker     bool AllowSideEntry) const {
386*9880d681SAndroid Build Coastguard Worker   assert(DstMBB);
387*9880d681SAndroid Build Coastguard Worker   if (SrcMBB == DstMBB)
388*9880d681SAndroid Build Coastguard Worker     return SinglePath_InPath;
389*9880d681SAndroid Build Coastguard Worker   while (SrcMBB && SrcMBB->succ_size() == 1) {
390*9880d681SAndroid Build Coastguard Worker     SrcMBB = *SrcMBB->succ_begin();
391*9880d681SAndroid Build Coastguard Worker     if (SrcMBB == DstMBB)
392*9880d681SAndroid Build Coastguard Worker       return SinglePath_InPath;
393*9880d681SAndroid Build Coastguard Worker     if (!AllowSideEntry && SrcMBB->pred_size() > 1)
394*9880d681SAndroid Build Coastguard Worker       return Not_SinglePath;
395*9880d681SAndroid Build Coastguard Worker   }
396*9880d681SAndroid Build Coastguard Worker   if (SrcMBB && SrcMBB->succ_size()==0)
397*9880d681SAndroid Build Coastguard Worker     return SinglePath_NotInPath;
398*9880d681SAndroid Build Coastguard Worker   return Not_SinglePath;
399*9880d681SAndroid Build Coastguard Worker }
400*9880d681SAndroid Build Coastguard Worker 
countActiveBlock(MBBVector::const_iterator It,MBBVector::const_iterator E) const401*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::countActiveBlock(MBBVector::const_iterator It,
402*9880d681SAndroid Build Coastguard Worker     MBBVector::const_iterator E) const {
403*9880d681SAndroid Build Coastguard Worker   int Count = 0;
404*9880d681SAndroid Build Coastguard Worker   while (It != E) {
405*9880d681SAndroid Build Coastguard Worker     if (!isRetiredBlock(*It))
406*9880d681SAndroid Build Coastguard Worker       ++Count;
407*9880d681SAndroid Build Coastguard Worker     ++It;
408*9880d681SAndroid Build Coastguard Worker   }
409*9880d681SAndroid Build Coastguard Worker   return Count;
410*9880d681SAndroid Build Coastguard Worker }
411*9880d681SAndroid Build Coastguard Worker 
needMigrateBlock(MachineBasicBlock * MBB) const412*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::needMigrateBlock(MachineBasicBlock *MBB) const {
413*9880d681SAndroid Build Coastguard Worker   unsigned BlockSizeThreshold = 30;
414*9880d681SAndroid Build Coastguard Worker   unsigned CloneInstrThreshold = 100;
415*9880d681SAndroid Build Coastguard Worker   bool MultiplePreds = MBB && (MBB->pred_size() > 1);
416*9880d681SAndroid Build Coastguard Worker 
417*9880d681SAndroid Build Coastguard Worker   if(!MultiplePreds)
418*9880d681SAndroid Build Coastguard Worker     return false;
419*9880d681SAndroid Build Coastguard Worker   unsigned BlkSize = MBB->size();
420*9880d681SAndroid Build Coastguard Worker   return ((BlkSize > BlockSizeThreshold) &&
421*9880d681SAndroid Build Coastguard Worker       (BlkSize * (MBB->pred_size() - 1) > CloneInstrThreshold));
422*9880d681SAndroid Build Coastguard Worker }
423*9880d681SAndroid Build Coastguard Worker 
reversePredicateSetter(MachineBasicBlock::iterator I)424*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::reversePredicateSetter(
425*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator I) {
426*9880d681SAndroid Build Coastguard Worker   assert(static_cast<MachineInstr *>(I) && "Expected valid iterator");
427*9880d681SAndroid Build Coastguard Worker   for (;; --I) {
428*9880d681SAndroid Build Coastguard Worker     if (I->getOpcode() == AMDGPU::PRED_X) {
429*9880d681SAndroid Build Coastguard Worker       switch (static_cast<MachineInstr *>(I)->getOperand(2).getImm()) {
430*9880d681SAndroid Build Coastguard Worker       case OPCODE_IS_ZERO_INT:
431*9880d681SAndroid Build Coastguard Worker         static_cast<MachineInstr *>(I)->getOperand(2)
432*9880d681SAndroid Build Coastguard Worker             .setImm(OPCODE_IS_NOT_ZERO_INT);
433*9880d681SAndroid Build Coastguard Worker         return;
434*9880d681SAndroid Build Coastguard Worker       case OPCODE_IS_NOT_ZERO_INT:
435*9880d681SAndroid Build Coastguard Worker         static_cast<MachineInstr *>(I)->getOperand(2)
436*9880d681SAndroid Build Coastguard Worker             .setImm(OPCODE_IS_ZERO_INT);
437*9880d681SAndroid Build Coastguard Worker         return;
438*9880d681SAndroid Build Coastguard Worker       case OPCODE_IS_ZERO:
439*9880d681SAndroid Build Coastguard Worker         static_cast<MachineInstr *>(I)->getOperand(2)
440*9880d681SAndroid Build Coastguard Worker             .setImm(OPCODE_IS_NOT_ZERO);
441*9880d681SAndroid Build Coastguard Worker         return;
442*9880d681SAndroid Build Coastguard Worker       case OPCODE_IS_NOT_ZERO:
443*9880d681SAndroid Build Coastguard Worker         static_cast<MachineInstr *>(I)->getOperand(2)
444*9880d681SAndroid Build Coastguard Worker             .setImm(OPCODE_IS_ZERO);
445*9880d681SAndroid Build Coastguard Worker         return;
446*9880d681SAndroid Build Coastguard Worker       default:
447*9880d681SAndroid Build Coastguard Worker         llvm_unreachable("PRED_X Opcode invalid!");
448*9880d681SAndroid Build Coastguard Worker       }
449*9880d681SAndroid Build Coastguard Worker     }
450*9880d681SAndroid Build Coastguard Worker   }
451*9880d681SAndroid Build Coastguard Worker }
452*9880d681SAndroid Build Coastguard Worker 
insertInstrEnd(MachineBasicBlock * MBB,int NewOpcode,const DebugLoc & DL)453*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::insertInstrEnd(MachineBasicBlock *MBB,
454*9880d681SAndroid Build Coastguard Worker                                            int NewOpcode, const DebugLoc &DL) {
455*9880d681SAndroid Build Coastguard Worker   MachineInstr *MI =
456*9880d681SAndroid Build Coastguard Worker       MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DL);
457*9880d681SAndroid Build Coastguard Worker   MBB->push_back(MI);
458*9880d681SAndroid Build Coastguard Worker   //assume the instruction doesn't take any reg operand ...
459*9880d681SAndroid Build Coastguard Worker   SHOWNEWINSTR(MI);
460*9880d681SAndroid Build Coastguard Worker }
461*9880d681SAndroid Build Coastguard Worker 
insertInstrBefore(MachineBasicBlock * MBB,int NewOpcode,const DebugLoc & DL)462*9880d681SAndroid Build Coastguard Worker MachineInstr *AMDGPUCFGStructurizer::insertInstrBefore(MachineBasicBlock *MBB,
463*9880d681SAndroid Build Coastguard Worker                                                        int NewOpcode,
464*9880d681SAndroid Build Coastguard Worker                                                        const DebugLoc &DL) {
465*9880d681SAndroid Build Coastguard Worker   MachineInstr *MI =
466*9880d681SAndroid Build Coastguard Worker       MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DL);
467*9880d681SAndroid Build Coastguard Worker   if (MBB->begin() != MBB->end())
468*9880d681SAndroid Build Coastguard Worker     MBB->insert(MBB->begin(), MI);
469*9880d681SAndroid Build Coastguard Worker   else
470*9880d681SAndroid Build Coastguard Worker     MBB->push_back(MI);
471*9880d681SAndroid Build Coastguard Worker   SHOWNEWINSTR(MI);
472*9880d681SAndroid Build Coastguard Worker   return MI;
473*9880d681SAndroid Build Coastguard Worker }
474*9880d681SAndroid Build Coastguard Worker 
insertInstrBefore(MachineBasicBlock::iterator I,int NewOpcode)475*9880d681SAndroid Build Coastguard Worker MachineInstr *AMDGPUCFGStructurizer::insertInstrBefore(
476*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator I, int NewOpcode) {
477*9880d681SAndroid Build Coastguard Worker   MachineInstr *OldMI = &(*I);
478*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB = OldMI->getParent();
479*9880d681SAndroid Build Coastguard Worker   MachineInstr *NewMBB =
480*9880d681SAndroid Build Coastguard Worker       MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DebugLoc());
481*9880d681SAndroid Build Coastguard Worker   MBB->insert(I, NewMBB);
482*9880d681SAndroid Build Coastguard Worker   //assume the instruction doesn't take any reg operand ...
483*9880d681SAndroid Build Coastguard Worker   SHOWNEWINSTR(NewMBB);
484*9880d681SAndroid Build Coastguard Worker   return NewMBB;
485*9880d681SAndroid Build Coastguard Worker }
486*9880d681SAndroid Build Coastguard Worker 
insertCondBranchBefore(MachineBasicBlock::iterator I,int NewOpcode,const DebugLoc & DL)487*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::insertCondBranchBefore(
488*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator I, int NewOpcode, const DebugLoc &DL) {
489*9880d681SAndroid Build Coastguard Worker   MachineInstr *OldMI = &(*I);
490*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB = OldMI->getParent();
491*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF = MBB->getParent();
492*9880d681SAndroid Build Coastguard Worker   MachineInstr *NewMI = MF->CreateMachineInstr(TII->get(NewOpcode), DL);
493*9880d681SAndroid Build Coastguard Worker   MBB->insert(I, NewMI);
494*9880d681SAndroid Build Coastguard Worker   MachineInstrBuilder MIB(*MF, NewMI);
495*9880d681SAndroid Build Coastguard Worker   MIB.addReg(OldMI->getOperand(1).getReg(), false);
496*9880d681SAndroid Build Coastguard Worker   SHOWNEWINSTR(NewMI);
497*9880d681SAndroid Build Coastguard Worker   //erase later oldInstr->eraseFromParent();
498*9880d681SAndroid Build Coastguard Worker }
499*9880d681SAndroid Build Coastguard Worker 
insertCondBranchBefore(MachineBasicBlock * blk,MachineBasicBlock::iterator I,int NewOpcode,int RegNum,const DebugLoc & DL)500*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::insertCondBranchBefore(
501*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *blk, MachineBasicBlock::iterator I, int NewOpcode,
502*9880d681SAndroid Build Coastguard Worker     int RegNum, const DebugLoc &DL) {
503*9880d681SAndroid Build Coastguard Worker   MachineFunction *MF = blk->getParent();
504*9880d681SAndroid Build Coastguard Worker   MachineInstr *NewInstr = MF->CreateMachineInstr(TII->get(NewOpcode), DL);
505*9880d681SAndroid Build Coastguard Worker   //insert before
506*9880d681SAndroid Build Coastguard Worker   blk->insert(I, NewInstr);
507*9880d681SAndroid Build Coastguard Worker   MachineInstrBuilder(*MF, NewInstr).addReg(RegNum, false);
508*9880d681SAndroid Build Coastguard Worker   SHOWNEWINSTR(NewInstr);
509*9880d681SAndroid Build Coastguard Worker }
510*9880d681SAndroid Build Coastguard Worker 
getBranchNzeroOpcode(int OldOpcode)511*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::getBranchNzeroOpcode(int OldOpcode) {
512*9880d681SAndroid Build Coastguard Worker   switch(OldOpcode) {
513*9880d681SAndroid Build Coastguard Worker   case AMDGPU::JUMP_COND:
514*9880d681SAndroid Build Coastguard Worker   case AMDGPU::JUMP: return AMDGPU::IF_PREDICATE_SET;
515*9880d681SAndroid Build Coastguard Worker   case AMDGPU::BRANCH_COND_i32:
516*9880d681SAndroid Build Coastguard Worker   case AMDGPU::BRANCH_COND_f32: return AMDGPU::IF_LOGICALNZ_f32;
517*9880d681SAndroid Build Coastguard Worker   default: llvm_unreachable("internal error");
518*9880d681SAndroid Build Coastguard Worker   }
519*9880d681SAndroid Build Coastguard Worker   return -1;
520*9880d681SAndroid Build Coastguard Worker }
521*9880d681SAndroid Build Coastguard Worker 
getBranchZeroOpcode(int OldOpcode)522*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::getBranchZeroOpcode(int OldOpcode) {
523*9880d681SAndroid Build Coastguard Worker   switch(OldOpcode) {
524*9880d681SAndroid Build Coastguard Worker   case AMDGPU::JUMP_COND:
525*9880d681SAndroid Build Coastguard Worker   case AMDGPU::JUMP: return AMDGPU::IF_PREDICATE_SET;
526*9880d681SAndroid Build Coastguard Worker   case AMDGPU::BRANCH_COND_i32:
527*9880d681SAndroid Build Coastguard Worker   case AMDGPU::BRANCH_COND_f32: return AMDGPU::IF_LOGICALZ_f32;
528*9880d681SAndroid Build Coastguard Worker   default: llvm_unreachable("internal error");
529*9880d681SAndroid Build Coastguard Worker   }
530*9880d681SAndroid Build Coastguard Worker   return -1;
531*9880d681SAndroid Build Coastguard Worker }
532*9880d681SAndroid Build Coastguard Worker 
getContinueNzeroOpcode(int OldOpcode)533*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::getContinueNzeroOpcode(int OldOpcode) {
534*9880d681SAndroid Build Coastguard Worker   switch(OldOpcode) {
535*9880d681SAndroid Build Coastguard Worker   case AMDGPU::JUMP_COND:
536*9880d681SAndroid Build Coastguard Worker   case AMDGPU::JUMP: return AMDGPU::CONTINUE_LOGICALNZ_i32;
537*9880d681SAndroid Build Coastguard Worker   default: llvm_unreachable("internal error");
538*9880d681SAndroid Build Coastguard Worker   };
539*9880d681SAndroid Build Coastguard Worker   return -1;
540*9880d681SAndroid Build Coastguard Worker }
541*9880d681SAndroid Build Coastguard Worker 
getContinueZeroOpcode(int OldOpcode)542*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::getContinueZeroOpcode(int OldOpcode) {
543*9880d681SAndroid Build Coastguard Worker   switch(OldOpcode) {
544*9880d681SAndroid Build Coastguard Worker   case AMDGPU::JUMP_COND:
545*9880d681SAndroid Build Coastguard Worker   case AMDGPU::JUMP: return AMDGPU::CONTINUE_LOGICALZ_i32;
546*9880d681SAndroid Build Coastguard Worker   default: llvm_unreachable("internal error");
547*9880d681SAndroid Build Coastguard Worker   }
548*9880d681SAndroid Build Coastguard Worker   return -1;
549*9880d681SAndroid Build Coastguard Worker }
550*9880d681SAndroid Build Coastguard Worker 
getTrueBranch(MachineInstr * MI)551*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *AMDGPUCFGStructurizer::getTrueBranch(MachineInstr *MI) {
552*9880d681SAndroid Build Coastguard Worker   return MI->getOperand(0).getMBB();
553*9880d681SAndroid Build Coastguard Worker }
554*9880d681SAndroid Build Coastguard Worker 
setTrueBranch(MachineInstr * MI,MachineBasicBlock * MBB)555*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::setTrueBranch(MachineInstr *MI,
556*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB) {
557*9880d681SAndroid Build Coastguard Worker   MI->getOperand(0).setMBB(MBB);
558*9880d681SAndroid Build Coastguard Worker }
559*9880d681SAndroid Build Coastguard Worker 
560*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *
getFalseBranch(MachineBasicBlock * MBB,MachineInstr * MI)561*9880d681SAndroid Build Coastguard Worker AMDGPUCFGStructurizer::getFalseBranch(MachineBasicBlock *MBB,
562*9880d681SAndroid Build Coastguard Worker     MachineInstr *MI) {
563*9880d681SAndroid Build Coastguard Worker   assert(MBB->succ_size() == 2);
564*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *TrueBranch = getTrueBranch(MI);
565*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::succ_iterator It = MBB->succ_begin();
566*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::succ_iterator Next = It;
567*9880d681SAndroid Build Coastguard Worker   ++Next;
568*9880d681SAndroid Build Coastguard Worker   return (*It == TrueBranch) ? *Next : *It;
569*9880d681SAndroid Build Coastguard Worker }
570*9880d681SAndroid Build Coastguard Worker 
isCondBranch(MachineInstr * MI)571*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::isCondBranch(MachineInstr *MI) {
572*9880d681SAndroid Build Coastguard Worker   switch (MI->getOpcode()) {
573*9880d681SAndroid Build Coastguard Worker     case AMDGPU::JUMP_COND:
574*9880d681SAndroid Build Coastguard Worker     case AMDGPU::BRANCH_COND_i32:
575*9880d681SAndroid Build Coastguard Worker     case AMDGPU::BRANCH_COND_f32: return true;
576*9880d681SAndroid Build Coastguard Worker   default:
577*9880d681SAndroid Build Coastguard Worker     return false;
578*9880d681SAndroid Build Coastguard Worker   }
579*9880d681SAndroid Build Coastguard Worker   return false;
580*9880d681SAndroid Build Coastguard Worker }
581*9880d681SAndroid Build Coastguard Worker 
isUncondBranch(MachineInstr * MI)582*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::isUncondBranch(MachineInstr *MI) {
583*9880d681SAndroid Build Coastguard Worker   switch (MI->getOpcode()) {
584*9880d681SAndroid Build Coastguard Worker   case AMDGPU::JUMP:
585*9880d681SAndroid Build Coastguard Worker   case AMDGPU::BRANCH:
586*9880d681SAndroid Build Coastguard Worker     return true;
587*9880d681SAndroid Build Coastguard Worker   default:
588*9880d681SAndroid Build Coastguard Worker     return false;
589*9880d681SAndroid Build Coastguard Worker   }
590*9880d681SAndroid Build Coastguard Worker   return false;
591*9880d681SAndroid Build Coastguard Worker }
592*9880d681SAndroid Build Coastguard Worker 
getLastDebugLocInBB(MachineBasicBlock * MBB)593*9880d681SAndroid Build Coastguard Worker DebugLoc AMDGPUCFGStructurizer::getLastDebugLocInBB(MachineBasicBlock *MBB) {
594*9880d681SAndroid Build Coastguard Worker   //get DebugLoc from the first MachineBasicBlock instruction with debug info
595*9880d681SAndroid Build Coastguard Worker   DebugLoc DL;
596*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::iterator It = MBB->begin(); It != MBB->end();
597*9880d681SAndroid Build Coastguard Worker       ++It) {
598*9880d681SAndroid Build Coastguard Worker     MachineInstr *instr = &(*It);
599*9880d681SAndroid Build Coastguard Worker     if (instr->getDebugLoc())
600*9880d681SAndroid Build Coastguard Worker       DL = instr->getDebugLoc();
601*9880d681SAndroid Build Coastguard Worker   }
602*9880d681SAndroid Build Coastguard Worker   return DL;
603*9880d681SAndroid Build Coastguard Worker }
604*9880d681SAndroid Build Coastguard Worker 
getNormalBlockBranchInstr(MachineBasicBlock * MBB)605*9880d681SAndroid Build Coastguard Worker MachineInstr *AMDGPUCFGStructurizer::getNormalBlockBranchInstr(
606*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB) {
607*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::reverse_iterator It = MBB->rbegin();
608*9880d681SAndroid Build Coastguard Worker   MachineInstr *MI = &*It;
609*9880d681SAndroid Build Coastguard Worker   if (MI && (isCondBranch(MI) || isUncondBranch(MI)))
610*9880d681SAndroid Build Coastguard Worker     return MI;
611*9880d681SAndroid Build Coastguard Worker   return nullptr;
612*9880d681SAndroid Build Coastguard Worker }
613*9880d681SAndroid Build Coastguard Worker 
getLoopendBlockBranchInstr(MachineBasicBlock * MBB)614*9880d681SAndroid Build Coastguard Worker MachineInstr *AMDGPUCFGStructurizer::getLoopendBlockBranchInstr(
615*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB) {
616*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::reverse_iterator It = MBB->rbegin(), E = MBB->rend();
617*9880d681SAndroid Build Coastguard Worker       It != E; ++It) {
618*9880d681SAndroid Build Coastguard Worker     // FIXME: Simplify
619*9880d681SAndroid Build Coastguard Worker     MachineInstr *MI = &*It;
620*9880d681SAndroid Build Coastguard Worker     if (MI) {
621*9880d681SAndroid Build Coastguard Worker       if (isCondBranch(MI) || isUncondBranch(MI))
622*9880d681SAndroid Build Coastguard Worker         return MI;
623*9880d681SAndroid Build Coastguard Worker       else if (!TII->isMov(MI->getOpcode()))
624*9880d681SAndroid Build Coastguard Worker         break;
625*9880d681SAndroid Build Coastguard Worker     }
626*9880d681SAndroid Build Coastguard Worker   }
627*9880d681SAndroid Build Coastguard Worker   return nullptr;
628*9880d681SAndroid Build Coastguard Worker }
629*9880d681SAndroid Build Coastguard Worker 
getReturnInstr(MachineBasicBlock * MBB)630*9880d681SAndroid Build Coastguard Worker MachineInstr *AMDGPUCFGStructurizer::getReturnInstr(MachineBasicBlock *MBB) {
631*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::reverse_iterator It = MBB->rbegin();
632*9880d681SAndroid Build Coastguard Worker   if (It != MBB->rend()) {
633*9880d681SAndroid Build Coastguard Worker     MachineInstr *instr = &(*It);
634*9880d681SAndroid Build Coastguard Worker     if (instr->getOpcode() == AMDGPU::RETURN)
635*9880d681SAndroid Build Coastguard Worker       return instr;
636*9880d681SAndroid Build Coastguard Worker   }
637*9880d681SAndroid Build Coastguard Worker   return nullptr;
638*9880d681SAndroid Build Coastguard Worker }
639*9880d681SAndroid Build Coastguard Worker 
isReturnBlock(MachineBasicBlock * MBB)640*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::isReturnBlock(MachineBasicBlock *MBB) {
641*9880d681SAndroid Build Coastguard Worker   MachineInstr *MI = getReturnInstr(MBB);
642*9880d681SAndroid Build Coastguard Worker   bool IsReturn = (MBB->succ_size() == 0);
643*9880d681SAndroid Build Coastguard Worker   if (MI)
644*9880d681SAndroid Build Coastguard Worker     assert(IsReturn);
645*9880d681SAndroid Build Coastguard Worker   else if (IsReturn)
646*9880d681SAndroid Build Coastguard Worker     DEBUG(
647*9880d681SAndroid Build Coastguard Worker       dbgs() << "BB" << MBB->getNumber()
648*9880d681SAndroid Build Coastguard Worker              <<" is return block without RETURN instr\n";);
649*9880d681SAndroid Build Coastguard Worker   return  IsReturn;
650*9880d681SAndroid Build Coastguard Worker }
651*9880d681SAndroid Build Coastguard Worker 
cloneSuccessorList(MachineBasicBlock * DstMBB,MachineBasicBlock * SrcMBB)652*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::cloneSuccessorList(MachineBasicBlock *DstMBB,
653*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *SrcMBB) {
654*9880d681SAndroid Build Coastguard Worker   for (MachineBasicBlock::succ_iterator It = SrcMBB->succ_begin(),
655*9880d681SAndroid Build Coastguard Worker        iterEnd = SrcMBB->succ_end(); It != iterEnd; ++It)
656*9880d681SAndroid Build Coastguard Worker     DstMBB->addSuccessor(*It);  // *iter's predecessor is also taken care of
657*9880d681SAndroid Build Coastguard Worker }
658*9880d681SAndroid Build Coastguard Worker 
clone(MachineBasicBlock * MBB)659*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *AMDGPUCFGStructurizer::clone(MachineBasicBlock *MBB) {
660*9880d681SAndroid Build Coastguard Worker   MachineFunction *Func = MBB->getParent();
661*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *NewMBB = Func->CreateMachineBasicBlock();
662*9880d681SAndroid Build Coastguard Worker   Func->push_back(NewMBB);  //insert to function
663*9880d681SAndroid Build Coastguard Worker   for (const MachineInstr &It : *MBB)
664*9880d681SAndroid Build Coastguard Worker     NewMBB->push_back(Func->CloneMachineInstr(&It));
665*9880d681SAndroid Build Coastguard Worker   return NewMBB;
666*9880d681SAndroid Build Coastguard Worker }
667*9880d681SAndroid Build Coastguard Worker 
replaceInstrUseOfBlockWith(MachineBasicBlock * SrcMBB,MachineBasicBlock * OldMBB,MachineBasicBlock * NewBlk)668*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::replaceInstrUseOfBlockWith(
669*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *SrcMBB, MachineBasicBlock *OldMBB,
670*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *NewBlk) {
671*9880d681SAndroid Build Coastguard Worker   MachineInstr *BranchMI = getLoopendBlockBranchInstr(SrcMBB);
672*9880d681SAndroid Build Coastguard Worker   if (BranchMI && isCondBranch(BranchMI) &&
673*9880d681SAndroid Build Coastguard Worker       getTrueBranch(BranchMI) == OldMBB)
674*9880d681SAndroid Build Coastguard Worker     setTrueBranch(BranchMI, NewBlk);
675*9880d681SAndroid Build Coastguard Worker }
676*9880d681SAndroid Build Coastguard Worker 
wrapup(MachineBasicBlock * MBB)677*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::wrapup(MachineBasicBlock *MBB) {
678*9880d681SAndroid Build Coastguard Worker   assert((!MBB->getParent()->getJumpTableInfo()
679*9880d681SAndroid Build Coastguard Worker           || MBB->getParent()->getJumpTableInfo()->isEmpty())
680*9880d681SAndroid Build Coastguard Worker          && "found a jump table");
681*9880d681SAndroid Build Coastguard Worker 
682*9880d681SAndroid Build Coastguard Worker    //collect continue right before endloop
683*9880d681SAndroid Build Coastguard Worker    SmallVector<MachineInstr *, DEFAULT_VEC_SLOTS> ContInstr;
684*9880d681SAndroid Build Coastguard Worker    MachineBasicBlock::iterator Pre = MBB->begin();
685*9880d681SAndroid Build Coastguard Worker    MachineBasicBlock::iterator E = MBB->end();
686*9880d681SAndroid Build Coastguard Worker    MachineBasicBlock::iterator It = Pre;
687*9880d681SAndroid Build Coastguard Worker    while (It != E) {
688*9880d681SAndroid Build Coastguard Worker      if (Pre->getOpcode() == AMDGPU::CONTINUE
689*9880d681SAndroid Build Coastguard Worker          && It->getOpcode() == AMDGPU::ENDLOOP)
690*9880d681SAndroid Build Coastguard Worker        ContInstr.push_back(&*Pre);
691*9880d681SAndroid Build Coastguard Worker      Pre = It;
692*9880d681SAndroid Build Coastguard Worker      ++It;
693*9880d681SAndroid Build Coastguard Worker    }
694*9880d681SAndroid Build Coastguard Worker 
695*9880d681SAndroid Build Coastguard Worker    //delete continue right before endloop
696*9880d681SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ContInstr.size(); ++i)
697*9880d681SAndroid Build Coastguard Worker       ContInstr[i]->eraseFromParent();
698*9880d681SAndroid Build Coastguard Worker 
699*9880d681SAndroid Build Coastguard Worker    // TODO to fix up jump table so later phase won't be confused.  if
700*9880d681SAndroid Build Coastguard Worker    // (jumpTableInfo->isEmpty() == false) { need to clean the jump table, but
701*9880d681SAndroid Build Coastguard Worker    // there isn't such an interface yet.  alternatively, replace all the other
702*9880d681SAndroid Build Coastguard Worker    // blocks in the jump table with the entryBlk //}
703*9880d681SAndroid Build Coastguard Worker 
704*9880d681SAndroid Build Coastguard Worker }
705*9880d681SAndroid Build Coastguard Worker 
706*9880d681SAndroid Build Coastguard Worker 
prepare()707*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::prepare() {
708*9880d681SAndroid Build Coastguard Worker   bool Changed = false;
709*9880d681SAndroid Build Coastguard Worker 
710*9880d681SAndroid Build Coastguard Worker   //FIXME: if not reducible flow graph, make it so ???
711*9880d681SAndroid Build Coastguard Worker 
712*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "AMDGPUCFGStructurizer::prepare\n";);
713*9880d681SAndroid Build Coastguard Worker 
714*9880d681SAndroid Build Coastguard Worker   orderBlocks(FuncRep);
715*9880d681SAndroid Build Coastguard Worker 
716*9880d681SAndroid Build Coastguard Worker   SmallVector<MachineBasicBlock *, DEFAULT_VEC_SLOTS> RetBlks;
717*9880d681SAndroid Build Coastguard Worker 
718*9880d681SAndroid Build Coastguard Worker   // Add an ExitBlk to loop that don't have one
719*9880d681SAndroid Build Coastguard Worker   for (MachineLoopInfo::iterator It = MLI->begin(),
720*9880d681SAndroid Build Coastguard Worker        E = MLI->end(); It != E; ++It) {
721*9880d681SAndroid Build Coastguard Worker     MachineLoop *LoopRep = (*It);
722*9880d681SAndroid Build Coastguard Worker     MBBVector ExitingMBBs;
723*9880d681SAndroid Build Coastguard Worker     LoopRep->getExitingBlocks(ExitingMBBs);
724*9880d681SAndroid Build Coastguard Worker 
725*9880d681SAndroid Build Coastguard Worker     if (ExitingMBBs.size() == 0) {
726*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock* DummyExitBlk = normalizeInfiniteLoopExit(LoopRep);
727*9880d681SAndroid Build Coastguard Worker       if (DummyExitBlk)
728*9880d681SAndroid Build Coastguard Worker         RetBlks.push_back(DummyExitBlk);
729*9880d681SAndroid Build Coastguard Worker     }
730*9880d681SAndroid Build Coastguard Worker   }
731*9880d681SAndroid Build Coastguard Worker 
732*9880d681SAndroid Build Coastguard Worker   // Remove unconditional branch instr.
733*9880d681SAndroid Build Coastguard Worker   // Add dummy exit block iff there are multiple returns.
734*9880d681SAndroid Build Coastguard Worker   for (SmallVectorImpl<MachineBasicBlock *>::const_iterator
735*9880d681SAndroid Build Coastguard Worker        It = OrderedBlks.begin(), E = OrderedBlks.end(); It != E; ++It) {
736*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB = *It;
737*9880d681SAndroid Build Coastguard Worker     removeUnconditionalBranch(MBB);
738*9880d681SAndroid Build Coastguard Worker     removeRedundantConditionalBranch(MBB);
739*9880d681SAndroid Build Coastguard Worker     if (isReturnBlock(MBB)) {
740*9880d681SAndroid Build Coastguard Worker       RetBlks.push_back(MBB);
741*9880d681SAndroid Build Coastguard Worker     }
742*9880d681SAndroid Build Coastguard Worker     assert(MBB->succ_size() <= 2);
743*9880d681SAndroid Build Coastguard Worker   }
744*9880d681SAndroid Build Coastguard Worker 
745*9880d681SAndroid Build Coastguard Worker   if (RetBlks.size() >= 2) {
746*9880d681SAndroid Build Coastguard Worker     addDummyExitBlock(RetBlks);
747*9880d681SAndroid Build Coastguard Worker     Changed = true;
748*9880d681SAndroid Build Coastguard Worker   }
749*9880d681SAndroid Build Coastguard Worker 
750*9880d681SAndroid Build Coastguard Worker   return Changed;
751*9880d681SAndroid Build Coastguard Worker }
752*9880d681SAndroid Build Coastguard Worker 
run()753*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::run() {
754*9880d681SAndroid Build Coastguard Worker 
755*9880d681SAndroid Build Coastguard Worker   //Assume reducible CFG...
756*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "AMDGPUCFGStructurizer::run\n");
757*9880d681SAndroid Build Coastguard Worker 
758*9880d681SAndroid Build Coastguard Worker #ifdef STRESSTEST
759*9880d681SAndroid Build Coastguard Worker   //Use the worse block ordering to test the algorithm.
760*9880d681SAndroid Build Coastguard Worker   ReverseVector(orderedBlks);
761*9880d681SAndroid Build Coastguard Worker #endif
762*9880d681SAndroid Build Coastguard Worker 
763*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "Ordered blocks:\n"; printOrderedBlocks(););
764*9880d681SAndroid Build Coastguard Worker   int NumIter = 0;
765*9880d681SAndroid Build Coastguard Worker   bool Finish = false;
766*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB;
767*9880d681SAndroid Build Coastguard Worker   bool MakeProgress = false;
768*9880d681SAndroid Build Coastguard Worker   int NumRemainedBlk = countActiveBlock(OrderedBlks.begin(),
769*9880d681SAndroid Build Coastguard Worker                                         OrderedBlks.end());
770*9880d681SAndroid Build Coastguard Worker 
771*9880d681SAndroid Build Coastguard Worker   do {
772*9880d681SAndroid Build Coastguard Worker     ++NumIter;
773*9880d681SAndroid Build Coastguard Worker     DEBUG(
774*9880d681SAndroid Build Coastguard Worker       dbgs() << "numIter = " << NumIter
775*9880d681SAndroid Build Coastguard Worker              << ", numRemaintedBlk = " << NumRemainedBlk << "\n";
776*9880d681SAndroid Build Coastguard Worker     );
777*9880d681SAndroid Build Coastguard Worker 
778*9880d681SAndroid Build Coastguard Worker     SmallVectorImpl<MachineBasicBlock *>::const_iterator It =
779*9880d681SAndroid Build Coastguard Worker         OrderedBlks.begin();
780*9880d681SAndroid Build Coastguard Worker     SmallVectorImpl<MachineBasicBlock *>::const_iterator E =
781*9880d681SAndroid Build Coastguard Worker         OrderedBlks.end();
782*9880d681SAndroid Build Coastguard Worker 
783*9880d681SAndroid Build Coastguard Worker     SmallVectorImpl<MachineBasicBlock *>::const_iterator SccBeginIter =
784*9880d681SAndroid Build Coastguard Worker         It;
785*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *SccBeginMBB = nullptr;
786*9880d681SAndroid Build Coastguard Worker     int SccNumBlk = 0;  // The number of active blocks, init to a
787*9880d681SAndroid Build Coastguard Worker                         // maximum possible number.
788*9880d681SAndroid Build Coastguard Worker     int SccNumIter;     // Number of iteration in this SCC.
789*9880d681SAndroid Build Coastguard Worker 
790*9880d681SAndroid Build Coastguard Worker     while (It != E) {
791*9880d681SAndroid Build Coastguard Worker       MBB = *It;
792*9880d681SAndroid Build Coastguard Worker 
793*9880d681SAndroid Build Coastguard Worker       if (!SccBeginMBB) {
794*9880d681SAndroid Build Coastguard Worker         SccBeginIter = It;
795*9880d681SAndroid Build Coastguard Worker         SccBeginMBB = MBB;
796*9880d681SAndroid Build Coastguard Worker         SccNumIter = 0;
797*9880d681SAndroid Build Coastguard Worker         SccNumBlk = NumRemainedBlk; // Init to maximum possible number.
798*9880d681SAndroid Build Coastguard Worker         DEBUG(
799*9880d681SAndroid Build Coastguard Worker               dbgs() << "start processing SCC" << getSCCNum(SccBeginMBB);
800*9880d681SAndroid Build Coastguard Worker               dbgs() << "\n";
801*9880d681SAndroid Build Coastguard Worker         );
802*9880d681SAndroid Build Coastguard Worker       }
803*9880d681SAndroid Build Coastguard Worker 
804*9880d681SAndroid Build Coastguard Worker       if (!isRetiredBlock(MBB))
805*9880d681SAndroid Build Coastguard Worker         patternMatch(MBB);
806*9880d681SAndroid Build Coastguard Worker 
807*9880d681SAndroid Build Coastguard Worker       ++It;
808*9880d681SAndroid Build Coastguard Worker 
809*9880d681SAndroid Build Coastguard Worker       bool ContNextScc = true;
810*9880d681SAndroid Build Coastguard Worker       if (It == E
811*9880d681SAndroid Build Coastguard Worker           || getSCCNum(SccBeginMBB) != getSCCNum(*It)) {
812*9880d681SAndroid Build Coastguard Worker         // Just finish one scc.
813*9880d681SAndroid Build Coastguard Worker         ++SccNumIter;
814*9880d681SAndroid Build Coastguard Worker         int sccRemainedNumBlk = countActiveBlock(SccBeginIter, It);
815*9880d681SAndroid Build Coastguard Worker         if (sccRemainedNumBlk != 1 && sccRemainedNumBlk >= SccNumBlk) {
816*9880d681SAndroid Build Coastguard Worker           DEBUG(
817*9880d681SAndroid Build Coastguard Worker             dbgs() << "Can't reduce SCC " << getSCCNum(MBB)
818*9880d681SAndroid Build Coastguard Worker                    << ", sccNumIter = " << SccNumIter;
819*9880d681SAndroid Build Coastguard Worker             dbgs() << "doesn't make any progress\n";
820*9880d681SAndroid Build Coastguard Worker           );
821*9880d681SAndroid Build Coastguard Worker           ContNextScc = true;
822*9880d681SAndroid Build Coastguard Worker         } else if (sccRemainedNumBlk != 1 && sccRemainedNumBlk < SccNumBlk) {
823*9880d681SAndroid Build Coastguard Worker           SccNumBlk = sccRemainedNumBlk;
824*9880d681SAndroid Build Coastguard Worker           It = SccBeginIter;
825*9880d681SAndroid Build Coastguard Worker           ContNextScc = false;
826*9880d681SAndroid Build Coastguard Worker           DEBUG(
827*9880d681SAndroid Build Coastguard Worker             dbgs() << "repeat processing SCC" << getSCCNum(MBB)
828*9880d681SAndroid Build Coastguard Worker                    << "sccNumIter = " << SccNumIter << '\n';
829*9880d681SAndroid Build Coastguard Worker           );
830*9880d681SAndroid Build Coastguard Worker         } else {
831*9880d681SAndroid Build Coastguard Worker           // Finish the current scc.
832*9880d681SAndroid Build Coastguard Worker           ContNextScc = true;
833*9880d681SAndroid Build Coastguard Worker         }
834*9880d681SAndroid Build Coastguard Worker       } else {
835*9880d681SAndroid Build Coastguard Worker         // Continue on next component in the current scc.
836*9880d681SAndroid Build Coastguard Worker         ContNextScc = false;
837*9880d681SAndroid Build Coastguard Worker       }
838*9880d681SAndroid Build Coastguard Worker 
839*9880d681SAndroid Build Coastguard Worker       if (ContNextScc)
840*9880d681SAndroid Build Coastguard Worker         SccBeginMBB = nullptr;
841*9880d681SAndroid Build Coastguard Worker     } //while, "one iteration" over the function.
842*9880d681SAndroid Build Coastguard Worker 
843*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *EntryMBB =
844*9880d681SAndroid Build Coastguard Worker         &*GraphTraits<MachineFunction *>::nodes_begin(FuncRep);
845*9880d681SAndroid Build Coastguard Worker     if (EntryMBB->succ_size() == 0) {
846*9880d681SAndroid Build Coastguard Worker       Finish = true;
847*9880d681SAndroid Build Coastguard Worker       DEBUG(
848*9880d681SAndroid Build Coastguard Worker         dbgs() << "Reduce to one block\n";
849*9880d681SAndroid Build Coastguard Worker       );
850*9880d681SAndroid Build Coastguard Worker     } else {
851*9880d681SAndroid Build Coastguard Worker       int NewnumRemainedBlk
852*9880d681SAndroid Build Coastguard Worker         = countActiveBlock(OrderedBlks.begin(), OrderedBlks.end());
853*9880d681SAndroid Build Coastguard Worker       // consider cloned blocks ??
854*9880d681SAndroid Build Coastguard Worker       if (NewnumRemainedBlk == 1 || NewnumRemainedBlk < NumRemainedBlk) {
855*9880d681SAndroid Build Coastguard Worker         MakeProgress = true;
856*9880d681SAndroid Build Coastguard Worker         NumRemainedBlk = NewnumRemainedBlk;
857*9880d681SAndroid Build Coastguard Worker       } else {
858*9880d681SAndroid Build Coastguard Worker         MakeProgress = false;
859*9880d681SAndroid Build Coastguard Worker         DEBUG(
860*9880d681SAndroid Build Coastguard Worker           dbgs() << "No progress\n";
861*9880d681SAndroid Build Coastguard Worker         );
862*9880d681SAndroid Build Coastguard Worker       }
863*9880d681SAndroid Build Coastguard Worker     }
864*9880d681SAndroid Build Coastguard Worker   } while (!Finish && MakeProgress);
865*9880d681SAndroid Build Coastguard Worker 
866*9880d681SAndroid Build Coastguard Worker   // Misc wrap up to maintain the consistency of the Function representation.
867*9880d681SAndroid Build Coastguard Worker   wrapup(&*GraphTraits<MachineFunction *>::nodes_begin(FuncRep));
868*9880d681SAndroid Build Coastguard Worker 
869*9880d681SAndroid Build Coastguard Worker   // Detach retired Block, release memory.
870*9880d681SAndroid Build Coastguard Worker   for (MBBInfoMap::iterator It = BlockInfoMap.begin(), E = BlockInfoMap.end();
871*9880d681SAndroid Build Coastguard Worker       It != E; ++It) {
872*9880d681SAndroid Build Coastguard Worker     if ((*It).second && (*It).second->IsRetired) {
873*9880d681SAndroid Build Coastguard Worker       assert(((*It).first)->getNumber() != -1);
874*9880d681SAndroid Build Coastguard Worker       DEBUG(
875*9880d681SAndroid Build Coastguard Worker         dbgs() << "Erase BB" << ((*It).first)->getNumber() << "\n";
876*9880d681SAndroid Build Coastguard Worker       );
877*9880d681SAndroid Build Coastguard Worker       (*It).first->eraseFromParent();  //Remove from the parent Function.
878*9880d681SAndroid Build Coastguard Worker     }
879*9880d681SAndroid Build Coastguard Worker     delete (*It).second;
880*9880d681SAndroid Build Coastguard Worker   }
881*9880d681SAndroid Build Coastguard Worker   BlockInfoMap.clear();
882*9880d681SAndroid Build Coastguard Worker   LLInfoMap.clear();
883*9880d681SAndroid Build Coastguard Worker 
884*9880d681SAndroid Build Coastguard Worker   if (!Finish) {
885*9880d681SAndroid Build Coastguard Worker     DEBUG(FuncRep->viewCFG());
886*9880d681SAndroid Build Coastguard Worker     report_fatal_error("IRREDUCIBLE_CFG");
887*9880d681SAndroid Build Coastguard Worker   }
888*9880d681SAndroid Build Coastguard Worker 
889*9880d681SAndroid Build Coastguard Worker   return true;
890*9880d681SAndroid Build Coastguard Worker }
891*9880d681SAndroid Build Coastguard Worker 
892*9880d681SAndroid Build Coastguard Worker 
893*9880d681SAndroid Build Coastguard Worker 
orderBlocks(MachineFunction * MF)894*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::orderBlocks(MachineFunction *MF) {
895*9880d681SAndroid Build Coastguard Worker   int SccNum = 0;
896*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB;
897*9880d681SAndroid Build Coastguard Worker   for (scc_iterator<MachineFunction *> It = scc_begin(MF); !It.isAtEnd();
898*9880d681SAndroid Build Coastguard Worker        ++It, ++SccNum) {
899*9880d681SAndroid Build Coastguard Worker     const std::vector<MachineBasicBlock *> &SccNext = *It;
900*9880d681SAndroid Build Coastguard Worker     for (std::vector<MachineBasicBlock *>::const_iterator
901*9880d681SAndroid Build Coastguard Worker          blockIter = SccNext.begin(), blockEnd = SccNext.end();
902*9880d681SAndroid Build Coastguard Worker          blockIter != blockEnd; ++blockIter) {
903*9880d681SAndroid Build Coastguard Worker       MBB = *blockIter;
904*9880d681SAndroid Build Coastguard Worker       OrderedBlks.push_back(MBB);
905*9880d681SAndroid Build Coastguard Worker       recordSccnum(MBB, SccNum);
906*9880d681SAndroid Build Coastguard Worker     }
907*9880d681SAndroid Build Coastguard Worker   }
908*9880d681SAndroid Build Coastguard Worker 
909*9880d681SAndroid Build Coastguard Worker   //walk through all the block in func to check for unreachable
910*9880d681SAndroid Build Coastguard Worker   typedef GraphTraits<MachineFunction *> GTM;
911*9880d681SAndroid Build Coastguard Worker   MachineFunction::iterator It = GTM::nodes_begin(MF), E = GTM::nodes_end(MF);
912*9880d681SAndroid Build Coastguard Worker   for (; It != E; ++It) {
913*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB = &(*It);
914*9880d681SAndroid Build Coastguard Worker     SccNum = getSCCNum(MBB);
915*9880d681SAndroid Build Coastguard Worker     if (SccNum == INVALIDSCCNUM)
916*9880d681SAndroid Build Coastguard Worker       dbgs() << "unreachable block BB" << MBB->getNumber() << "\n";
917*9880d681SAndroid Build Coastguard Worker   }
918*9880d681SAndroid Build Coastguard Worker }
919*9880d681SAndroid Build Coastguard Worker 
patternMatch(MachineBasicBlock * MBB)920*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::patternMatch(MachineBasicBlock *MBB) {
921*9880d681SAndroid Build Coastguard Worker   int NumMatch = 0;
922*9880d681SAndroid Build Coastguard Worker   int CurMatch;
923*9880d681SAndroid Build Coastguard Worker 
924*9880d681SAndroid Build Coastguard Worker   DEBUG(
925*9880d681SAndroid Build Coastguard Worker         dbgs() << "Begin patternMatch BB" << MBB->getNumber() << "\n";
926*9880d681SAndroid Build Coastguard Worker   );
927*9880d681SAndroid Build Coastguard Worker 
928*9880d681SAndroid Build Coastguard Worker   while ((CurMatch = patternMatchGroup(MBB)) > 0)
929*9880d681SAndroid Build Coastguard Worker     NumMatch += CurMatch;
930*9880d681SAndroid Build Coastguard Worker 
931*9880d681SAndroid Build Coastguard Worker   DEBUG(
932*9880d681SAndroid Build Coastguard Worker         dbgs() << "End patternMatch BB" << MBB->getNumber()
933*9880d681SAndroid Build Coastguard Worker       << ", numMatch = " << NumMatch << "\n";
934*9880d681SAndroid Build Coastguard Worker   );
935*9880d681SAndroid Build Coastguard Worker 
936*9880d681SAndroid Build Coastguard Worker   return NumMatch;
937*9880d681SAndroid Build Coastguard Worker }
938*9880d681SAndroid Build Coastguard Worker 
patternMatchGroup(MachineBasicBlock * MBB)939*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::patternMatchGroup(MachineBasicBlock *MBB) {
940*9880d681SAndroid Build Coastguard Worker   int NumMatch = 0;
941*9880d681SAndroid Build Coastguard Worker   NumMatch += loopendPatternMatch();
942*9880d681SAndroid Build Coastguard Worker   NumMatch += serialPatternMatch(MBB);
943*9880d681SAndroid Build Coastguard Worker   NumMatch += ifPatternMatch(MBB);
944*9880d681SAndroid Build Coastguard Worker   return NumMatch;
945*9880d681SAndroid Build Coastguard Worker }
946*9880d681SAndroid Build Coastguard Worker 
947*9880d681SAndroid Build Coastguard Worker 
serialPatternMatch(MachineBasicBlock * MBB)948*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::serialPatternMatch(MachineBasicBlock *MBB) {
949*9880d681SAndroid Build Coastguard Worker   if (MBB->succ_size() != 1)
950*9880d681SAndroid Build Coastguard Worker     return 0;
951*9880d681SAndroid Build Coastguard Worker 
952*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *childBlk = *MBB->succ_begin();
953*9880d681SAndroid Build Coastguard Worker   if (childBlk->pred_size() != 1 || isActiveLoophead(childBlk))
954*9880d681SAndroid Build Coastguard Worker     return 0;
955*9880d681SAndroid Build Coastguard Worker 
956*9880d681SAndroid Build Coastguard Worker   mergeSerialBlock(MBB, childBlk);
957*9880d681SAndroid Build Coastguard Worker   ++numSerialPatternMatch;
958*9880d681SAndroid Build Coastguard Worker   return 1;
959*9880d681SAndroid Build Coastguard Worker }
960*9880d681SAndroid Build Coastguard Worker 
ifPatternMatch(MachineBasicBlock * MBB)961*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::ifPatternMatch(MachineBasicBlock *MBB) {
962*9880d681SAndroid Build Coastguard Worker   //two edges
963*9880d681SAndroid Build Coastguard Worker   if (MBB->succ_size() != 2)
964*9880d681SAndroid Build Coastguard Worker     return 0;
965*9880d681SAndroid Build Coastguard Worker   if (hasBackEdge(MBB))
966*9880d681SAndroid Build Coastguard Worker     return 0;
967*9880d681SAndroid Build Coastguard Worker   MachineInstr *BranchMI = getNormalBlockBranchInstr(MBB);
968*9880d681SAndroid Build Coastguard Worker   if (!BranchMI)
969*9880d681SAndroid Build Coastguard Worker     return 0;
970*9880d681SAndroid Build Coastguard Worker 
971*9880d681SAndroid Build Coastguard Worker   assert(isCondBranch(BranchMI));
972*9880d681SAndroid Build Coastguard Worker   int NumMatch = 0;
973*9880d681SAndroid Build Coastguard Worker 
974*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *TrueMBB = getTrueBranch(BranchMI);
975*9880d681SAndroid Build Coastguard Worker   NumMatch += serialPatternMatch(TrueMBB);
976*9880d681SAndroid Build Coastguard Worker   NumMatch += ifPatternMatch(TrueMBB);
977*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *FalseMBB = getFalseBranch(MBB, BranchMI);
978*9880d681SAndroid Build Coastguard Worker   NumMatch += serialPatternMatch(FalseMBB);
979*9880d681SAndroid Build Coastguard Worker   NumMatch += ifPatternMatch(FalseMBB);
980*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *LandBlk;
981*9880d681SAndroid Build Coastguard Worker   int Cloned = 0;
982*9880d681SAndroid Build Coastguard Worker 
983*9880d681SAndroid Build Coastguard Worker   assert (!TrueMBB->succ_empty() || !FalseMBB->succ_empty());
984*9880d681SAndroid Build Coastguard Worker   // TODO: Simplify
985*9880d681SAndroid Build Coastguard Worker   if (TrueMBB->succ_size() == 1 && FalseMBB->succ_size() == 1
986*9880d681SAndroid Build Coastguard Worker     && *TrueMBB->succ_begin() == *FalseMBB->succ_begin()) {
987*9880d681SAndroid Build Coastguard Worker     // Diamond pattern
988*9880d681SAndroid Build Coastguard Worker     LandBlk = *TrueMBB->succ_begin();
989*9880d681SAndroid Build Coastguard Worker   } else if (TrueMBB->succ_size() == 1 && *TrueMBB->succ_begin() == FalseMBB) {
990*9880d681SAndroid Build Coastguard Worker     // Triangle pattern, false is empty
991*9880d681SAndroid Build Coastguard Worker     LandBlk = FalseMBB;
992*9880d681SAndroid Build Coastguard Worker     FalseMBB = nullptr;
993*9880d681SAndroid Build Coastguard Worker   } else if (FalseMBB->succ_size() == 1
994*9880d681SAndroid Build Coastguard Worker              && *FalseMBB->succ_begin() == TrueMBB) {
995*9880d681SAndroid Build Coastguard Worker     // Triangle pattern, true is empty
996*9880d681SAndroid Build Coastguard Worker     // We reverse the predicate to make a triangle, empty false pattern;
997*9880d681SAndroid Build Coastguard Worker     std::swap(TrueMBB, FalseMBB);
998*9880d681SAndroid Build Coastguard Worker     reversePredicateSetter(MBB->end());
999*9880d681SAndroid Build Coastguard Worker     LandBlk = FalseMBB;
1000*9880d681SAndroid Build Coastguard Worker     FalseMBB = nullptr;
1001*9880d681SAndroid Build Coastguard Worker   } else if (FalseMBB->succ_size() == 1
1002*9880d681SAndroid Build Coastguard Worker              && isSameloopDetachedContbreak(TrueMBB, FalseMBB)) {
1003*9880d681SAndroid Build Coastguard Worker     LandBlk = *FalseMBB->succ_begin();
1004*9880d681SAndroid Build Coastguard Worker   } else if (TrueMBB->succ_size() == 1
1005*9880d681SAndroid Build Coastguard Worker     && isSameloopDetachedContbreak(FalseMBB, TrueMBB)) {
1006*9880d681SAndroid Build Coastguard Worker     LandBlk = *TrueMBB->succ_begin();
1007*9880d681SAndroid Build Coastguard Worker   } else {
1008*9880d681SAndroid Build Coastguard Worker     return NumMatch + handleJumpintoIf(MBB, TrueMBB, FalseMBB);
1009*9880d681SAndroid Build Coastguard Worker   }
1010*9880d681SAndroid Build Coastguard Worker 
1011*9880d681SAndroid Build Coastguard Worker   // improveSimpleJumpinfoIf can handle the case where landBlk == NULL but the
1012*9880d681SAndroid Build Coastguard Worker   // new BB created for landBlk==NULL may introduce new challenge to the
1013*9880d681SAndroid Build Coastguard Worker   // reduction process.
1014*9880d681SAndroid Build Coastguard Worker   if (LandBlk &&
1015*9880d681SAndroid Build Coastguard Worker       ((TrueMBB && TrueMBB->pred_size() > 1)
1016*9880d681SAndroid Build Coastguard Worker       || (FalseMBB && FalseMBB->pred_size() > 1))) {
1017*9880d681SAndroid Build Coastguard Worker      Cloned += improveSimpleJumpintoIf(MBB, TrueMBB, FalseMBB, &LandBlk);
1018*9880d681SAndroid Build Coastguard Worker   }
1019*9880d681SAndroid Build Coastguard Worker 
1020*9880d681SAndroid Build Coastguard Worker   if (TrueMBB && TrueMBB->pred_size() > 1) {
1021*9880d681SAndroid Build Coastguard Worker     TrueMBB = cloneBlockForPredecessor(TrueMBB, MBB);
1022*9880d681SAndroid Build Coastguard Worker     ++Cloned;
1023*9880d681SAndroid Build Coastguard Worker   }
1024*9880d681SAndroid Build Coastguard Worker 
1025*9880d681SAndroid Build Coastguard Worker   if (FalseMBB && FalseMBB->pred_size() > 1) {
1026*9880d681SAndroid Build Coastguard Worker     FalseMBB = cloneBlockForPredecessor(FalseMBB, MBB);
1027*9880d681SAndroid Build Coastguard Worker     ++Cloned;
1028*9880d681SAndroid Build Coastguard Worker   }
1029*9880d681SAndroid Build Coastguard Worker 
1030*9880d681SAndroid Build Coastguard Worker   mergeIfthenelseBlock(BranchMI, MBB, TrueMBB, FalseMBB, LandBlk);
1031*9880d681SAndroid Build Coastguard Worker 
1032*9880d681SAndroid Build Coastguard Worker   ++numIfPatternMatch;
1033*9880d681SAndroid Build Coastguard Worker 
1034*9880d681SAndroid Build Coastguard Worker   numClonedBlock += Cloned;
1035*9880d681SAndroid Build Coastguard Worker 
1036*9880d681SAndroid Build Coastguard Worker   return 1 + Cloned + NumMatch;
1037*9880d681SAndroid Build Coastguard Worker }
1038*9880d681SAndroid Build Coastguard Worker 
loopendPatternMatch()1039*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::loopendPatternMatch() {
1040*9880d681SAndroid Build Coastguard Worker   std::deque<MachineLoop *> NestedLoops;
1041*9880d681SAndroid Build Coastguard Worker   for (auto &It: *MLI)
1042*9880d681SAndroid Build Coastguard Worker     for (MachineLoop *ML : depth_first(It))
1043*9880d681SAndroid Build Coastguard Worker       NestedLoops.push_front(ML);
1044*9880d681SAndroid Build Coastguard Worker 
1045*9880d681SAndroid Build Coastguard Worker   if (NestedLoops.size() == 0)
1046*9880d681SAndroid Build Coastguard Worker     return 0;
1047*9880d681SAndroid Build Coastguard Worker 
1048*9880d681SAndroid Build Coastguard Worker   // Process nested loop outside->inside (we did push_front),
1049*9880d681SAndroid Build Coastguard Worker   // so "continue" to a outside loop won't be mistaken as "break"
1050*9880d681SAndroid Build Coastguard Worker   // of the current loop.
1051*9880d681SAndroid Build Coastguard Worker   int Num = 0;
1052*9880d681SAndroid Build Coastguard Worker   for (MachineLoop *ExaminedLoop : NestedLoops) {
1053*9880d681SAndroid Build Coastguard Worker     if (ExaminedLoop->getNumBlocks() == 0 || Visited[ExaminedLoop])
1054*9880d681SAndroid Build Coastguard Worker       continue;
1055*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "Processing:\n"; ExaminedLoop->dump(););
1056*9880d681SAndroid Build Coastguard Worker     int NumBreak = mergeLoop(ExaminedLoop);
1057*9880d681SAndroid Build Coastguard Worker     if (NumBreak == -1)
1058*9880d681SAndroid Build Coastguard Worker       break;
1059*9880d681SAndroid Build Coastguard Worker     Num += NumBreak;
1060*9880d681SAndroid Build Coastguard Worker   }
1061*9880d681SAndroid Build Coastguard Worker   return Num;
1062*9880d681SAndroid Build Coastguard Worker }
1063*9880d681SAndroid Build Coastguard Worker 
mergeLoop(MachineLoop * LoopRep)1064*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::mergeLoop(MachineLoop *LoopRep) {
1065*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *LoopHeader = LoopRep->getHeader();
1066*9880d681SAndroid Build Coastguard Worker   MBBVector ExitingMBBs;
1067*9880d681SAndroid Build Coastguard Worker   LoopRep->getExitingBlocks(ExitingMBBs);
1068*9880d681SAndroid Build Coastguard Worker   assert(!ExitingMBBs.empty() && "Infinite Loop not supported");
1069*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "Loop has " << ExitingMBBs.size() << " exiting blocks\n";);
1070*9880d681SAndroid Build Coastguard Worker   // We assume a single ExitBlk
1071*9880d681SAndroid Build Coastguard Worker   MBBVector ExitBlks;
1072*9880d681SAndroid Build Coastguard Worker   LoopRep->getExitBlocks(ExitBlks);
1073*9880d681SAndroid Build Coastguard Worker   SmallPtrSet<MachineBasicBlock *, 2> ExitBlkSet;
1074*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = ExitBlks.size(); i < e; ++i)
1075*9880d681SAndroid Build Coastguard Worker     ExitBlkSet.insert(ExitBlks[i]);
1076*9880d681SAndroid Build Coastguard Worker   assert(ExitBlkSet.size() == 1);
1077*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *ExitBlk = *ExitBlks.begin();
1078*9880d681SAndroid Build Coastguard Worker   assert(ExitBlk && "Loop has several exit block");
1079*9880d681SAndroid Build Coastguard Worker   MBBVector LatchBlks;
1080*9880d681SAndroid Build Coastguard Worker   typedef GraphTraits<Inverse<MachineBasicBlock*> > InvMBBTraits;
1081*9880d681SAndroid Build Coastguard Worker   InvMBBTraits::ChildIteratorType PI = InvMBBTraits::child_begin(LoopHeader),
1082*9880d681SAndroid Build Coastguard Worker       PE = InvMBBTraits::child_end(LoopHeader);
1083*9880d681SAndroid Build Coastguard Worker   for (; PI != PE; PI++) {
1084*9880d681SAndroid Build Coastguard Worker     if (LoopRep->contains(*PI))
1085*9880d681SAndroid Build Coastguard Worker       LatchBlks.push_back(*PI);
1086*9880d681SAndroid Build Coastguard Worker   }
1087*9880d681SAndroid Build Coastguard Worker 
1088*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = ExitingMBBs.size(); i < e; ++i)
1089*9880d681SAndroid Build Coastguard Worker     mergeLoopbreakBlock(ExitingMBBs[i], ExitBlk);
1090*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = LatchBlks.size(); i < e; ++i)
1091*9880d681SAndroid Build Coastguard Worker     settleLoopcontBlock(LatchBlks[i], LoopHeader);
1092*9880d681SAndroid Build Coastguard Worker   int Match = 0;
1093*9880d681SAndroid Build Coastguard Worker   do {
1094*9880d681SAndroid Build Coastguard Worker     Match = 0;
1095*9880d681SAndroid Build Coastguard Worker     Match += serialPatternMatch(LoopHeader);
1096*9880d681SAndroid Build Coastguard Worker     Match += ifPatternMatch(LoopHeader);
1097*9880d681SAndroid Build Coastguard Worker   } while (Match > 0);
1098*9880d681SAndroid Build Coastguard Worker   mergeLooplandBlock(LoopHeader, ExitBlk);
1099*9880d681SAndroid Build Coastguard Worker   MachineLoop *ParentLoop = LoopRep->getParentLoop();
1100*9880d681SAndroid Build Coastguard Worker   if (ParentLoop)
1101*9880d681SAndroid Build Coastguard Worker     MLI->changeLoopFor(LoopHeader, ParentLoop);
1102*9880d681SAndroid Build Coastguard Worker   else
1103*9880d681SAndroid Build Coastguard Worker     MLI->removeBlock(LoopHeader);
1104*9880d681SAndroid Build Coastguard Worker   Visited[LoopRep] = true;
1105*9880d681SAndroid Build Coastguard Worker   return 1;
1106*9880d681SAndroid Build Coastguard Worker }
1107*9880d681SAndroid Build Coastguard Worker 
isSameloopDetachedContbreak(MachineBasicBlock * Src1MBB,MachineBasicBlock * Src2MBB)1108*9880d681SAndroid Build Coastguard Worker bool AMDGPUCFGStructurizer::isSameloopDetachedContbreak(
1109*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *Src1MBB, MachineBasicBlock *Src2MBB) {
1110*9880d681SAndroid Build Coastguard Worker   if (Src1MBB->succ_size() == 0) {
1111*9880d681SAndroid Build Coastguard Worker     MachineLoop *LoopRep = MLI->getLoopFor(Src1MBB);
1112*9880d681SAndroid Build Coastguard Worker     if (LoopRep&& LoopRep == MLI->getLoopFor(Src2MBB)) {
1113*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *&TheEntry = LLInfoMap[LoopRep];
1114*9880d681SAndroid Build Coastguard Worker       if (TheEntry) {
1115*9880d681SAndroid Build Coastguard Worker         DEBUG(
1116*9880d681SAndroid Build Coastguard Worker           dbgs() << "isLoopContBreakBlock yes src1 = BB"
1117*9880d681SAndroid Build Coastguard Worker                  << Src1MBB->getNumber()
1118*9880d681SAndroid Build Coastguard Worker                  << " src2 = BB" << Src2MBB->getNumber() << "\n";
1119*9880d681SAndroid Build Coastguard Worker         );
1120*9880d681SAndroid Build Coastguard Worker         return true;
1121*9880d681SAndroid Build Coastguard Worker       }
1122*9880d681SAndroid Build Coastguard Worker     }
1123*9880d681SAndroid Build Coastguard Worker   }
1124*9880d681SAndroid Build Coastguard Worker   return false;
1125*9880d681SAndroid Build Coastguard Worker }
1126*9880d681SAndroid Build Coastguard Worker 
handleJumpintoIf(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB)1127*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::handleJumpintoIf(MachineBasicBlock *HeadMBB,
1128*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
1129*9880d681SAndroid Build Coastguard Worker   int Num = handleJumpintoIfImp(HeadMBB, TrueMBB, FalseMBB);
1130*9880d681SAndroid Build Coastguard Worker   if (Num == 0) {
1131*9880d681SAndroid Build Coastguard Worker     DEBUG(
1132*9880d681SAndroid Build Coastguard Worker       dbgs() << "handleJumpintoIf swap trueBlk and FalseBlk" << "\n";
1133*9880d681SAndroid Build Coastguard Worker     );
1134*9880d681SAndroid Build Coastguard Worker     Num = handleJumpintoIfImp(HeadMBB, FalseMBB, TrueMBB);
1135*9880d681SAndroid Build Coastguard Worker   }
1136*9880d681SAndroid Build Coastguard Worker   return Num;
1137*9880d681SAndroid Build Coastguard Worker }
1138*9880d681SAndroid Build Coastguard Worker 
handleJumpintoIfImp(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB)1139*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
1140*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
1141*9880d681SAndroid Build Coastguard Worker   int Num = 0;
1142*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *DownBlk;
1143*9880d681SAndroid Build Coastguard Worker 
1144*9880d681SAndroid Build Coastguard Worker   //trueBlk could be the common post dominator
1145*9880d681SAndroid Build Coastguard Worker   DownBlk = TrueMBB;
1146*9880d681SAndroid Build Coastguard Worker 
1147*9880d681SAndroid Build Coastguard Worker   DEBUG(
1148*9880d681SAndroid Build Coastguard Worker     dbgs() << "handleJumpintoIfImp head = BB" << HeadMBB->getNumber()
1149*9880d681SAndroid Build Coastguard Worker            << " true = BB" << TrueMBB->getNumber()
1150*9880d681SAndroid Build Coastguard Worker            << ", numSucc=" << TrueMBB->succ_size()
1151*9880d681SAndroid Build Coastguard Worker            << " false = BB" << FalseMBB->getNumber() << "\n";
1152*9880d681SAndroid Build Coastguard Worker   );
1153*9880d681SAndroid Build Coastguard Worker 
1154*9880d681SAndroid Build Coastguard Worker   while (DownBlk) {
1155*9880d681SAndroid Build Coastguard Worker     DEBUG(
1156*9880d681SAndroid Build Coastguard Worker       dbgs() << "check down = BB" << DownBlk->getNumber();
1157*9880d681SAndroid Build Coastguard Worker     );
1158*9880d681SAndroid Build Coastguard Worker 
1159*9880d681SAndroid Build Coastguard Worker     if (singlePathTo(FalseMBB, DownBlk) == SinglePath_InPath) {
1160*9880d681SAndroid Build Coastguard Worker       DEBUG(
1161*9880d681SAndroid Build Coastguard Worker         dbgs() << " working\n";
1162*9880d681SAndroid Build Coastguard Worker       );
1163*9880d681SAndroid Build Coastguard Worker 
1164*9880d681SAndroid Build Coastguard Worker       Num += cloneOnSideEntryTo(HeadMBB, TrueMBB, DownBlk);
1165*9880d681SAndroid Build Coastguard Worker       Num += cloneOnSideEntryTo(HeadMBB, FalseMBB, DownBlk);
1166*9880d681SAndroid Build Coastguard Worker 
1167*9880d681SAndroid Build Coastguard Worker       numClonedBlock += Num;
1168*9880d681SAndroid Build Coastguard Worker       Num += serialPatternMatch(*HeadMBB->succ_begin());
1169*9880d681SAndroid Build Coastguard Worker       Num += serialPatternMatch(*std::next(HeadMBB->succ_begin()));
1170*9880d681SAndroid Build Coastguard Worker       Num += ifPatternMatch(HeadMBB);
1171*9880d681SAndroid Build Coastguard Worker       assert(Num > 0);
1172*9880d681SAndroid Build Coastguard Worker 
1173*9880d681SAndroid Build Coastguard Worker       break;
1174*9880d681SAndroid Build Coastguard Worker     }
1175*9880d681SAndroid Build Coastguard Worker     DEBUG(
1176*9880d681SAndroid Build Coastguard Worker       dbgs() << " not working\n";
1177*9880d681SAndroid Build Coastguard Worker     );
1178*9880d681SAndroid Build Coastguard Worker     DownBlk = (DownBlk->succ_size() == 1) ? (*DownBlk->succ_begin()) : nullptr;
1179*9880d681SAndroid Build Coastguard Worker   } // walk down the postDomTree
1180*9880d681SAndroid Build Coastguard Worker 
1181*9880d681SAndroid Build Coastguard Worker   return Num;
1182*9880d681SAndroid Build Coastguard Worker }
1183*9880d681SAndroid Build Coastguard Worker 
showImproveSimpleJumpintoIf(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB,MachineBasicBlock * LandMBB,bool Detail)1184*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::showImproveSimpleJumpintoIf(
1185*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *HeadMBB, MachineBasicBlock *TrueMBB,
1186*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB, bool Detail) {
1187*9880d681SAndroid Build Coastguard Worker   dbgs() << "head = BB" << HeadMBB->getNumber()
1188*9880d681SAndroid Build Coastguard Worker          << " size = " << HeadMBB->size();
1189*9880d681SAndroid Build Coastguard Worker   if (Detail) {
1190*9880d681SAndroid Build Coastguard Worker     dbgs() << "\n";
1191*9880d681SAndroid Build Coastguard Worker     HeadMBB->print(dbgs());
1192*9880d681SAndroid Build Coastguard Worker     dbgs() << "\n";
1193*9880d681SAndroid Build Coastguard Worker   }
1194*9880d681SAndroid Build Coastguard Worker 
1195*9880d681SAndroid Build Coastguard Worker   if (TrueMBB) {
1196*9880d681SAndroid Build Coastguard Worker     dbgs() << ", true = BB" << TrueMBB->getNumber() << " size = "
1197*9880d681SAndroid Build Coastguard Worker            << TrueMBB->size() << " numPred = " << TrueMBB->pred_size();
1198*9880d681SAndroid Build Coastguard Worker     if (Detail) {
1199*9880d681SAndroid Build Coastguard Worker       dbgs() << "\n";
1200*9880d681SAndroid Build Coastguard Worker       TrueMBB->print(dbgs());
1201*9880d681SAndroid Build Coastguard Worker       dbgs() << "\n";
1202*9880d681SAndroid Build Coastguard Worker     }
1203*9880d681SAndroid Build Coastguard Worker   }
1204*9880d681SAndroid Build Coastguard Worker   if (FalseMBB) {
1205*9880d681SAndroid Build Coastguard Worker     dbgs() << ", false = BB" << FalseMBB->getNumber() << " size = "
1206*9880d681SAndroid Build Coastguard Worker            << FalseMBB->size() << " numPred = " << FalseMBB->pred_size();
1207*9880d681SAndroid Build Coastguard Worker     if (Detail) {
1208*9880d681SAndroid Build Coastguard Worker       dbgs() << "\n";
1209*9880d681SAndroid Build Coastguard Worker       FalseMBB->print(dbgs());
1210*9880d681SAndroid Build Coastguard Worker       dbgs() << "\n";
1211*9880d681SAndroid Build Coastguard Worker     }
1212*9880d681SAndroid Build Coastguard Worker   }
1213*9880d681SAndroid Build Coastguard Worker   if (LandMBB) {
1214*9880d681SAndroid Build Coastguard Worker     dbgs() << ", land = BB" << LandMBB->getNumber() << " size = "
1215*9880d681SAndroid Build Coastguard Worker            << LandMBB->size() << " numPred = " << LandMBB->pred_size();
1216*9880d681SAndroid Build Coastguard Worker     if (Detail) {
1217*9880d681SAndroid Build Coastguard Worker       dbgs() << "\n";
1218*9880d681SAndroid Build Coastguard Worker       LandMBB->print(dbgs());
1219*9880d681SAndroid Build Coastguard Worker       dbgs() << "\n";
1220*9880d681SAndroid Build Coastguard Worker     }
1221*9880d681SAndroid Build Coastguard Worker   }
1222*9880d681SAndroid Build Coastguard Worker 
1223*9880d681SAndroid Build Coastguard Worker     dbgs() << "\n";
1224*9880d681SAndroid Build Coastguard Worker }
1225*9880d681SAndroid Build Coastguard Worker 
improveSimpleJumpintoIf(MachineBasicBlock * HeadMBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB,MachineBasicBlock ** LandMBBPtr)1226*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
1227*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
1228*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock **LandMBBPtr) {
1229*9880d681SAndroid Build Coastguard Worker   bool MigrateTrue = false;
1230*9880d681SAndroid Build Coastguard Worker   bool MigrateFalse = false;
1231*9880d681SAndroid Build Coastguard Worker 
1232*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *LandBlk = *LandMBBPtr;
1233*9880d681SAndroid Build Coastguard Worker 
1234*9880d681SAndroid Build Coastguard Worker   assert((!TrueMBB || TrueMBB->succ_size() <= 1)
1235*9880d681SAndroid Build Coastguard Worker          && (!FalseMBB || FalseMBB->succ_size() <= 1));
1236*9880d681SAndroid Build Coastguard Worker 
1237*9880d681SAndroid Build Coastguard Worker   if (TrueMBB == FalseMBB)
1238*9880d681SAndroid Build Coastguard Worker     return 0;
1239*9880d681SAndroid Build Coastguard Worker 
1240*9880d681SAndroid Build Coastguard Worker   MigrateTrue = needMigrateBlock(TrueMBB);
1241*9880d681SAndroid Build Coastguard Worker   MigrateFalse = needMigrateBlock(FalseMBB);
1242*9880d681SAndroid Build Coastguard Worker 
1243*9880d681SAndroid Build Coastguard Worker   if (!MigrateTrue && !MigrateFalse)
1244*9880d681SAndroid Build Coastguard Worker     return 0;
1245*9880d681SAndroid Build Coastguard Worker 
1246*9880d681SAndroid Build Coastguard Worker   // If we need to migrate either trueBlk and falseBlk, migrate the rest that
1247*9880d681SAndroid Build Coastguard Worker   // have more than one predecessors.  without doing this, its predecessor
1248*9880d681SAndroid Build Coastguard Worker   // rather than headBlk will have undefined value in initReg.
1249*9880d681SAndroid Build Coastguard Worker   if (!MigrateTrue && TrueMBB && TrueMBB->pred_size() > 1)
1250*9880d681SAndroid Build Coastguard Worker     MigrateTrue = true;
1251*9880d681SAndroid Build Coastguard Worker   if (!MigrateFalse && FalseMBB && FalseMBB->pred_size() > 1)
1252*9880d681SAndroid Build Coastguard Worker     MigrateFalse = true;
1253*9880d681SAndroid Build Coastguard Worker 
1254*9880d681SAndroid Build Coastguard Worker   DEBUG(
1255*9880d681SAndroid Build Coastguard Worker     dbgs() << "before improveSimpleJumpintoIf: ";
1256*9880d681SAndroid Build Coastguard Worker     showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0);
1257*9880d681SAndroid Build Coastguard Worker   );
1258*9880d681SAndroid Build Coastguard Worker 
1259*9880d681SAndroid Build Coastguard Worker   // org: headBlk => if () {trueBlk} else {falseBlk} => landBlk
1260*9880d681SAndroid Build Coastguard Worker   //
1261*9880d681SAndroid Build Coastguard Worker   // new: headBlk => if () {initReg = 1; org trueBlk branch} else
1262*9880d681SAndroid Build Coastguard Worker   //      {initReg = 0; org falseBlk branch }
1263*9880d681SAndroid Build Coastguard Worker   //      => landBlk => if (initReg) {org trueBlk} else {org falseBlk}
1264*9880d681SAndroid Build Coastguard Worker   //      => org landBlk
1265*9880d681SAndroid Build Coastguard Worker   //      if landBlk->pred_size() > 2, put the about if-else inside
1266*9880d681SAndroid Build Coastguard Worker   //      if (initReg !=2) {...}
1267*9880d681SAndroid Build Coastguard Worker   //
1268*9880d681SAndroid Build Coastguard Worker   // add initReg = initVal to headBlk
1269*9880d681SAndroid Build Coastguard Worker 
1270*9880d681SAndroid Build Coastguard Worker   const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
1271*9880d681SAndroid Build Coastguard Worker   if (!MigrateTrue || !MigrateFalse) {
1272*9880d681SAndroid Build Coastguard Worker     // XXX: We have an opportunity here to optimize the "branch into if" case
1273*9880d681SAndroid Build Coastguard Worker     // here.  Branch into if looks like this:
1274*9880d681SAndroid Build Coastguard Worker     //                        entry
1275*9880d681SAndroid Build Coastguard Worker     //                       /     |
1276*9880d681SAndroid Build Coastguard Worker     //           diamond_head       branch_from
1277*9880d681SAndroid Build Coastguard Worker     //             /      \           |
1278*9880d681SAndroid Build Coastguard Worker     // diamond_false        diamond_true
1279*9880d681SAndroid Build Coastguard Worker     //             \      /
1280*9880d681SAndroid Build Coastguard Worker     //               done
1281*9880d681SAndroid Build Coastguard Worker     //
1282*9880d681SAndroid Build Coastguard Worker     // The diamond_head block begins the "if" and the diamond_true block
1283*9880d681SAndroid Build Coastguard Worker     // is the block being "branched into".
1284*9880d681SAndroid Build Coastguard Worker     //
1285*9880d681SAndroid Build Coastguard Worker     // If MigrateTrue is true, then TrueBB is the block being "branched into"
1286*9880d681SAndroid Build Coastguard Worker     // and if MigrateFalse is true, then FalseBB is the block being
1287*9880d681SAndroid Build Coastguard Worker     // "branched into"
1288*9880d681SAndroid Build Coastguard Worker     //
1289*9880d681SAndroid Build Coastguard Worker     // Here is the pseudo code for how I think the optimization should work:
1290*9880d681SAndroid Build Coastguard Worker     // 1. Insert MOV GPR0, 0 before the branch instruction in diamond_head.
1291*9880d681SAndroid Build Coastguard Worker     // 2. Insert MOV GPR0, 1 before the branch instruction in branch_from.
1292*9880d681SAndroid Build Coastguard Worker     // 3. Move the branch instruction from diamond_head into its own basic
1293*9880d681SAndroid Build Coastguard Worker     //    block (new_block).
1294*9880d681SAndroid Build Coastguard Worker     // 4. Add an unconditional branch from diamond_head to new_block
1295*9880d681SAndroid Build Coastguard Worker     // 5. Replace the branch instruction in branch_from with an unconditional
1296*9880d681SAndroid Build Coastguard Worker     //    branch to new_block.  If branch_from has multiple predecessors, then
1297*9880d681SAndroid Build Coastguard Worker     //    we need to replace the True/False block in the branch
1298*9880d681SAndroid Build Coastguard Worker     //    instruction instead of replacing it.
1299*9880d681SAndroid Build Coastguard Worker     // 6. Change the condition of the branch instruction in new_block from
1300*9880d681SAndroid Build Coastguard Worker     //    COND to (COND || GPR0)
1301*9880d681SAndroid Build Coastguard Worker     //
1302*9880d681SAndroid Build Coastguard Worker     // In order insert these MOV instruction, we will need to use the
1303*9880d681SAndroid Build Coastguard Worker     // RegisterScavenger.  Usually liveness stops being tracked during
1304*9880d681SAndroid Build Coastguard Worker     // the late machine optimization passes, however if we implement
1305*9880d681SAndroid Build Coastguard Worker     // bool TargetRegisterInfo::requiresRegisterScavenging(
1306*9880d681SAndroid Build Coastguard Worker     //                                                const MachineFunction &MF)
1307*9880d681SAndroid Build Coastguard Worker     // and have it return true, liveness will be tracked correctly
1308*9880d681SAndroid Build Coastguard Worker     // by generic optimization passes.  We will also need to make sure that
1309*9880d681SAndroid Build Coastguard Worker     // all of our target-specific passes that run after regalloc and before
1310*9880d681SAndroid Build Coastguard Worker     // the CFGStructurizer track liveness and we will need to modify this pass
1311*9880d681SAndroid Build Coastguard Worker     // to correctly track liveness.
1312*9880d681SAndroid Build Coastguard Worker     //
1313*9880d681SAndroid Build Coastguard Worker     // After the above changes, the new CFG should look like this:
1314*9880d681SAndroid Build Coastguard Worker     //                        entry
1315*9880d681SAndroid Build Coastguard Worker     //                       /     |
1316*9880d681SAndroid Build Coastguard Worker     //           diamond_head       branch_from
1317*9880d681SAndroid Build Coastguard Worker     //                       \     /
1318*9880d681SAndroid Build Coastguard Worker     //                      new_block
1319*9880d681SAndroid Build Coastguard Worker     //                      /      |
1320*9880d681SAndroid Build Coastguard Worker     //         diamond_false        diamond_true
1321*9880d681SAndroid Build Coastguard Worker     //                      \      /
1322*9880d681SAndroid Build Coastguard Worker     //                        done
1323*9880d681SAndroid Build Coastguard Worker     //
1324*9880d681SAndroid Build Coastguard Worker     // Without this optimization, we are forced to duplicate the diamond_true
1325*9880d681SAndroid Build Coastguard Worker     // block and we will end up with a CFG like this:
1326*9880d681SAndroid Build Coastguard Worker     //
1327*9880d681SAndroid Build Coastguard Worker     //                        entry
1328*9880d681SAndroid Build Coastguard Worker     //                       /     |
1329*9880d681SAndroid Build Coastguard Worker     //           diamond_head       branch_from
1330*9880d681SAndroid Build Coastguard Worker     //             /      \                   |
1331*9880d681SAndroid Build Coastguard Worker     // diamond_false        diamond_true      diamond_true (duplicate)
1332*9880d681SAndroid Build Coastguard Worker     //             \      /                   |
1333*9880d681SAndroid Build Coastguard Worker     //               done --------------------|
1334*9880d681SAndroid Build Coastguard Worker     //
1335*9880d681SAndroid Build Coastguard Worker     // Duplicating diamond_true can be very costly especially if it has a
1336*9880d681SAndroid Build Coastguard Worker     // lot of instructions.
1337*9880d681SAndroid Build Coastguard Worker     return 0;
1338*9880d681SAndroid Build Coastguard Worker   }
1339*9880d681SAndroid Build Coastguard Worker 
1340*9880d681SAndroid Build Coastguard Worker   int NumNewBlk = 0;
1341*9880d681SAndroid Build Coastguard Worker 
1342*9880d681SAndroid Build Coastguard Worker   bool LandBlkHasOtherPred = (LandBlk->pred_size() > 2);
1343*9880d681SAndroid Build Coastguard Worker 
1344*9880d681SAndroid Build Coastguard Worker   //insert AMDGPU::ENDIF to avoid special case "input landBlk == NULL"
1345*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator I = insertInstrBefore(LandBlk, AMDGPU::ENDIF);
1346*9880d681SAndroid Build Coastguard Worker 
1347*9880d681SAndroid Build Coastguard Worker   if (LandBlkHasOtherPred) {
1348*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Extra register needed to handle CFG");
1349*9880d681SAndroid Build Coastguard Worker     unsigned CmpResReg =
1350*9880d681SAndroid Build Coastguard Worker       HeadMBB->getParent()->getRegInfo().createVirtualRegister(I32RC);
1351*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Extra compare instruction needed to handle CFG");
1352*9880d681SAndroid Build Coastguard Worker     insertCondBranchBefore(LandBlk, I, AMDGPU::IF_PREDICATE_SET,
1353*9880d681SAndroid Build Coastguard Worker         CmpResReg, DebugLoc());
1354*9880d681SAndroid Build Coastguard Worker   }
1355*9880d681SAndroid Build Coastguard Worker 
1356*9880d681SAndroid Build Coastguard Worker   // XXX: We are running this after RA, so creating virtual registers will
1357*9880d681SAndroid Build Coastguard Worker   // cause an assertion failure in the PostRA scheduling pass.
1358*9880d681SAndroid Build Coastguard Worker   unsigned InitReg =
1359*9880d681SAndroid Build Coastguard Worker     HeadMBB->getParent()->getRegInfo().createVirtualRegister(I32RC);
1360*9880d681SAndroid Build Coastguard Worker   insertCondBranchBefore(LandBlk, I, AMDGPU::IF_PREDICATE_SET, InitReg,
1361*9880d681SAndroid Build Coastguard Worker       DebugLoc());
1362*9880d681SAndroid Build Coastguard Worker 
1363*9880d681SAndroid Build Coastguard Worker   if (MigrateTrue) {
1364*9880d681SAndroid Build Coastguard Worker     migrateInstruction(TrueMBB, LandBlk, I);
1365*9880d681SAndroid Build Coastguard Worker     // need to uncondionally insert the assignment to ensure a path from its
1366*9880d681SAndroid Build Coastguard Worker     // predecessor rather than headBlk has valid value in initReg if
1367*9880d681SAndroid Build Coastguard Worker     // (initVal != 1).
1368*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Extra register needed to handle CFG");
1369*9880d681SAndroid Build Coastguard Worker   }
1370*9880d681SAndroid Build Coastguard Worker   insertInstrBefore(I, AMDGPU::ELSE);
1371*9880d681SAndroid Build Coastguard Worker 
1372*9880d681SAndroid Build Coastguard Worker   if (MigrateFalse) {
1373*9880d681SAndroid Build Coastguard Worker     migrateInstruction(FalseMBB, LandBlk, I);
1374*9880d681SAndroid Build Coastguard Worker     // need to uncondionally insert the assignment to ensure a path from its
1375*9880d681SAndroid Build Coastguard Worker     // predecessor rather than headBlk has valid value in initReg if
1376*9880d681SAndroid Build Coastguard Worker     // (initVal != 0)
1377*9880d681SAndroid Build Coastguard Worker     report_fatal_error("Extra register needed to handle CFG");
1378*9880d681SAndroid Build Coastguard Worker   }
1379*9880d681SAndroid Build Coastguard Worker 
1380*9880d681SAndroid Build Coastguard Worker   if (LandBlkHasOtherPred) {
1381*9880d681SAndroid Build Coastguard Worker     // add endif
1382*9880d681SAndroid Build Coastguard Worker     insertInstrBefore(I, AMDGPU::ENDIF);
1383*9880d681SAndroid Build Coastguard Worker 
1384*9880d681SAndroid Build Coastguard Worker     // put initReg = 2 to other predecessors of landBlk
1385*9880d681SAndroid Build Coastguard Worker     for (MachineBasicBlock::pred_iterator PI = LandBlk->pred_begin(),
1386*9880d681SAndroid Build Coastguard Worker          PE = LandBlk->pred_end(); PI != PE; ++PI) {
1387*9880d681SAndroid Build Coastguard Worker       MachineBasicBlock *MBB = *PI;
1388*9880d681SAndroid Build Coastguard Worker       if (MBB != TrueMBB && MBB != FalseMBB)
1389*9880d681SAndroid Build Coastguard Worker         report_fatal_error("Extra register needed to handle CFG");
1390*9880d681SAndroid Build Coastguard Worker     }
1391*9880d681SAndroid Build Coastguard Worker   }
1392*9880d681SAndroid Build Coastguard Worker   DEBUG(
1393*9880d681SAndroid Build Coastguard Worker     dbgs() << "result from improveSimpleJumpintoIf: ";
1394*9880d681SAndroid Build Coastguard Worker     showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0);
1395*9880d681SAndroid Build Coastguard Worker   );
1396*9880d681SAndroid Build Coastguard Worker 
1397*9880d681SAndroid Build Coastguard Worker   // update landBlk
1398*9880d681SAndroid Build Coastguard Worker   *LandMBBPtr = LandBlk;
1399*9880d681SAndroid Build Coastguard Worker 
1400*9880d681SAndroid Build Coastguard Worker   return NumNewBlk;
1401*9880d681SAndroid Build Coastguard Worker }
1402*9880d681SAndroid Build Coastguard Worker 
mergeSerialBlock(MachineBasicBlock * DstMBB,MachineBasicBlock * SrcMBB)1403*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::mergeSerialBlock(MachineBasicBlock *DstMBB,
1404*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *SrcMBB) {
1405*9880d681SAndroid Build Coastguard Worker   DEBUG(
1406*9880d681SAndroid Build Coastguard Worker     dbgs() << "serialPattern BB" << DstMBB->getNumber()
1407*9880d681SAndroid Build Coastguard Worker            << " <= BB" << SrcMBB->getNumber() << "\n";
1408*9880d681SAndroid Build Coastguard Worker   );
1409*9880d681SAndroid Build Coastguard Worker   DstMBB->splice(DstMBB->end(), SrcMBB, SrcMBB->begin(), SrcMBB->end());
1410*9880d681SAndroid Build Coastguard Worker 
1411*9880d681SAndroid Build Coastguard Worker   DstMBB->removeSuccessor(SrcMBB, true);
1412*9880d681SAndroid Build Coastguard Worker   cloneSuccessorList(DstMBB, SrcMBB);
1413*9880d681SAndroid Build Coastguard Worker 
1414*9880d681SAndroid Build Coastguard Worker   removeSuccessor(SrcMBB);
1415*9880d681SAndroid Build Coastguard Worker   MLI->removeBlock(SrcMBB);
1416*9880d681SAndroid Build Coastguard Worker   retireBlock(SrcMBB);
1417*9880d681SAndroid Build Coastguard Worker }
1418*9880d681SAndroid Build Coastguard Worker 
mergeIfthenelseBlock(MachineInstr * BranchMI,MachineBasicBlock * MBB,MachineBasicBlock * TrueMBB,MachineBasicBlock * FalseMBB,MachineBasicBlock * LandMBB)1419*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::mergeIfthenelseBlock(MachineInstr *BranchMI,
1420*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB, MachineBasicBlock *TrueMBB,
1421*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB) {
1422*9880d681SAndroid Build Coastguard Worker   assert (TrueMBB);
1423*9880d681SAndroid Build Coastguard Worker   DEBUG(
1424*9880d681SAndroid Build Coastguard Worker     dbgs() << "ifPattern BB" << MBB->getNumber();
1425*9880d681SAndroid Build Coastguard Worker     dbgs() << "{  ";
1426*9880d681SAndroid Build Coastguard Worker     if (TrueMBB) {
1427*9880d681SAndroid Build Coastguard Worker       dbgs() << "BB" << TrueMBB->getNumber();
1428*9880d681SAndroid Build Coastguard Worker     }
1429*9880d681SAndroid Build Coastguard Worker     dbgs() << "  } else ";
1430*9880d681SAndroid Build Coastguard Worker     dbgs() << "{  ";
1431*9880d681SAndroid Build Coastguard Worker     if (FalseMBB) {
1432*9880d681SAndroid Build Coastguard Worker       dbgs() << "BB" << FalseMBB->getNumber();
1433*9880d681SAndroid Build Coastguard Worker     }
1434*9880d681SAndroid Build Coastguard Worker     dbgs() << "  }\n ";
1435*9880d681SAndroid Build Coastguard Worker     dbgs() << "landBlock: ";
1436*9880d681SAndroid Build Coastguard Worker     if (!LandMBB) {
1437*9880d681SAndroid Build Coastguard Worker       dbgs() << "NULL";
1438*9880d681SAndroid Build Coastguard Worker     } else {
1439*9880d681SAndroid Build Coastguard Worker       dbgs() << "BB" << LandMBB->getNumber();
1440*9880d681SAndroid Build Coastguard Worker     }
1441*9880d681SAndroid Build Coastguard Worker     dbgs() << "\n";
1442*9880d681SAndroid Build Coastguard Worker   );
1443*9880d681SAndroid Build Coastguard Worker 
1444*9880d681SAndroid Build Coastguard Worker   int OldOpcode = BranchMI->getOpcode();
1445*9880d681SAndroid Build Coastguard Worker   DebugLoc BranchDL = BranchMI->getDebugLoc();
1446*9880d681SAndroid Build Coastguard Worker 
1447*9880d681SAndroid Build Coastguard Worker //    transform to
1448*9880d681SAndroid Build Coastguard Worker //    if cond
1449*9880d681SAndroid Build Coastguard Worker //       trueBlk
1450*9880d681SAndroid Build Coastguard Worker //    else
1451*9880d681SAndroid Build Coastguard Worker //       falseBlk
1452*9880d681SAndroid Build Coastguard Worker //    endif
1453*9880d681SAndroid Build Coastguard Worker //    landBlk
1454*9880d681SAndroid Build Coastguard Worker 
1455*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator I = BranchMI;
1456*9880d681SAndroid Build Coastguard Worker   insertCondBranchBefore(I, getBranchNzeroOpcode(OldOpcode),
1457*9880d681SAndroid Build Coastguard Worker       BranchDL);
1458*9880d681SAndroid Build Coastguard Worker 
1459*9880d681SAndroid Build Coastguard Worker   if (TrueMBB) {
1460*9880d681SAndroid Build Coastguard Worker     MBB->splice(I, TrueMBB, TrueMBB->begin(), TrueMBB->end());
1461*9880d681SAndroid Build Coastguard Worker     MBB->removeSuccessor(TrueMBB, true);
1462*9880d681SAndroid Build Coastguard Worker     if (LandMBB && TrueMBB->succ_size()!=0)
1463*9880d681SAndroid Build Coastguard Worker       TrueMBB->removeSuccessor(LandMBB, true);
1464*9880d681SAndroid Build Coastguard Worker     retireBlock(TrueMBB);
1465*9880d681SAndroid Build Coastguard Worker     MLI->removeBlock(TrueMBB);
1466*9880d681SAndroid Build Coastguard Worker   }
1467*9880d681SAndroid Build Coastguard Worker 
1468*9880d681SAndroid Build Coastguard Worker   if (FalseMBB) {
1469*9880d681SAndroid Build Coastguard Worker     insertInstrBefore(I, AMDGPU::ELSE);
1470*9880d681SAndroid Build Coastguard Worker     MBB->splice(I, FalseMBB, FalseMBB->begin(),
1471*9880d681SAndroid Build Coastguard Worker                    FalseMBB->end());
1472*9880d681SAndroid Build Coastguard Worker     MBB->removeSuccessor(FalseMBB, true);
1473*9880d681SAndroid Build Coastguard Worker     if (LandMBB && FalseMBB->succ_size() != 0)
1474*9880d681SAndroid Build Coastguard Worker       FalseMBB->removeSuccessor(LandMBB, true);
1475*9880d681SAndroid Build Coastguard Worker     retireBlock(FalseMBB);
1476*9880d681SAndroid Build Coastguard Worker     MLI->removeBlock(FalseMBB);
1477*9880d681SAndroid Build Coastguard Worker   }
1478*9880d681SAndroid Build Coastguard Worker   insertInstrBefore(I, AMDGPU::ENDIF);
1479*9880d681SAndroid Build Coastguard Worker 
1480*9880d681SAndroid Build Coastguard Worker   BranchMI->eraseFromParent();
1481*9880d681SAndroid Build Coastguard Worker 
1482*9880d681SAndroid Build Coastguard Worker   if (LandMBB && TrueMBB && FalseMBB)
1483*9880d681SAndroid Build Coastguard Worker     MBB->addSuccessor(LandMBB);
1484*9880d681SAndroid Build Coastguard Worker 
1485*9880d681SAndroid Build Coastguard Worker }
1486*9880d681SAndroid Build Coastguard Worker 
mergeLooplandBlock(MachineBasicBlock * DstBlk,MachineBasicBlock * LandMBB)1487*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::mergeLooplandBlock(MachineBasicBlock *DstBlk,
1488*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *LandMBB) {
1489*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "loopPattern header = BB" << DstBlk->getNumber()
1490*9880d681SAndroid Build Coastguard Worker                << " land = BB" << LandMBB->getNumber() << "\n";);
1491*9880d681SAndroid Build Coastguard Worker 
1492*9880d681SAndroid Build Coastguard Worker   insertInstrBefore(DstBlk, AMDGPU::WHILELOOP, DebugLoc());
1493*9880d681SAndroid Build Coastguard Worker   insertInstrEnd(DstBlk, AMDGPU::ENDLOOP, DebugLoc());
1494*9880d681SAndroid Build Coastguard Worker   DstBlk->replaceSuccessor(DstBlk, LandMBB);
1495*9880d681SAndroid Build Coastguard Worker }
1496*9880d681SAndroid Build Coastguard Worker 
1497*9880d681SAndroid Build Coastguard Worker 
mergeLoopbreakBlock(MachineBasicBlock * ExitingMBB,MachineBasicBlock * LandMBB)1498*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
1499*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *LandMBB) {
1500*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "loopbreakPattern exiting = BB" << ExitingMBB->getNumber()
1501*9880d681SAndroid Build Coastguard Worker                << " land = BB" << LandMBB->getNumber() << "\n";);
1502*9880d681SAndroid Build Coastguard Worker   MachineInstr *BranchMI = getLoopendBlockBranchInstr(ExitingMBB);
1503*9880d681SAndroid Build Coastguard Worker   assert(BranchMI && isCondBranch(BranchMI));
1504*9880d681SAndroid Build Coastguard Worker   DebugLoc DL = BranchMI->getDebugLoc();
1505*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *TrueBranch = getTrueBranch(BranchMI);
1506*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator I = BranchMI;
1507*9880d681SAndroid Build Coastguard Worker   if (TrueBranch != LandMBB)
1508*9880d681SAndroid Build Coastguard Worker     reversePredicateSetter(I);
1509*9880d681SAndroid Build Coastguard Worker   insertCondBranchBefore(ExitingMBB, I, AMDGPU::IF_PREDICATE_SET, AMDGPU::PREDICATE_BIT, DL);
1510*9880d681SAndroid Build Coastguard Worker   insertInstrBefore(I, AMDGPU::BREAK);
1511*9880d681SAndroid Build Coastguard Worker   insertInstrBefore(I, AMDGPU::ENDIF);
1512*9880d681SAndroid Build Coastguard Worker   //now branchInst can be erase safely
1513*9880d681SAndroid Build Coastguard Worker   BranchMI->eraseFromParent();
1514*9880d681SAndroid Build Coastguard Worker   //now take care of successors, retire blocks
1515*9880d681SAndroid Build Coastguard Worker   ExitingMBB->removeSuccessor(LandMBB, true);
1516*9880d681SAndroid Build Coastguard Worker }
1517*9880d681SAndroid Build Coastguard Worker 
settleLoopcontBlock(MachineBasicBlock * ContingMBB,MachineBasicBlock * ContMBB)1518*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::settleLoopcontBlock(MachineBasicBlock *ContingMBB,
1519*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *ContMBB) {
1520*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "settleLoopcontBlock conting = BB"
1521*9880d681SAndroid Build Coastguard Worker                << ContingMBB->getNumber()
1522*9880d681SAndroid Build Coastguard Worker                << ", cont = BB" << ContMBB->getNumber() << "\n";);
1523*9880d681SAndroid Build Coastguard Worker 
1524*9880d681SAndroid Build Coastguard Worker   MachineInstr *MI = getLoopendBlockBranchInstr(ContingMBB);
1525*9880d681SAndroid Build Coastguard Worker   if (MI) {
1526*9880d681SAndroid Build Coastguard Worker     assert(isCondBranch(MI));
1527*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock::iterator I = MI;
1528*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *TrueBranch = getTrueBranch(MI);
1529*9880d681SAndroid Build Coastguard Worker     int OldOpcode = MI->getOpcode();
1530*9880d681SAndroid Build Coastguard Worker     DebugLoc DL = MI->getDebugLoc();
1531*9880d681SAndroid Build Coastguard Worker 
1532*9880d681SAndroid Build Coastguard Worker     bool UseContinueLogical = ((&*ContingMBB->rbegin()) == MI);
1533*9880d681SAndroid Build Coastguard Worker 
1534*9880d681SAndroid Build Coastguard Worker     if (!UseContinueLogical) {
1535*9880d681SAndroid Build Coastguard Worker       int BranchOpcode =
1536*9880d681SAndroid Build Coastguard Worker           TrueBranch == ContMBB ? getBranchNzeroOpcode(OldOpcode) :
1537*9880d681SAndroid Build Coastguard Worker           getBranchZeroOpcode(OldOpcode);
1538*9880d681SAndroid Build Coastguard Worker       insertCondBranchBefore(I, BranchOpcode, DL);
1539*9880d681SAndroid Build Coastguard Worker       // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
1540*9880d681SAndroid Build Coastguard Worker       insertInstrEnd(ContingMBB, AMDGPU::CONTINUE, DL);
1541*9880d681SAndroid Build Coastguard Worker       insertInstrEnd(ContingMBB, AMDGPU::ENDIF, DL);
1542*9880d681SAndroid Build Coastguard Worker     } else {
1543*9880d681SAndroid Build Coastguard Worker       int BranchOpcode =
1544*9880d681SAndroid Build Coastguard Worker           TrueBranch == ContMBB ? getContinueNzeroOpcode(OldOpcode) :
1545*9880d681SAndroid Build Coastguard Worker           getContinueZeroOpcode(OldOpcode);
1546*9880d681SAndroid Build Coastguard Worker       insertCondBranchBefore(I, BranchOpcode, DL);
1547*9880d681SAndroid Build Coastguard Worker     }
1548*9880d681SAndroid Build Coastguard Worker 
1549*9880d681SAndroid Build Coastguard Worker     MI->eraseFromParent();
1550*9880d681SAndroid Build Coastguard Worker   } else {
1551*9880d681SAndroid Build Coastguard Worker     // if we've arrived here then we've already erased the branch instruction
1552*9880d681SAndroid Build Coastguard Worker     // travel back up the basic block to see the last reference of our debug
1553*9880d681SAndroid Build Coastguard Worker     // location we've just inserted that reference here so it should be
1554*9880d681SAndroid Build Coastguard Worker     // representative insertEnd to ensure phi-moves, if exist, go before the
1555*9880d681SAndroid Build Coastguard Worker     // continue-instr.
1556*9880d681SAndroid Build Coastguard Worker     insertInstrEnd(ContingMBB, AMDGPU::CONTINUE,
1557*9880d681SAndroid Build Coastguard Worker         getLastDebugLocInBB(ContingMBB));
1558*9880d681SAndroid Build Coastguard Worker   }
1559*9880d681SAndroid Build Coastguard Worker }
1560*9880d681SAndroid Build Coastguard Worker 
cloneOnSideEntryTo(MachineBasicBlock * PreMBB,MachineBasicBlock * SrcMBB,MachineBasicBlock * DstMBB)1561*9880d681SAndroid Build Coastguard Worker int AMDGPUCFGStructurizer::cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
1562*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB) {
1563*9880d681SAndroid Build Coastguard Worker   int Cloned = 0;
1564*9880d681SAndroid Build Coastguard Worker   assert(PreMBB->isSuccessor(SrcMBB));
1565*9880d681SAndroid Build Coastguard Worker   while (SrcMBB && SrcMBB != DstMBB) {
1566*9880d681SAndroid Build Coastguard Worker     assert(SrcMBB->succ_size() == 1);
1567*9880d681SAndroid Build Coastguard Worker     if (SrcMBB->pred_size() > 1) {
1568*9880d681SAndroid Build Coastguard Worker       SrcMBB = cloneBlockForPredecessor(SrcMBB, PreMBB);
1569*9880d681SAndroid Build Coastguard Worker       ++Cloned;
1570*9880d681SAndroid Build Coastguard Worker     }
1571*9880d681SAndroid Build Coastguard Worker 
1572*9880d681SAndroid Build Coastguard Worker     PreMBB = SrcMBB;
1573*9880d681SAndroid Build Coastguard Worker     SrcMBB = *SrcMBB->succ_begin();
1574*9880d681SAndroid Build Coastguard Worker   }
1575*9880d681SAndroid Build Coastguard Worker 
1576*9880d681SAndroid Build Coastguard Worker   return Cloned;
1577*9880d681SAndroid Build Coastguard Worker }
1578*9880d681SAndroid Build Coastguard Worker 
1579*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *
cloneBlockForPredecessor(MachineBasicBlock * MBB,MachineBasicBlock * PredMBB)1580*9880d681SAndroid Build Coastguard Worker AMDGPUCFGStructurizer::cloneBlockForPredecessor(MachineBasicBlock *MBB,
1581*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *PredMBB) {
1582*9880d681SAndroid Build Coastguard Worker   assert(PredMBB->isSuccessor(MBB) &&
1583*9880d681SAndroid Build Coastguard Worker          "succBlk is not a prececessor of curBlk");
1584*9880d681SAndroid Build Coastguard Worker 
1585*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *CloneMBB = clone(MBB);  //clone instructions
1586*9880d681SAndroid Build Coastguard Worker   replaceInstrUseOfBlockWith(PredMBB, MBB, CloneMBB);
1587*9880d681SAndroid Build Coastguard Worker   //srcBlk, oldBlk, newBlk
1588*9880d681SAndroid Build Coastguard Worker 
1589*9880d681SAndroid Build Coastguard Worker   PredMBB->replaceSuccessor(MBB, CloneMBB);
1590*9880d681SAndroid Build Coastguard Worker 
1591*9880d681SAndroid Build Coastguard Worker   // add all successor to cloneBlk
1592*9880d681SAndroid Build Coastguard Worker   cloneSuccessorList(CloneMBB, MBB);
1593*9880d681SAndroid Build Coastguard Worker 
1594*9880d681SAndroid Build Coastguard Worker   numClonedInstr += MBB->size();
1595*9880d681SAndroid Build Coastguard Worker 
1596*9880d681SAndroid Build Coastguard Worker   DEBUG(
1597*9880d681SAndroid Build Coastguard Worker     dbgs() << "Cloned block: " << "BB"
1598*9880d681SAndroid Build Coastguard Worker            << MBB->getNumber() << "size " << MBB->size() << "\n";
1599*9880d681SAndroid Build Coastguard Worker   );
1600*9880d681SAndroid Build Coastguard Worker 
1601*9880d681SAndroid Build Coastguard Worker   SHOWNEWBLK(CloneMBB, "result of Cloned block: ");
1602*9880d681SAndroid Build Coastguard Worker 
1603*9880d681SAndroid Build Coastguard Worker   return CloneMBB;
1604*9880d681SAndroid Build Coastguard Worker }
1605*9880d681SAndroid Build Coastguard Worker 
migrateInstruction(MachineBasicBlock * SrcMBB,MachineBasicBlock * DstMBB,MachineBasicBlock::iterator I)1606*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::migrateInstruction(MachineBasicBlock *SrcMBB,
1607*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *DstMBB, MachineBasicBlock::iterator I) {
1608*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock::iterator SpliceEnd;
1609*9880d681SAndroid Build Coastguard Worker   //look for the input branchinstr, not the AMDGPU branchinstr
1610*9880d681SAndroid Build Coastguard Worker   MachineInstr *BranchMI = getNormalBlockBranchInstr(SrcMBB);
1611*9880d681SAndroid Build Coastguard Worker   if (!BranchMI) {
1612*9880d681SAndroid Build Coastguard Worker     DEBUG(
1613*9880d681SAndroid Build Coastguard Worker       dbgs() << "migrateInstruction don't see branch instr\n" ;
1614*9880d681SAndroid Build Coastguard Worker     );
1615*9880d681SAndroid Build Coastguard Worker     SpliceEnd = SrcMBB->end();
1616*9880d681SAndroid Build Coastguard Worker   } else {
1617*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "migrateInstruction see branch instr: " << *BranchMI);
1618*9880d681SAndroid Build Coastguard Worker     SpliceEnd = BranchMI;
1619*9880d681SAndroid Build Coastguard Worker   }
1620*9880d681SAndroid Build Coastguard Worker   DEBUG(
1621*9880d681SAndroid Build Coastguard Worker     dbgs() << "migrateInstruction before splice dstSize = " << DstMBB->size()
1622*9880d681SAndroid Build Coastguard Worker       << "srcSize = " << SrcMBB->size() << "\n";
1623*9880d681SAndroid Build Coastguard Worker   );
1624*9880d681SAndroid Build Coastguard Worker 
1625*9880d681SAndroid Build Coastguard Worker   //splice insert before insertPos
1626*9880d681SAndroid Build Coastguard Worker   DstMBB->splice(I, SrcMBB, SrcMBB->begin(), SpliceEnd);
1627*9880d681SAndroid Build Coastguard Worker 
1628*9880d681SAndroid Build Coastguard Worker   DEBUG(
1629*9880d681SAndroid Build Coastguard Worker     dbgs() << "migrateInstruction after splice dstSize = " << DstMBB->size()
1630*9880d681SAndroid Build Coastguard Worker       << "srcSize = " << SrcMBB->size() << '\n';
1631*9880d681SAndroid Build Coastguard Worker   );
1632*9880d681SAndroid Build Coastguard Worker }
1633*9880d681SAndroid Build Coastguard Worker 
1634*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *
normalizeInfiniteLoopExit(MachineLoop * LoopRep)1635*9880d681SAndroid Build Coastguard Worker AMDGPUCFGStructurizer::normalizeInfiniteLoopExit(MachineLoop* LoopRep) {
1636*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *LoopHeader = LoopRep->getHeader();
1637*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *LoopLatch = LoopRep->getLoopLatch();
1638*9880d681SAndroid Build Coastguard Worker 
1639*9880d681SAndroid Build Coastguard Worker   if (!LoopHeader || !LoopLatch)
1640*9880d681SAndroid Build Coastguard Worker     return nullptr;
1641*9880d681SAndroid Build Coastguard Worker   MachineInstr *BranchMI = getLoopendBlockBranchInstr(LoopLatch);
1642*9880d681SAndroid Build Coastguard Worker   // Is LoopRep an infinite loop ?
1643*9880d681SAndroid Build Coastguard Worker   if (!BranchMI || !isUncondBranch(BranchMI))
1644*9880d681SAndroid Build Coastguard Worker     return nullptr;
1645*9880d681SAndroid Build Coastguard Worker 
1646*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *DummyExitBlk = FuncRep->CreateMachineBasicBlock();
1647*9880d681SAndroid Build Coastguard Worker   FuncRep->push_back(DummyExitBlk);  //insert to function
1648*9880d681SAndroid Build Coastguard Worker   SHOWNEWBLK(DummyExitBlk, "DummyExitBlock to normalize infiniteLoop: ");
1649*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "Old branch instr: " << *BranchMI << "\n";);
1650*9880d681SAndroid Build Coastguard Worker   LLVMContext &Ctx = LoopHeader->getParent()->getFunction()->getContext();
1651*9880d681SAndroid Build Coastguard Worker   Ctx.emitError("Extra register needed to handle CFG");
1652*9880d681SAndroid Build Coastguard Worker   return nullptr;
1653*9880d681SAndroid Build Coastguard Worker }
1654*9880d681SAndroid Build Coastguard Worker 
removeUnconditionalBranch(MachineBasicBlock * MBB)1655*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::removeUnconditionalBranch(MachineBasicBlock *MBB) {
1656*9880d681SAndroid Build Coastguard Worker   MachineInstr *BranchMI;
1657*9880d681SAndroid Build Coastguard Worker 
1658*9880d681SAndroid Build Coastguard Worker   // I saw two unconditional branch in one basic block in example
1659*9880d681SAndroid Build Coastguard Worker   // test_fc_do_while_or.c need to fix the upstream on this to remove the loop.
1660*9880d681SAndroid Build Coastguard Worker   while ((BranchMI = getLoopendBlockBranchInstr(MBB))
1661*9880d681SAndroid Build Coastguard Worker           && isUncondBranch(BranchMI)) {
1662*9880d681SAndroid Build Coastguard Worker     DEBUG(dbgs() << "Removing uncond branch instr: " << *BranchMI);
1663*9880d681SAndroid Build Coastguard Worker     BranchMI->eraseFromParent();
1664*9880d681SAndroid Build Coastguard Worker   }
1665*9880d681SAndroid Build Coastguard Worker }
1666*9880d681SAndroid Build Coastguard Worker 
removeRedundantConditionalBranch(MachineBasicBlock * MBB)1667*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::removeRedundantConditionalBranch(
1668*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB) {
1669*9880d681SAndroid Build Coastguard Worker   if (MBB->succ_size() != 2)
1670*9880d681SAndroid Build Coastguard Worker     return;
1671*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB1 = *MBB->succ_begin();
1672*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *MBB2 = *std::next(MBB->succ_begin());
1673*9880d681SAndroid Build Coastguard Worker   if (MBB1 != MBB2)
1674*9880d681SAndroid Build Coastguard Worker     return;
1675*9880d681SAndroid Build Coastguard Worker 
1676*9880d681SAndroid Build Coastguard Worker   MachineInstr *BranchMI = getNormalBlockBranchInstr(MBB);
1677*9880d681SAndroid Build Coastguard Worker   assert(BranchMI && isCondBranch(BranchMI));
1678*9880d681SAndroid Build Coastguard Worker   DEBUG(dbgs() << "Removing unneeded cond branch instr: " << *BranchMI);
1679*9880d681SAndroid Build Coastguard Worker   BranchMI->eraseFromParent();
1680*9880d681SAndroid Build Coastguard Worker   SHOWNEWBLK(MBB1, "Removing redundant successor");
1681*9880d681SAndroid Build Coastguard Worker   MBB->removeSuccessor(MBB1, true);
1682*9880d681SAndroid Build Coastguard Worker }
1683*9880d681SAndroid Build Coastguard Worker 
addDummyExitBlock(SmallVectorImpl<MachineBasicBlock * > & RetMBB)1684*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::addDummyExitBlock(
1685*9880d681SAndroid Build Coastguard Worker     SmallVectorImpl<MachineBasicBlock*> &RetMBB) {
1686*9880d681SAndroid Build Coastguard Worker   MachineBasicBlock *DummyExitBlk = FuncRep->CreateMachineBasicBlock();
1687*9880d681SAndroid Build Coastguard Worker   FuncRep->push_back(DummyExitBlk);  //insert to function
1688*9880d681SAndroid Build Coastguard Worker   insertInstrEnd(DummyExitBlk, AMDGPU::RETURN);
1689*9880d681SAndroid Build Coastguard Worker 
1690*9880d681SAndroid Build Coastguard Worker   for (SmallVectorImpl<MachineBasicBlock *>::iterator It = RetMBB.begin(),
1691*9880d681SAndroid Build Coastguard Worker        E = RetMBB.end(); It != E; ++It) {
1692*9880d681SAndroid Build Coastguard Worker     MachineBasicBlock *MBB = *It;
1693*9880d681SAndroid Build Coastguard Worker     MachineInstr *MI = getReturnInstr(MBB);
1694*9880d681SAndroid Build Coastguard Worker     if (MI)
1695*9880d681SAndroid Build Coastguard Worker       MI->eraseFromParent();
1696*9880d681SAndroid Build Coastguard Worker     MBB->addSuccessor(DummyExitBlk);
1697*9880d681SAndroid Build Coastguard Worker     DEBUG(
1698*9880d681SAndroid Build Coastguard Worker       dbgs() << "Add dummyExitBlock to BB" << MBB->getNumber()
1699*9880d681SAndroid Build Coastguard Worker              << " successors\n";
1700*9880d681SAndroid Build Coastguard Worker     );
1701*9880d681SAndroid Build Coastguard Worker   }
1702*9880d681SAndroid Build Coastguard Worker   SHOWNEWBLK(DummyExitBlk, "DummyExitBlock: ");
1703*9880d681SAndroid Build Coastguard Worker }
1704*9880d681SAndroid Build Coastguard Worker 
removeSuccessor(MachineBasicBlock * MBB)1705*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::removeSuccessor(MachineBasicBlock *MBB) {
1706*9880d681SAndroid Build Coastguard Worker   while (MBB->succ_size())
1707*9880d681SAndroid Build Coastguard Worker     MBB->removeSuccessor(*MBB->succ_begin());
1708*9880d681SAndroid Build Coastguard Worker }
1709*9880d681SAndroid Build Coastguard Worker 
recordSccnum(MachineBasicBlock * MBB,int SccNum)1710*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::recordSccnum(MachineBasicBlock *MBB,
1711*9880d681SAndroid Build Coastguard Worker     int SccNum) {
1712*9880d681SAndroid Build Coastguard Worker   BlockInformation *&srcBlkInfo = BlockInfoMap[MBB];
1713*9880d681SAndroid Build Coastguard Worker   if (!srcBlkInfo)
1714*9880d681SAndroid Build Coastguard Worker     srcBlkInfo = new BlockInformation();
1715*9880d681SAndroid Build Coastguard Worker   srcBlkInfo->SccNum = SccNum;
1716*9880d681SAndroid Build Coastguard Worker }
1717*9880d681SAndroid Build Coastguard Worker 
retireBlock(MachineBasicBlock * MBB)1718*9880d681SAndroid Build Coastguard Worker void AMDGPUCFGStructurizer::retireBlock(MachineBasicBlock *MBB) {
1719*9880d681SAndroid Build Coastguard Worker   DEBUG(
1720*9880d681SAndroid Build Coastguard Worker         dbgs() << "Retiring BB" << MBB->getNumber() << "\n";
1721*9880d681SAndroid Build Coastguard Worker   );
1722*9880d681SAndroid Build Coastguard Worker 
1723*9880d681SAndroid Build Coastguard Worker   BlockInformation *&SrcBlkInfo = BlockInfoMap[MBB];
1724*9880d681SAndroid Build Coastguard Worker 
1725*9880d681SAndroid Build Coastguard Worker   if (!SrcBlkInfo)
1726*9880d681SAndroid Build Coastguard Worker     SrcBlkInfo = new BlockInformation();
1727*9880d681SAndroid Build Coastguard Worker 
1728*9880d681SAndroid Build Coastguard Worker   SrcBlkInfo->IsRetired = true;
1729*9880d681SAndroid Build Coastguard Worker   assert(MBB->succ_size() == 0 && MBB->pred_size() == 0
1730*9880d681SAndroid Build Coastguard Worker          && "can't retire block yet");
1731*9880d681SAndroid Build Coastguard Worker }
1732*9880d681SAndroid Build Coastguard Worker 
1733*9880d681SAndroid Build Coastguard Worker char AMDGPUCFGStructurizer::ID = 0;
1734*9880d681SAndroid Build Coastguard Worker 
1735*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
1736*9880d681SAndroid Build Coastguard Worker 
1737*9880d681SAndroid Build Coastguard Worker 
1738*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(AMDGPUCFGStructurizer, "amdgpustructurizer",
1739*9880d681SAndroid Build Coastguard Worker                       "AMDGPU CFG Structurizer", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)1740*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
1741*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
1742*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
1743*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(AMDGPUCFGStructurizer, "amdgpustructurizer",
1744*9880d681SAndroid Build Coastguard Worker                       "AMDGPU CFG Structurizer", false, false)
1745*9880d681SAndroid Build Coastguard Worker 
1746*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createAMDGPUCFGStructurizerPass() {
1747*9880d681SAndroid Build Coastguard Worker   return new AMDGPUCFGStructurizer();
1748*9880d681SAndroid Build Coastguard Worker }
1749