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