blob: 6b61a0376df9548b8193cb241592164159aca466 [file] [log] [blame]
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001//===-- AMDILCFGStructurizer.cpp - CFG Structurizer -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8/// \file
9//==-----------------------------------------------------------------------===//
10
Tom Stellardf98f2ce2012-12-11 21:25:42 +000011#define DEBUG_TYPE "structcfg"
12
Tom Stellard3ff0abf2013-06-07 20:37:48 +000013#include "AMDGPU.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000014#include "AMDGPUInstrInfo.h"
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +000015#include "llvm/Support/Debug.h"
16#include "llvm/Support/raw_ostream.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000017#include "llvm/ADT/SCCIterator.h"
18#include "llvm/ADT/SmallVector.h"
19#include "llvm/ADT/Statistic.h"
20#include "llvm/Analysis/DominatorInternals.h"
21#include "llvm/Analysis/Dominators.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000022#include "llvm/CodeGen/MachineDominators.h"
23#include "llvm/CodeGen/MachineFunction.h"
24#include "llvm/CodeGen/MachineFunctionAnalysis.h"
25#include "llvm/CodeGen/MachineFunctionPass.h"
26#include "llvm/CodeGen/MachineInstrBuilder.h"
27#include "llvm/CodeGen/MachineJumpTableInfo.h"
28#include "llvm/CodeGen/MachineLoopInfo.h"
Chandler Carruth58a2cbe2013-01-02 10:22:59 +000029#include "llvm/CodeGen/MachinePostDominators.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000030#include "llvm/CodeGen/MachineRegisterInfo.h"
31#include "llvm/Target/TargetInstrInfo.h"
Tom Stellard3ff0abf2013-06-07 20:37:48 +000032#include "llvm/Target/TargetMachine.h"
Tom Stellardf98f2ce2012-12-11 21:25:42 +000033
34using namespace llvm;
35
Tom Stellard3ff0abf2013-06-07 20:37:48 +000036#define DEFAULT_VEC_SLOTS 8
37
Tom Stellardf98f2ce2012-12-11 21:25:42 +000038// TODO: move-begin.
39
40//===----------------------------------------------------------------------===//
41//
42// Statistics for CFGStructurizer.
43//
44//===----------------------------------------------------------------------===//
45
46STATISTIC(numSerialPatternMatch, "CFGStructurizer number of serial pattern "
47 "matched");
48STATISTIC(numIfPatternMatch, "CFGStructurizer number of if pattern "
49 "matched");
50STATISTIC(numLoopbreakPatternMatch, "CFGStructurizer number of loop-break "
51 "pattern matched");
52STATISTIC(numLoopcontPatternMatch, "CFGStructurizer number of loop-continue "
53 "pattern matched");
54STATISTIC(numLoopPatternMatch, "CFGStructurizer number of loop pattern "
55 "matched");
56STATISTIC(numClonedBlock, "CFGStructurizer cloned blocks");
57STATISTIC(numClonedInstr, "CFGStructurizer cloned instructions");
58
59//===----------------------------------------------------------------------===//
60//
61// Miscellaneous utility for CFGStructurizer.
62//
63//===----------------------------------------------------------------------===//
Benjamin Kramer879b0712013-05-23 15:43:05 +000064namespace {
Tom Stellardf98f2ce2012-12-11 21:25:42 +000065#define SHOWNEWINSTR(i) \
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +000066 DEBUG(dbgs() << "New instr: " << *i << "\n");
Tom Stellardf98f2ce2012-12-11 21:25:42 +000067
68#define SHOWNEWBLK(b, msg) \
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +000069DEBUG( \
70 dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
71 dbgs() << "\n"; \
72);
Tom Stellardf98f2ce2012-12-11 21:25:42 +000073
74#define SHOWBLK_DETAIL(b, msg) \
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +000075DEBUG( \
Tom Stellardf98f2ce2012-12-11 21:25:42 +000076 if (b) { \
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +000077 dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
78 b->print(dbgs()); \
79 dbgs() << "\n"; \
Tom Stellardf98f2ce2012-12-11 21:25:42 +000080 } \
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +000081);
Tom Stellardf98f2ce2012-12-11 21:25:42 +000082
83#define INVALIDSCCNUM -1
84#define INVALIDREGNUM 0
85
86template<class LoopinfoT>
87void PrintLoopinfo(const LoopinfoT &LoopInfo, llvm::raw_ostream &OS) {
88 for (typename LoopinfoT::iterator iter = LoopInfo.begin(),
89 iterEnd = LoopInfo.end();
90 iter != iterEnd; ++iter) {
91 (*iter)->print(OS, 0);
92 }
93}
94
95template<class NodeT>
Craig Toppera0ec3f92013-07-14 04:42:23 +000096void ReverseVector(SmallVectorImpl<NodeT *> &Src) {
Tom Stellardf98f2ce2012-12-11 21:25:42 +000097 size_t sz = Src.size();
98 for (size_t i = 0; i < sz/2; ++i) {
99 NodeT *t = Src[i];
100 Src[i] = Src[sz - i - 1];
101 Src[sz - i - 1] = t;
102 }
103}
104
Benjamin Kramer879b0712013-05-23 15:43:05 +0000105} // end anonymous namespace
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000106
107//===----------------------------------------------------------------------===//
108//
109// supporting data structure for CFGStructurizer
110//
111//===----------------------------------------------------------------------===//
112
Benjamin Kramer879b0712013-05-23 15:43:05 +0000113namespace {
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000114template<class PassT>
115struct CFGStructTraits {
116};
117
118template <class InstrT>
119class BlockInformation {
120public:
121 bool isRetired;
122 int sccNum;
123 //SmallVector<InstrT*, DEFAULT_VEC_SLOTS> succInstr;
124 //Instructions defining the corresponding successor.
125 BlockInformation() : isRetired(false), sccNum(INVALIDSCCNUM) {}
126};
127
128template <class BlockT, class InstrT, class RegiT>
129class LandInformation {
130public:
131 BlockT *landBlk;
132 std::set<RegiT> breakInitRegs; //Registers that need to "reg = 0", before
133 //WHILELOOP(thisloop) init before entering
134 //thisloop.
135 std::set<RegiT> contInitRegs; //Registers that need to "reg = 0", after
136 //WHILELOOP(thisloop) init after entering
137 //thisloop.
138 std::set<RegiT> endbranchInitRegs; //Init before entering this loop, at loop
139 //land block, branch cond on this reg.
140 std::set<RegiT> breakOnRegs; //registers that need to "if (reg) break
141 //endif" after ENDLOOP(thisloop) break
142 //outerLoopOf(thisLoop).
143 std::set<RegiT> contOnRegs; //registers that need to "if (reg) continue
144 //endif" after ENDLOOP(thisloop) continue on
145 //outerLoopOf(thisLoop).
146 LandInformation() : landBlk(NULL) {}
147};
148
Benjamin Kramer879b0712013-05-23 15:43:05 +0000149} // end anonymous namespace
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000150
151//===----------------------------------------------------------------------===//
152//
153// CFGStructurizer
154//
155//===----------------------------------------------------------------------===//
156
Benjamin Kramer879b0712013-05-23 15:43:05 +0000157namespace {
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000158// bixia TODO: port it to BasicBlock, not just MachineBasicBlock.
159template<class PassT>
160class CFGStructurizer {
161public:
162 typedef enum {
163 Not_SinglePath = 0,
164 SinglePath_InPath = 1,
165 SinglePath_NotInPath = 2
166 } PathToKind;
167
168public:
169 typedef typename PassT::InstructionType InstrT;
170 typedef typename PassT::FunctionType FuncT;
171 typedef typename PassT::DominatortreeType DomTreeT;
172 typedef typename PassT::PostDominatortreeType PostDomTreeT;
173 typedef typename PassT::DomTreeNodeType DomTreeNodeT;
174 typedef typename PassT::LoopinfoType LoopInfoT;
175
176 typedef GraphTraits<FuncT *> FuncGTraits;
177 //typedef FuncGTraits::nodes_iterator BlockIterator;
178 typedef typename FuncT::iterator BlockIterator;
179
180 typedef typename FuncGTraits::NodeType BlockT;
181 typedef GraphTraits<BlockT *> BlockGTraits;
182 typedef GraphTraits<Inverse<BlockT *> > InvBlockGTraits;
183 //typedef BlockGTraits::succ_iterator InstructionIterator;
184 typedef typename BlockT::iterator InstrIterator;
185
186 typedef CFGStructTraits<PassT> CFGTraits;
187 typedef BlockInformation<InstrT> BlockInfo;
188 typedef std::map<BlockT *, BlockInfo *> BlockInfoMap;
189
190 typedef int RegiT;
191 typedef typename PassT::LoopType LoopT;
192 typedef LandInformation<BlockT, InstrT, RegiT> LoopLandInfo;
193 typedef std::map<LoopT *, LoopLandInfo *> LoopLandInfoMap;
194 //landing info for loop break
195 typedef SmallVector<BlockT *, 32> BlockTSmallerVector;
196
197public:
198 CFGStructurizer();
199 ~CFGStructurizer();
200
201 /// Perform the CFG structurization
202 bool run(FuncT &Func, PassT &Pass, const AMDGPURegisterInfo *tri);
203
204 /// Perform the CFG preparation
205 bool prepare(FuncT &Func, PassT &Pass, const AMDGPURegisterInfo *tri);
206
207private:
208 void reversePredicateSetter(typename BlockT::iterator);
209 void orderBlocks();
210 void printOrderedBlocks(llvm::raw_ostream &OS);
211 int patternMatch(BlockT *CurBlock);
212 int patternMatchGroup(BlockT *CurBlock);
213
214 int serialPatternMatch(BlockT *CurBlock);
215 int ifPatternMatch(BlockT *CurBlock);
216 int switchPatternMatch(BlockT *CurBlock);
217 int loopendPatternMatch(BlockT *CurBlock);
218 int loopPatternMatch(BlockT *CurBlock);
219
220 int loopbreakPatternMatch(LoopT *LoopRep, BlockT *LoopHeader);
221 int loopcontPatternMatch(LoopT *LoopRep, BlockT *LoopHeader);
222 //int loopWithoutBreak(BlockT *);
223
224 void handleLoopbreak (BlockT *ExitingBlock, LoopT *ExitingLoop,
225 BlockT *ExitBlock, LoopT *exitLoop, BlockT *landBlock);
226 void handleLoopcontBlock(BlockT *ContingBlock, LoopT *contingLoop,
227 BlockT *ContBlock, LoopT *contLoop);
228 bool isSameloopDetachedContbreak(BlockT *Src1Block, BlockT *Src2Block);
229 int handleJumpintoIf(BlockT *HeadBlock, BlockT *TrueBlock,
230 BlockT *FalseBlock);
231 int handleJumpintoIfImp(BlockT *HeadBlock, BlockT *TrueBlock,
232 BlockT *FalseBlock);
233 int improveSimpleJumpintoIf(BlockT *HeadBlock, BlockT *TrueBlock,
234 BlockT *FalseBlock, BlockT **LandBlockPtr);
235 void showImproveSimpleJumpintoIf(BlockT *HeadBlock, BlockT *TrueBlock,
236 BlockT *FalseBlock, BlockT *LandBlock,
237 bool Detail = false);
238 PathToKind singlePathTo(BlockT *SrcBlock, BlockT *DstBlock,
239 bool AllowSideEntry = true);
240 BlockT *singlePathEnd(BlockT *srcBlock, BlockT *DstBlock,
241 bool AllowSideEntry = true);
242 int cloneOnSideEntryTo(BlockT *PreBlock, BlockT *SrcBlock, BlockT *DstBlock);
243 void mergeSerialBlock(BlockT *DstBlock, BlockT *srcBlock);
244
245 void mergeIfthenelseBlock(InstrT *BranchInstr, BlockT *CurBlock,
246 BlockT *TrueBlock, BlockT *FalseBlock,
247 BlockT *LandBlock);
248 void mergeLooplandBlock(BlockT *DstBlock, LoopLandInfo *LoopLand);
249 void mergeLoopbreakBlock(BlockT *ExitingBlock, BlockT *ExitBlock,
250 BlockT *ExitLandBlock, RegiT SetReg);
251 void settleLoopcontBlock(BlockT *ContingBlock, BlockT *ContBlock,
252 RegiT SetReg);
253 BlockT *relocateLoopcontBlock(LoopT *ParentLoopRep, LoopT *LoopRep,
254 std::set<BlockT*> &ExitBlockSet,
255 BlockT *ExitLandBlk);
256 BlockT *addLoopEndbranchBlock(LoopT *LoopRep,
257 BlockTSmallerVector &ExitingBlocks,
258 BlockTSmallerVector &ExitBlocks);
259 BlockT *normalizeInfiniteLoopExit(LoopT *LoopRep);
260 void removeUnconditionalBranch(BlockT *SrcBlock);
261 void removeRedundantConditionalBranch(BlockT *SrcBlock);
Craig Toppera0ec3f92013-07-14 04:42:23 +0000262 void addDummyExitBlock(SmallVectorImpl<BlockT *> &RetBlocks);
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000263
264 void removeSuccessor(BlockT *SrcBlock);
265 BlockT *cloneBlockForPredecessor(BlockT *CurBlock, BlockT *PredBlock);
266 BlockT *exitingBlock2ExitBlock (LoopT *LoopRep, BlockT *exitingBlock);
267
268 void migrateInstruction(BlockT *SrcBlock, BlockT *DstBlock,
269 InstrIterator InsertPos);
270
271 void recordSccnum(BlockT *SrcBlock, int SCCNum);
272 int getSCCNum(BlockT *srcBlk);
273
274 void retireBlock(BlockT *DstBlock, BlockT *SrcBlock);
275 bool isRetiredBlock(BlockT *SrcBlock);
276 bool isActiveLoophead(BlockT *CurBlock);
277 bool needMigrateBlock(BlockT *Block);
278
279 BlockT *recordLoopLandBlock(LoopT *LoopRep, BlockT *LandBlock,
280 BlockTSmallerVector &exitBlocks,
281 std::set<BlockT*> &ExitBlockSet);
282 void setLoopLandBlock(LoopT *LoopRep, BlockT *Block = NULL);
283 BlockT *getLoopLandBlock(LoopT *LoopRep);
284 LoopLandInfo *getLoopLandInfo(LoopT *LoopRep);
285
286 void addLoopBreakOnReg(LoopT *LoopRep, RegiT RegNum);
287 void addLoopContOnReg(LoopT *LoopRep, RegiT RegNum);
288 void addLoopBreakInitReg(LoopT *LoopRep, RegiT RegNum);
289 void addLoopContInitReg(LoopT *LoopRep, RegiT RegNum);
290 void addLoopEndbranchInitReg(LoopT *LoopRep, RegiT RegNum);
291
292 bool hasBackEdge(BlockT *curBlock);
293 unsigned getLoopDepth (LoopT *LoopRep);
294 int countActiveBlock(
Craig Topper365ef0b2013-07-03 15:07:05 +0000295 typename SmallVectorImpl<BlockT *>::const_iterator IterStart,
296 typename SmallVectorImpl<BlockT *>::const_iterator IterEnd);
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000297 BlockT *findNearestCommonPostDom(std::set<BlockT *>&);
298 BlockT *findNearestCommonPostDom(BlockT *Block1, BlockT *Block2);
299
300private:
301 DomTreeT *domTree;
302 PostDomTreeT *postDomTree;
303 LoopInfoT *loopInfo;
304 PassT *passRep;
305 FuncT *funcRep;
306
307 BlockInfoMap blockInfoMap;
308 LoopLandInfoMap loopLandInfoMap;
309 SmallVector<BlockT *, DEFAULT_VEC_SLOTS> orderedBlks;
310 const AMDGPURegisterInfo *TRI;
311
312}; //template class CFGStructurizer
313
314template<class PassT> CFGStructurizer<PassT>::CFGStructurizer()
315 : domTree(NULL), postDomTree(NULL), loopInfo(NULL) {
316}
317
318template<class PassT> CFGStructurizer<PassT>::~CFGStructurizer() {
319 for (typename BlockInfoMap::iterator I = blockInfoMap.begin(),
320 E = blockInfoMap.end(); I != E; ++I) {
321 delete I->second;
322 }
323}
324
325template<class PassT>
326bool CFGStructurizer<PassT>::prepare(FuncT &func, PassT &pass,
327 const AMDGPURegisterInfo * tri) {
328 passRep = &pass;
329 funcRep = &func;
330 TRI = tri;
331
332 bool changed = false;
333
334 //FIXME: if not reducible flow graph, make it so ???
335
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000336 DEBUG(
337 dbgs() << "AMDGPUCFGStructurizer::prepare\n";
338 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000339
340 loopInfo = CFGTraits::getLoopInfo(pass);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000341 DEBUG(
342 dbgs() << "LoopInfo:\n";
343 PrintLoopinfo(*loopInfo, dbgs());
344 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000345
346 orderBlocks();
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000347 DEBUG(
348 for (typename SmallVectorImpl<BlockT *>::const_iterator
349 iterBlk = orderedBlks.begin(), iterBlkEnd = orderedBlks.end();
350 iterBlk != iterBlkEnd;
351 ++iterBlk) {
352 (*iterBlk)->dump();
353 }
354 dbgs() << "Ordered blocks:\n";
355 printOrderedBlocks(dbgs());
356 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000357
358 SmallVector<BlockT *, DEFAULT_VEC_SLOTS> retBlks;
359
360 for (typename LoopInfoT::iterator iter = loopInfo->begin(),
361 iterEnd = loopInfo->end();
362 iter != iterEnd; ++iter) {
363 LoopT* loopRep = (*iter);
364 BlockTSmallerVector exitingBlks;
365 loopRep->getExitingBlocks(exitingBlks);
366
367 if (exitingBlks.size() == 0) {
368 BlockT* dummyExitBlk = normalizeInfiniteLoopExit(loopRep);
369 if (dummyExitBlk != NULL)
370 retBlks.push_back(dummyExitBlk);
371 }
372 }
373
374 // Remove unconditional branch instr.
375 // Add dummy exit block iff there are multiple returns.
376
Craig Topper365ef0b2013-07-03 15:07:05 +0000377 for (typename SmallVectorImpl<BlockT *>::const_iterator
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000378 iterBlk = orderedBlks.begin(), iterEndBlk = orderedBlks.end();
379 iterBlk != iterEndBlk;
380 ++iterBlk) {
381 BlockT *curBlk = *iterBlk;
382 removeUnconditionalBranch(curBlk);
383 removeRedundantConditionalBranch(curBlk);
384 if (CFGTraits::isReturnBlock(curBlk)) {
385 retBlks.push_back(curBlk);
386 }
387 assert(curBlk->succ_size() <= 2);
388 } //for
389
390 if (retBlks.size() >= 2) {
391 addDummyExitBlock(retBlks);
392 changed = true;
393 }
394
395 return changed;
396} //CFGStructurizer::prepare
397
398template<class PassT>
399bool CFGStructurizer<PassT>::run(FuncT &func, PassT &pass,
400 const AMDGPURegisterInfo * tri) {
401 passRep = &pass;
402 funcRep = &func;
403 TRI = tri;
404
405 //Assume reducible CFG...
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000406 DEBUG(
407 dbgs() << "AMDGPUCFGStructurizer::run\n";
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000408 func.viewCFG();
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000409 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000410
411 domTree = CFGTraits::getDominatorTree(pass);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000412 DEBUG(
413 domTree->print(dbgs(), (const llvm::Module*)0);
414 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000415
416 postDomTree = CFGTraits::getPostDominatorTree(pass);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000417 DEBUG(
418 postDomTree->print(dbgs());
419 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000420
421 loopInfo = CFGTraits::getLoopInfo(pass);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000422 DEBUG(
423 dbgs() << "LoopInfo:\n";
424 PrintLoopinfo(*loopInfo, dbgs());
425 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000426
427 orderBlocks();
428#ifdef STRESSTEST
429 //Use the worse block ordering to test the algorithm.
430 ReverseVector(orderedBlks);
431#endif
432
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000433 DEBUG(
434 dbgs() << "Ordered blocks:\n";
435 printOrderedBlocks(dbgs());
436 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000437 int numIter = 0;
438 bool finish = false;
439 BlockT *curBlk;
440 bool makeProgress = false;
441 int numRemainedBlk = countActiveBlock(orderedBlks.begin(),
442 orderedBlks.end());
443
444 do {
445 ++numIter;
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000446 DEBUG(
447 dbgs() << "numIter = " << numIter
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000448 << ", numRemaintedBlk = " << numRemainedBlk << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000449 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000450
Craig Topper365ef0b2013-07-03 15:07:05 +0000451 typename SmallVectorImpl<BlockT *>::const_iterator
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000452 iterBlk = orderedBlks.begin();
Craig Topper365ef0b2013-07-03 15:07:05 +0000453 typename SmallVectorImpl<BlockT *>::const_iterator
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000454 iterBlkEnd = orderedBlks.end();
455
Craig Topper365ef0b2013-07-03 15:07:05 +0000456 typename SmallVectorImpl<BlockT *>::const_iterator
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000457 sccBeginIter = iterBlk;
458 BlockT *sccBeginBlk = NULL;
459 int sccNumBlk = 0; // The number of active blocks, init to a
460 // maximum possible number.
461 int sccNumIter; // Number of iteration in this SCC.
462
463 while (iterBlk != iterBlkEnd) {
464 curBlk = *iterBlk;
465
466 if (sccBeginBlk == NULL) {
467 sccBeginIter = iterBlk;
468 sccBeginBlk = curBlk;
469 sccNumIter = 0;
470 sccNumBlk = numRemainedBlk; // Init to maximum possible number.
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000471 DEBUG(
472 dbgs() << "start processing SCC" << getSCCNum(sccBeginBlk);
473 dbgs() << "\n";
474 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000475 }
476
477 if (!isRetiredBlock(curBlk)) {
478 patternMatch(curBlk);
479 }
480
481 ++iterBlk;
482
483 bool contNextScc = true;
484 if (iterBlk == iterBlkEnd
485 || getSCCNum(sccBeginBlk) != getSCCNum(*iterBlk)) {
486 // Just finish one scc.
487 ++sccNumIter;
488 int sccRemainedNumBlk = countActiveBlock(sccBeginIter, iterBlk);
489 if (sccRemainedNumBlk != 1 && sccRemainedNumBlk >= sccNumBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000490 DEBUG(
491 dbgs() << "Can't reduce SCC " << getSCCNum(curBlk)
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000492 << ", sccNumIter = " << sccNumIter;
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000493 dbgs() << "doesn't make any progress\n";
494 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000495 contNextScc = true;
496 } else if (sccRemainedNumBlk != 1 && sccRemainedNumBlk < sccNumBlk) {
497 sccNumBlk = sccRemainedNumBlk;
498 iterBlk = sccBeginIter;
499 contNextScc = false;
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000500 DEBUG(
501 dbgs() << "repeat processing SCC" << getSCCNum(curBlk)
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000502 << "sccNumIter = " << sccNumIter << "\n";
503 func.viewCFG();
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000504 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000505 } else {
506 // Finish the current scc.
507 contNextScc = true;
508 }
509 } else {
510 // Continue on next component in the current scc.
511 contNextScc = false;
512 }
513
514 if (contNextScc) {
515 sccBeginBlk = NULL;
516 }
517 } //while, "one iteration" over the function.
518
519 BlockT *entryBlk = FuncGTraits::nodes_begin(&func);
520 if (entryBlk->succ_size() == 0) {
521 finish = true;
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000522 DEBUG(
523 dbgs() << "Reduce to one block\n";
524 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000525 } else {
526 int newnumRemainedBlk
527 = countActiveBlock(orderedBlks.begin(), orderedBlks.end());
528 // consider cloned blocks ??
529 if (newnumRemainedBlk == 1 || newnumRemainedBlk < numRemainedBlk) {
530 makeProgress = true;
531 numRemainedBlk = newnumRemainedBlk;
532 } else {
533 makeProgress = false;
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000534 DEBUG(
535 dbgs() << "No progress\n";
536 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000537 }
538 }
539 } while (!finish && makeProgress);
540
541 // Misc wrap up to maintain the consistency of the Function representation.
542 CFGTraits::wrapup(FuncGTraits::nodes_begin(&func));
543
544 // Detach retired Block, release memory.
545 for (typename BlockInfoMap::iterator iterMap = blockInfoMap.begin(),
546 iterEndMap = blockInfoMap.end(); iterMap != iterEndMap; ++iterMap) {
547 if ((*iterMap).second && (*iterMap).second->isRetired) {
548 assert(((*iterMap).first)->getNumber() != -1);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000549 DEBUG(
550 dbgs() << "Erase BB" << ((*iterMap).first)->getNumber() << "\n";
551 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000552 (*iterMap).first->eraseFromParent(); //Remove from the parent Function.
553 }
554 delete (*iterMap).second;
555 }
556 blockInfoMap.clear();
557
558 // clear loopLandInfoMap
559 for (typename LoopLandInfoMap::iterator iterMap = loopLandInfoMap.begin(),
560 iterEndMap = loopLandInfoMap.end(); iterMap != iterEndMap; ++iterMap) {
561 delete (*iterMap).second;
562 }
563 loopLandInfoMap.clear();
564
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000565 DEBUG(
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000566 func.viewCFG();
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000567 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000568
569 if (!finish) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000570 llvm_unreachable("IRREDUCIBL_CF");
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000571 }
572
573 return true;
574} //CFGStructurizer::run
575
576/// Print the ordered Blocks.
577///
578template<class PassT>
579void CFGStructurizer<PassT>::printOrderedBlocks(llvm::raw_ostream &os) {
580 size_t i = 0;
Craig Topper365ef0b2013-07-03 15:07:05 +0000581 for (typename SmallVectorImpl<BlockT *>::const_iterator
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000582 iterBlk = orderedBlks.begin(), iterBlkEnd = orderedBlks.end();
583 iterBlk != iterBlkEnd;
584 ++iterBlk, ++i) {
585 os << "BB" << (*iterBlk)->getNumber();
586 os << "(" << getSCCNum(*iterBlk) << "," << (*iterBlk)->size() << ")";
587 if (i != 0 && i % 10 == 0) {
588 os << "\n";
589 } else {
590 os << " ";
591 }
592 }
593} //printOrderedBlocks
594
595/// Compute the reversed DFS post order of Blocks
596///
597template<class PassT> void CFGStructurizer<PassT>::orderBlocks() {
598 int sccNum = 0;
599 BlockT *bb;
600 for (scc_iterator<FuncT *> sccIter = scc_begin(funcRep),
601 sccEnd = scc_end(funcRep); sccIter != sccEnd; ++sccIter, ++sccNum) {
602 std::vector<BlockT *> &sccNext = *sccIter;
603 for (typename std::vector<BlockT *>::const_iterator
604 blockIter = sccNext.begin(), blockEnd = sccNext.end();
605 blockIter != blockEnd; ++blockIter) {
606 bb = *blockIter;
607 orderedBlks.push_back(bb);
608 recordSccnum(bb, sccNum);
609 }
610 }
611
612 //walk through all the block in func to check for unreachable
613 for (BlockIterator blockIter1 = FuncGTraits::nodes_begin(funcRep),
614 blockEnd1 = FuncGTraits::nodes_end(funcRep);
615 blockIter1 != blockEnd1; ++blockIter1) {
616 BlockT *bb = &(*blockIter1);
617 sccNum = getSCCNum(bb);
618 if (sccNum == INVALIDSCCNUM) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000619 dbgs() << "unreachable block BB" << bb->getNumber() << "\n";
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000620 }
621 }
622} //orderBlocks
623
624template<class PassT> int CFGStructurizer<PassT>::patternMatch(BlockT *curBlk) {
625 int numMatch = 0;
626 int curMatch;
627
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000628 DEBUG(
629 dbgs() << "Begin patternMatch BB" << curBlk->getNumber() << "\n";
630 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000631
632 while ((curMatch = patternMatchGroup(curBlk)) > 0) {
633 numMatch += curMatch;
634 }
635
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000636 DEBUG(
637 dbgs() << "End patternMatch BB" << curBlk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000638 << ", numMatch = " << numMatch << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000639 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000640
641 return numMatch;
642} //patternMatch
643
644template<class PassT>
645int CFGStructurizer<PassT>::patternMatchGroup(BlockT *curBlk) {
646 int numMatch = 0;
647 numMatch += serialPatternMatch(curBlk);
648 numMatch += ifPatternMatch(curBlk);
649 numMatch += loopendPatternMatch(curBlk);
650 numMatch += loopPatternMatch(curBlk);
651 return numMatch;
652}//patternMatchGroup
653
654template<class PassT>
655int CFGStructurizer<PassT>::serialPatternMatch(BlockT *curBlk) {
656 if (curBlk->succ_size() != 1) {
657 return 0;
658 }
659
660 BlockT *childBlk = *curBlk->succ_begin();
661 if (childBlk->pred_size() != 1 || isActiveLoophead(childBlk)) {
662 return 0;
663 }
664
665 mergeSerialBlock(curBlk, childBlk);
666 ++numSerialPatternMatch;
667 return 1;
668} //serialPatternMatch
669
670template<class PassT>
671int CFGStructurizer<PassT>::ifPatternMatch(BlockT *curBlk) {
672 //two edges
673 if (curBlk->succ_size() != 2) {
674 return 0;
675 }
676
677 if (hasBackEdge(curBlk)) {
678 return 0;
679 }
680
681 InstrT *branchInstr = CFGTraits::getNormalBlockBranchInstr(curBlk);
682 if (branchInstr == NULL) {
683 return 0;
684 }
685
686 assert(CFGTraits::isCondBranch(branchInstr));
687
688 BlockT *trueBlk = CFGTraits::getTrueBranch(branchInstr);
689 BlockT *falseBlk = CFGTraits::getFalseBranch(curBlk, branchInstr);
690 BlockT *landBlk;
691 int cloned = 0;
692
693 // TODO: Simplify
694 if (trueBlk->succ_size() == 1 && falseBlk->succ_size() == 1
695 && *trueBlk->succ_begin() == *falseBlk->succ_begin()) {
696 landBlk = *trueBlk->succ_begin();
697 } else if (trueBlk->succ_size() == 0 && falseBlk->succ_size() == 0) {
698 landBlk = NULL;
699 } else if (trueBlk->succ_size() == 1 && *trueBlk->succ_begin() == falseBlk) {
700 landBlk = falseBlk;
701 falseBlk = NULL;
702 } else if (falseBlk->succ_size() == 1
703 && *falseBlk->succ_begin() == trueBlk) {
704 landBlk = trueBlk;
705 trueBlk = NULL;
706 } else if (falseBlk->succ_size() == 1
707 && isSameloopDetachedContbreak(trueBlk, falseBlk)) {
708 landBlk = *falseBlk->succ_begin();
709 } else if (trueBlk->succ_size() == 1
710 && isSameloopDetachedContbreak(falseBlk, trueBlk)) {
711 landBlk = *trueBlk->succ_begin();
712 } else {
713 return handleJumpintoIf(curBlk, trueBlk, falseBlk);
714 }
715
716 // improveSimpleJumpinfoIf can handle the case where landBlk == NULL but the
717 // new BB created for landBlk==NULL may introduce new challenge to the
718 // reduction process.
719 if (landBlk != NULL &&
720 ((trueBlk && trueBlk->pred_size() > 1)
721 || (falseBlk && falseBlk->pred_size() > 1))) {
722 cloned += improveSimpleJumpintoIf(curBlk, trueBlk, falseBlk, &landBlk);
723 }
724
725 if (trueBlk && trueBlk->pred_size() > 1) {
726 trueBlk = cloneBlockForPredecessor(trueBlk, curBlk);
727 ++cloned;
728 }
729
730 if (falseBlk && falseBlk->pred_size() > 1) {
731 falseBlk = cloneBlockForPredecessor(falseBlk, curBlk);
732 ++cloned;
733 }
734
735 mergeIfthenelseBlock(branchInstr, curBlk, trueBlk, falseBlk, landBlk);
736
737 ++numIfPatternMatch;
738
739 numClonedBlock += cloned;
740
741 return 1 + cloned;
742} //ifPatternMatch
743
744template<class PassT>
745int CFGStructurizer<PassT>::switchPatternMatch(BlockT *curBlk) {
746 return 0;
747} //switchPatternMatch
748
749template<class PassT>
750int CFGStructurizer<PassT>::loopendPatternMatch(BlockT *curBlk) {
751 LoopT *loopRep = loopInfo->getLoopFor(curBlk);
752 typename std::vector<LoopT *> nestedLoops;
753 while (loopRep) {
754 nestedLoops.push_back(loopRep);
755 loopRep = loopRep->getParentLoop();
756 }
757
758 if (nestedLoops.size() == 0) {
759 return 0;
760 }
761
762 // Process nested loop outside->inside, so "continue" to a outside loop won't
763 // be mistaken as "break" of the current loop.
764 int num = 0;
765 for (typename std::vector<LoopT *>::reverse_iterator
766 iter = nestedLoops.rbegin(), iterEnd = nestedLoops.rend();
767 iter != iterEnd; ++iter) {
768 loopRep = *iter;
769
770 if (getLoopLandBlock(loopRep) != NULL) {
771 continue;
772 }
773
774 BlockT *loopHeader = loopRep->getHeader();
775
776 int numBreak = loopbreakPatternMatch(loopRep, loopHeader);
777
778 if (numBreak == -1) {
779 break;
780 }
781
782 int numCont = loopcontPatternMatch(loopRep, loopHeader);
783 num += numBreak + numCont;
784 }
785
786 return num;
787} //loopendPatternMatch
788
789template<class PassT>
790int CFGStructurizer<PassT>::loopPatternMatch(BlockT *curBlk) {
791 if (curBlk->succ_size() != 0) {
792 return 0;
793 }
794
795 int numLoop = 0;
796 LoopT *loopRep = loopInfo->getLoopFor(curBlk);
797 while (loopRep && loopRep->getHeader() == curBlk) {
798 LoopLandInfo *loopLand = getLoopLandInfo(loopRep);
799 if (loopLand) {
800 BlockT *landBlk = loopLand->landBlk;
801 assert(landBlk);
802 if (!isRetiredBlock(landBlk)) {
803 mergeLooplandBlock(curBlk, loopLand);
804 ++numLoop;
805 }
806 }
807 loopRep = loopRep->getParentLoop();
808 }
809
810 numLoopPatternMatch += numLoop;
811
812 return numLoop;
813} //loopPatternMatch
814
815template<class PassT>
816int CFGStructurizer<PassT>::loopbreakPatternMatch(LoopT *loopRep,
817 BlockT *loopHeader) {
818 BlockTSmallerVector exitingBlks;
819 loopRep->getExitingBlocks(exitingBlks);
820
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000821 DEBUG(
822 dbgs() << "Loop has " << exitingBlks.size() << " exiting blocks\n";
823 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000824
825 if (exitingBlks.size() == 0) {
826 setLoopLandBlock(loopRep);
827 return 0;
828 }
829
830 // Compute the corresponding exitBlks and exit block set.
831 BlockTSmallerVector exitBlks;
832 std::set<BlockT *> exitBlkSet;
833 for (typename BlockTSmallerVector::const_iterator iter = exitingBlks.begin(),
834 iterEnd = exitingBlks.end(); iter != iterEnd; ++iter) {
835 BlockT *exitingBlk = *iter;
836 BlockT *exitBlk = exitingBlock2ExitBlock(loopRep, exitingBlk);
837 exitBlks.push_back(exitBlk);
838 exitBlkSet.insert(exitBlk); //non-duplicate insert
839 }
840
841 assert(exitBlkSet.size() > 0);
842 assert(exitBlks.size() == exitingBlks.size());
843
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000844 DEBUG(
845 dbgs() << "Loop has " << exitBlkSet.size() << " exit blocks\n";
846 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000847
848 // Find exitLandBlk.
849 BlockT *exitLandBlk = NULL;
850 int numCloned = 0;
851 int numSerial = 0;
852
853 if (exitBlkSet.size() == 1) {
854 exitLandBlk = *exitBlkSet.begin();
855 } else {
856 exitLandBlk = findNearestCommonPostDom(exitBlkSet);
857
858 if (exitLandBlk == NULL) {
859 return -1;
860 }
861
862 bool allInPath = true;
863 bool allNotInPath = true;
864 for (typename std::set<BlockT*>::const_iterator
865 iter = exitBlkSet.begin(),
866 iterEnd = exitBlkSet.end();
867 iter != iterEnd; ++iter) {
868 BlockT *exitBlk = *iter;
869
870 PathToKind pathKind = singlePathTo(exitBlk, exitLandBlk, true);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000871 DEBUG(
872 dbgs() << "BB" << exitBlk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000873 << " to BB" << exitLandBlk->getNumber() << " PathToKind="
874 << pathKind << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000875 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000876
877 allInPath = allInPath && (pathKind == SinglePath_InPath);
878 allNotInPath = allNotInPath && (pathKind == SinglePath_NotInPath);
879
880 if (!allInPath && !allNotInPath) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000881 DEBUG(
882 dbgs() << "singlePath check fail\n";
883 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000884 return -1;
885 }
886 } // check all exit blocks
887
888 if (allNotInPath) {
889
890 // TODO: Simplify, maybe separate function?
891 LoopT *parentLoopRep = loopRep->getParentLoop();
892 BlockT *parentLoopHeader = NULL;
893 if (parentLoopRep)
894 parentLoopHeader = parentLoopRep->getHeader();
895
896 if (exitLandBlk == parentLoopHeader &&
897 (exitLandBlk = relocateLoopcontBlock(parentLoopRep,
898 loopRep,
899 exitBlkSet,
900 exitLandBlk)) != NULL) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000901 DEBUG(
902 dbgs() << "relocateLoopcontBlock success\n";
903 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000904 } else if ((exitLandBlk = addLoopEndbranchBlock(loopRep,
905 exitingBlks,
906 exitBlks)) != NULL) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000907 DEBUG(
908 dbgs() << "insertEndbranchBlock success\n";
909 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000910 } else {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +0000911 DEBUG(
912 dbgs() << "loop exit fail\n";
913 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +0000914 return -1;
915 }
916 }
917
918 // Handle side entry to exit path.
919 exitBlks.clear();
920 exitBlkSet.clear();
921 for (typename BlockTSmallerVector::iterator iterExiting =
922 exitingBlks.begin(),
923 iterExitingEnd = exitingBlks.end();
924 iterExiting != iterExitingEnd; ++iterExiting) {
925 BlockT *exitingBlk = *iterExiting;
926 BlockT *exitBlk = exitingBlock2ExitBlock(loopRep, exitingBlk);
927 BlockT *newExitBlk = exitBlk;
928
929 if (exitBlk != exitLandBlk && exitBlk->pred_size() > 1) {
930 newExitBlk = cloneBlockForPredecessor(exitBlk, exitingBlk);
931 ++numCloned;
932 }
933
934 numCloned += cloneOnSideEntryTo(exitingBlk, newExitBlk, exitLandBlk);
935
936 exitBlks.push_back(newExitBlk);
937 exitBlkSet.insert(newExitBlk);
938 }
939
940 for (typename BlockTSmallerVector::iterator iterExit = exitBlks.begin(),
941 iterExitEnd = exitBlks.end();
942 iterExit != iterExitEnd; ++iterExit) {
943 BlockT *exitBlk = *iterExit;
944 numSerial += serialPatternMatch(exitBlk);
945 }
946
947 for (typename BlockTSmallerVector::iterator iterExit = exitBlks.begin(),
948 iterExitEnd = exitBlks.end();
949 iterExit != iterExitEnd; ++iterExit) {
950 BlockT *exitBlk = *iterExit;
951 if (exitBlk->pred_size() > 1) {
952 if (exitBlk != exitLandBlk) {
953 return -1;
954 }
955 } else {
956 if (exitBlk != exitLandBlk &&
957 (exitBlk->succ_size() != 1 ||
958 *exitBlk->succ_begin() != exitLandBlk)) {
959 return -1;
960 }
961 }
962 }
963 } // else
964
965 exitLandBlk = recordLoopLandBlock(loopRep, exitLandBlk, exitBlks, exitBlkSet);
966
967 // Fold break into the breaking block. Leverage across level breaks.
968 assert(exitingBlks.size() == exitBlks.size());
969 for (typename BlockTSmallerVector::const_iterator iterExit = exitBlks.begin(),
970 iterExiting = exitingBlks.begin(), iterExitEnd = exitBlks.end();
971 iterExit != iterExitEnd; ++iterExit, ++iterExiting) {
972 BlockT *exitBlk = *iterExit;
973 BlockT *exitingBlk = *iterExiting;
974 assert(exitBlk->pred_size() == 1 || exitBlk == exitLandBlk);
975 LoopT *exitingLoop = loopInfo->getLoopFor(exitingBlk);
976 handleLoopbreak(exitingBlk, exitingLoop, exitBlk, loopRep, exitLandBlk);
977 }
978
979 int numBreak = static_cast<int>(exitingBlks.size());
980 numLoopbreakPatternMatch += numBreak;
981 numClonedBlock += numCloned;
982 return numBreak + numSerial + numCloned;
983} //loopbreakPatternMatch
984
985template<class PassT>
986int CFGStructurizer<PassT>::loopcontPatternMatch(LoopT *loopRep,
987 BlockT *loopHeader) {
988 int numCont = 0;
989 SmallVector<BlockT *, DEFAULT_VEC_SLOTS> contBlk;
990 for (typename InvBlockGTraits::ChildIteratorType iter =
991 InvBlockGTraits::child_begin(loopHeader),
992 iterEnd = InvBlockGTraits::child_end(loopHeader);
993 iter != iterEnd; ++iter) {
994 BlockT *curBlk = *iter;
995 if (loopRep->contains(curBlk)) {
996 handleLoopcontBlock(curBlk, loopInfo->getLoopFor(curBlk),
997 loopHeader, loopRep);
998 contBlk.push_back(curBlk);
999 ++numCont;
1000 }
1001 }
1002
Craig Topper365ef0b2013-07-03 15:07:05 +00001003 for (typename SmallVectorImpl<BlockT *>::iterator
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001004 iter = contBlk.begin(), iterEnd = contBlk.end();
1005 iter != iterEnd; ++iter) {
1006 (*iter)->removeSuccessor(loopHeader);
1007 }
1008
1009 numLoopcontPatternMatch += numCont;
1010
1011 return numCont;
1012} //loopcontPatternMatch
1013
1014
1015template<class PassT>
1016bool CFGStructurizer<PassT>::isSameloopDetachedContbreak(BlockT *src1Blk,
1017 BlockT *src2Blk) {
1018 // return true iff src1Blk->succ_size() == 0 && src1Blk and src2Blk are in the
1019 // same loop with LoopLandInfo without explicitly keeping track of
1020 // loopContBlks and loopBreakBlks, this is a method to get the information.
1021 //
1022 if (src1Blk->succ_size() == 0) {
1023 LoopT *loopRep = loopInfo->getLoopFor(src1Blk);
1024 if (loopRep != NULL && loopRep == loopInfo->getLoopFor(src2Blk)) {
1025 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
1026 if (theEntry != NULL) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001027 DEBUG(
1028 dbgs() << "isLoopContBreakBlock yes src1 = BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001029 << src1Blk->getNumber()
1030 << " src2 = BB" << src2Blk->getNumber() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001031 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001032 return true;
1033 }
1034 }
1035 }
1036 return false;
1037} //isSameloopDetachedContbreak
1038
1039template<class PassT>
1040int CFGStructurizer<PassT>::handleJumpintoIf(BlockT *headBlk,
1041 BlockT *trueBlk,
1042 BlockT *falseBlk) {
1043 int num = handleJumpintoIfImp(headBlk, trueBlk, falseBlk);
1044 if (num == 0) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001045 DEBUG(
1046 dbgs() << "handleJumpintoIf swap trueBlk and FalseBlk" << "\n";
1047 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001048 num = handleJumpintoIfImp(headBlk, falseBlk, trueBlk);
1049 }
1050 return num;
1051}
1052
1053template<class PassT>
1054int CFGStructurizer<PassT>::handleJumpintoIfImp(BlockT *headBlk,
1055 BlockT *trueBlk,
1056 BlockT *falseBlk) {
1057 int num = 0;
1058 BlockT *downBlk;
1059
1060 //trueBlk could be the common post dominator
1061 downBlk = trueBlk;
1062
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001063 DEBUG(
1064 dbgs() << "handleJumpintoIfImp head = BB" << headBlk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001065 << " true = BB" << trueBlk->getNumber()
1066 << ", numSucc=" << trueBlk->succ_size()
1067 << " false = BB" << falseBlk->getNumber() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001068 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001069
1070 while (downBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001071 DEBUG(
1072 dbgs() << "check down = BB" << downBlk->getNumber();
1073 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001074
1075 if (singlePathTo(falseBlk, downBlk) == SinglePath_InPath) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001076 DEBUG(
1077 dbgs() << " working\n";
1078 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001079
1080 num += cloneOnSideEntryTo(headBlk, trueBlk, downBlk);
1081 num += cloneOnSideEntryTo(headBlk, falseBlk, downBlk);
1082
1083 numClonedBlock += num;
1084 num += serialPatternMatch(*headBlk->succ_begin());
1085 num += serialPatternMatch(*(++headBlk->succ_begin()));
1086 num += ifPatternMatch(headBlk);
1087 assert(num > 0);
1088
1089 break;
1090 }
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001091 DEBUG(
1092 dbgs() << " not working\n";
1093 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001094 downBlk = (downBlk->succ_size() == 1) ? (*downBlk->succ_begin()) : NULL;
1095 } // walk down the postDomTree
1096
1097 return num;
1098} //handleJumpintoIf
1099
1100template<class PassT>
1101void CFGStructurizer<PassT>::showImproveSimpleJumpintoIf(BlockT *headBlk,
1102 BlockT *trueBlk,
1103 BlockT *falseBlk,
1104 BlockT *landBlk,
1105 bool detail) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001106 dbgs() << "head = BB" << headBlk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001107 << " size = " << headBlk->size();
1108 if (detail) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001109 dbgs() << "\n";
1110 headBlk->print(dbgs());
1111 dbgs() << "\n";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001112 }
1113
1114 if (trueBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001115 dbgs() << ", true = BB" << trueBlk->getNumber() << " size = "
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001116 << trueBlk->size() << " numPred = " << trueBlk->pred_size();
1117 if (detail) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001118 dbgs() << "\n";
1119 trueBlk->print(dbgs());
1120 dbgs() << "\n";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001121 }
1122 }
1123 if (falseBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001124 dbgs() << ", false = BB" << falseBlk->getNumber() << " size = "
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001125 << falseBlk->size() << " numPred = " << falseBlk->pred_size();
1126 if (detail) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001127 dbgs() << "\n";
1128 falseBlk->print(dbgs());
1129 dbgs() << "\n";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001130 }
1131 }
1132 if (landBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001133 dbgs() << ", land = BB" << landBlk->getNumber() << " size = "
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001134 << landBlk->size() << " numPred = " << landBlk->pred_size();
1135 if (detail) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001136 dbgs() << "\n";
1137 landBlk->print(dbgs());
1138 dbgs() << "\n";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001139 }
1140 }
1141
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001142 dbgs() << "\n";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001143} //showImproveSimpleJumpintoIf
1144
1145template<class PassT>
1146int CFGStructurizer<PassT>::improveSimpleJumpintoIf(BlockT *headBlk,
1147 BlockT *trueBlk,
1148 BlockT *falseBlk,
1149 BlockT **plandBlk) {
1150 bool migrateTrue = false;
1151 bool migrateFalse = false;
1152
1153 BlockT *landBlk = *plandBlk;
1154
1155 assert((trueBlk == NULL || trueBlk->succ_size() <= 1)
1156 && (falseBlk == NULL || falseBlk->succ_size() <= 1));
1157
1158 if (trueBlk == falseBlk) {
1159 return 0;
1160 }
1161
1162 migrateTrue = needMigrateBlock(trueBlk);
1163 migrateFalse = needMigrateBlock(falseBlk);
1164
1165 if (!migrateTrue && !migrateFalse) {
1166 return 0;
1167 }
1168
1169 // If we need to migrate either trueBlk and falseBlk, migrate the rest that
1170 // have more than one predecessors. without doing this, its predecessor
1171 // rather than headBlk will have undefined value in initReg.
1172 if (!migrateTrue && trueBlk && trueBlk->pred_size() > 1) {
1173 migrateTrue = true;
1174 }
1175 if (!migrateFalse && falseBlk && falseBlk->pred_size() > 1) {
1176 migrateFalse = true;
1177 }
1178
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001179 DEBUG(
1180 dbgs() << "before improveSimpleJumpintoIf: ";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001181 showImproveSimpleJumpintoIf(headBlk, trueBlk, falseBlk, landBlk, 0);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001182 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001183
1184 // org: headBlk => if () {trueBlk} else {falseBlk} => landBlk
1185 //
1186 // new: headBlk => if () {initReg = 1; org trueBlk branch} else
1187 // {initReg = 0; org falseBlk branch }
1188 // => landBlk => if (initReg) {org trueBlk} else {org falseBlk}
1189 // => org landBlk
1190 // if landBlk->pred_size() > 2, put the about if-else inside
1191 // if (initReg !=2) {...}
1192 //
1193 // add initReg = initVal to headBlk
1194
1195 const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
1196 unsigned initReg =
1197 funcRep->getRegInfo().createVirtualRegister(I32RC);
1198 if (!migrateTrue || !migrateFalse) {
1199 int initVal = migrateTrue ? 0 : 1;
1200 CFGTraits::insertAssignInstrBefore(headBlk, passRep, initReg, initVal);
1201 }
1202
1203 int numNewBlk = 0;
1204
1205 if (landBlk == NULL) {
1206 landBlk = funcRep->CreateMachineBasicBlock();
1207 funcRep->push_back(landBlk); //insert to function
1208
1209 if (trueBlk) {
1210 trueBlk->addSuccessor(landBlk);
1211 } else {
1212 headBlk->addSuccessor(landBlk);
1213 }
1214
1215 if (falseBlk) {
1216 falseBlk->addSuccessor(landBlk);
1217 } else {
1218 headBlk->addSuccessor(landBlk);
1219 }
1220
1221 numNewBlk ++;
1222 }
1223
1224 bool landBlkHasOtherPred = (landBlk->pred_size() > 2);
1225
1226 //insert AMDGPU::ENDIF to avoid special case "input landBlk == NULL"
1227 typename BlockT::iterator insertPos =
1228 CFGTraits::getInstrPos
1229 (landBlk, CFGTraits::insertInstrBefore(landBlk, AMDGPU::ENDIF, passRep));
1230
1231 if (landBlkHasOtherPred) {
1232 unsigned immReg =
1233 funcRep->getRegInfo().createVirtualRegister(I32RC);
1234 CFGTraits::insertAssignInstrBefore(insertPos, passRep, immReg, 2);
1235 unsigned cmpResReg =
1236 funcRep->getRegInfo().createVirtualRegister(I32RC);
1237
1238 CFGTraits::insertCompareInstrBefore(landBlk, insertPos, passRep, cmpResReg,
1239 initReg, immReg);
1240 CFGTraits::insertCondBranchBefore(landBlk, insertPos,
1241 AMDGPU::IF_PREDICATE_SET, passRep,
1242 cmpResReg, DebugLoc());
1243 }
1244
1245 CFGTraits::insertCondBranchBefore(landBlk, insertPos, AMDGPU::IF_PREDICATE_SET,
1246 passRep, initReg, DebugLoc());
1247
1248 if (migrateTrue) {
1249 migrateInstruction(trueBlk, landBlk, insertPos);
1250 // need to uncondionally insert the assignment to ensure a path from its
1251 // predecessor rather than headBlk has valid value in initReg if
1252 // (initVal != 1).
1253 CFGTraits::insertAssignInstrBefore(trueBlk, passRep, initReg, 1);
1254 }
1255 CFGTraits::insertInstrBefore(insertPos, AMDGPU::ELSE, passRep);
1256
1257 if (migrateFalse) {
1258 migrateInstruction(falseBlk, landBlk, insertPos);
1259 // need to uncondionally insert the assignment to ensure a path from its
1260 // predecessor rather than headBlk has valid value in initReg if
1261 // (initVal != 0)
1262 CFGTraits::insertAssignInstrBefore(falseBlk, passRep, initReg, 0);
1263 }
1264
1265 if (landBlkHasOtherPred) {
1266 // add endif
1267 CFGTraits::insertInstrBefore(insertPos, AMDGPU::ENDIF, passRep);
1268
1269 // put initReg = 2 to other predecessors of landBlk
1270 for (typename BlockT::pred_iterator predIter = landBlk->pred_begin(),
1271 predIterEnd = landBlk->pred_end(); predIter != predIterEnd;
1272 ++predIter) {
1273 BlockT *curBlk = *predIter;
1274 if (curBlk != trueBlk && curBlk != falseBlk) {
1275 CFGTraits::insertAssignInstrBefore(curBlk, passRep, initReg, 2);
1276 }
1277 } //for
1278 }
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001279 DEBUG(
1280 dbgs() << "result from improveSimpleJumpintoIf: ";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001281 showImproveSimpleJumpintoIf(headBlk, trueBlk, falseBlk, landBlk, 0);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001282 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001283
1284 // update landBlk
1285 *plandBlk = landBlk;
1286
1287 return numNewBlk;
1288} //improveSimpleJumpintoIf
1289
1290template<class PassT>
1291void CFGStructurizer<PassT>::handleLoopbreak(BlockT *exitingBlk,
1292 LoopT *exitingLoop,
1293 BlockT *exitBlk,
1294 LoopT *exitLoop,
1295 BlockT *landBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001296 DEBUG(
1297 dbgs() << "Trying to break loop-depth = " << getLoopDepth(exitLoop)
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001298 << " from loop-depth = " << getLoopDepth(exitingLoop) << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001299 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001300 const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
1301
1302 RegiT initReg = INVALIDREGNUM;
1303 if (exitingLoop != exitLoop) {
1304 initReg = static_cast<int>
1305 (funcRep->getRegInfo().createVirtualRegister(I32RC));
1306 assert(initReg != INVALIDREGNUM);
1307 addLoopBreakInitReg(exitLoop, initReg);
1308 while (exitingLoop != exitLoop && exitingLoop) {
1309 addLoopBreakOnReg(exitingLoop, initReg);
1310 exitingLoop = exitingLoop->getParentLoop();
1311 }
1312 assert(exitingLoop == exitLoop);
1313 }
1314
1315 mergeLoopbreakBlock(exitingBlk, exitBlk, landBlk, initReg);
1316
1317} //handleLoopbreak
1318
1319template<class PassT>
1320void CFGStructurizer<PassT>::handleLoopcontBlock(BlockT *contingBlk,
1321 LoopT *contingLoop,
1322 BlockT *contBlk,
1323 LoopT *contLoop) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001324 DEBUG(
1325 dbgs() << "loopcontPattern cont = BB" << contingBlk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001326 << " header = BB" << contBlk->getNumber() << "\n";
1327
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001328 dbgs() << "Trying to continue loop-depth = "
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001329 << getLoopDepth(contLoop)
1330 << " from loop-depth = " << getLoopDepth(contingLoop) << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001331 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001332
1333 RegiT initReg = INVALIDREGNUM;
1334 const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
1335 if (contingLoop != contLoop) {
1336 initReg = static_cast<int>
1337 (funcRep->getRegInfo().createVirtualRegister(I32RC));
1338 assert(initReg != INVALIDREGNUM);
1339 addLoopContInitReg(contLoop, initReg);
1340 while (contingLoop && contingLoop->getParentLoop() != contLoop) {
1341 addLoopBreakOnReg(contingLoop, initReg); //not addLoopContOnReg
1342 contingLoop = contingLoop->getParentLoop();
1343 }
1344 assert(contingLoop && contingLoop->getParentLoop() == contLoop);
1345 addLoopContOnReg(contingLoop, initReg);
1346 }
1347
1348 settleLoopcontBlock(contingBlk, contBlk, initReg);
1349} //handleLoopcontBlock
1350
1351template<class PassT>
1352void CFGStructurizer<PassT>::mergeSerialBlock(BlockT *dstBlk, BlockT *srcBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001353 DEBUG(
1354 dbgs() << "serialPattern BB" << dstBlk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001355 << " <= BB" << srcBlk->getNumber() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001356 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001357 dstBlk->splice(dstBlk->end(), srcBlk, srcBlk->begin(), srcBlk->end());
1358
1359 dstBlk->removeSuccessor(srcBlk);
1360 CFGTraits::cloneSuccessorList(dstBlk, srcBlk);
1361
1362 removeSuccessor(srcBlk);
1363 retireBlock(dstBlk, srcBlk);
1364} //mergeSerialBlock
1365
1366template<class PassT>
1367void CFGStructurizer<PassT>::mergeIfthenelseBlock(InstrT *branchInstr,
1368 BlockT *curBlk,
1369 BlockT *trueBlk,
1370 BlockT *falseBlk,
1371 BlockT *landBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001372 DEBUG(
1373 dbgs() << "ifPattern BB" << curBlk->getNumber();
1374 dbgs() << "{ ";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001375 if (trueBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001376 dbgs() << "BB" << trueBlk->getNumber();
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001377 }
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001378 dbgs() << " } else ";
1379 dbgs() << "{ ";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001380 if (falseBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001381 dbgs() << "BB" << falseBlk->getNumber();
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001382 }
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001383 dbgs() << " }\n ";
1384 dbgs() << "landBlock: ";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001385 if (landBlk == NULL) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001386 dbgs() << "NULL";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001387 } else {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001388 dbgs() << "BB" << landBlk->getNumber();
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001389 }
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001390 dbgs() << "\n";
1391 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001392
1393 int oldOpcode = branchInstr->getOpcode();
1394 DebugLoc branchDL = branchInstr->getDebugLoc();
1395
1396// transform to
1397// if cond
1398// trueBlk
1399// else
1400// falseBlk
1401// endif
1402// landBlk
1403
1404 typename BlockT::iterator branchInstrPos =
1405 CFGTraits::getInstrPos(curBlk, branchInstr);
1406 CFGTraits::insertCondBranchBefore(branchInstrPos,
1407 CFGTraits::getBranchNzeroOpcode(oldOpcode),
1408 passRep,
1409 branchDL);
1410
1411 if (trueBlk) {
1412 curBlk->splice(branchInstrPos, trueBlk, trueBlk->begin(), trueBlk->end());
1413 curBlk->removeSuccessor(trueBlk);
1414 if (landBlk && trueBlk->succ_size()!=0) {
1415 trueBlk->removeSuccessor(landBlk);
1416 }
1417 retireBlock(curBlk, trueBlk);
1418 }
1419 CFGTraits::insertInstrBefore(branchInstrPos, AMDGPU::ELSE, passRep);
1420
1421 if (falseBlk) {
1422 curBlk->splice(branchInstrPos, falseBlk, falseBlk->begin(),
1423 falseBlk->end());
1424 curBlk->removeSuccessor(falseBlk);
1425 if (landBlk && falseBlk->succ_size() != 0) {
1426 falseBlk->removeSuccessor(landBlk);
1427 }
1428 retireBlock(curBlk, falseBlk);
1429 }
1430 CFGTraits::insertInstrBefore(branchInstrPos, AMDGPU::ENDIF, passRep);
1431
1432 branchInstr->eraseFromParent();
1433
1434 if (landBlk && trueBlk && falseBlk) {
1435 curBlk->addSuccessor(landBlk);
1436 }
1437
1438} //mergeIfthenelseBlock
1439
1440template<class PassT>
1441void CFGStructurizer<PassT>::mergeLooplandBlock(BlockT *dstBlk,
1442 LoopLandInfo *loopLand) {
1443 BlockT *landBlk = loopLand->landBlk;
1444
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001445 DEBUG(
1446 dbgs() << "loopPattern header = BB" << dstBlk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001447 << " land = BB" << landBlk->getNumber() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001448 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001449
1450 // Loop contInitRegs are init at the beginning of the loop.
1451 for (typename std::set<RegiT>::const_iterator iter =
1452 loopLand->contInitRegs.begin(),
1453 iterEnd = loopLand->contInitRegs.end(); iter != iterEnd; ++iter) {
1454 CFGTraits::insertAssignInstrBefore(dstBlk, passRep, *iter, 0);
1455 }
1456
1457 /* we last inserterd the DebugLoc in the
1458 * BREAK_LOGICALZ_i32 or AMDGPU::BREAK_LOGICALNZ statement in the current dstBlk.
1459 * search for the DebugLoc in the that statement.
1460 * if not found, we have to insert the empty/default DebugLoc */
1461 InstrT *loopBreakInstr = CFGTraits::getLoopBreakInstr(dstBlk);
1462 DebugLoc DLBreak = (loopBreakInstr) ? loopBreakInstr->getDebugLoc() : DebugLoc();
1463
1464 CFGTraits::insertInstrBefore(dstBlk, AMDGPU::WHILELOOP, passRep, DLBreak);
1465 // Loop breakInitRegs are init before entering the loop.
1466 for (typename std::set<RegiT>::const_iterator iter =
1467 loopLand->breakInitRegs.begin(),
1468 iterEnd = loopLand->breakInitRegs.end(); iter != iterEnd; ++iter) {
1469 CFGTraits::insertAssignInstrBefore(dstBlk, passRep, *iter, 0);
1470 }
1471 // Loop endbranchInitRegs are init before entering the loop.
1472 for (typename std::set<RegiT>::const_iterator iter =
1473 loopLand->endbranchInitRegs.begin(),
1474 iterEnd = loopLand->endbranchInitRegs.end(); iter != iterEnd; ++iter) {
1475 CFGTraits::insertAssignInstrBefore(dstBlk, passRep, *iter, 0);
1476 }
1477
1478 /* we last inserterd the DebugLoc in the continue statement in the current dstBlk
1479 * search for the DebugLoc in the continue statement.
1480 * if not found, we have to insert the empty/default DebugLoc */
1481 InstrT *continueInstr = CFGTraits::getContinueInstr(dstBlk);
1482 DebugLoc DLContinue = (continueInstr) ? continueInstr->getDebugLoc() : DebugLoc();
1483
1484 CFGTraits::insertInstrEnd(dstBlk, AMDGPU::ENDLOOP, passRep, DLContinue);
1485 // Loop breakOnRegs are check after the ENDLOOP: break the loop outside this
1486 // loop.
1487 for (typename std::set<RegiT>::const_iterator iter =
1488 loopLand->breakOnRegs.begin(),
1489 iterEnd = loopLand->breakOnRegs.end(); iter != iterEnd; ++iter) {
1490 CFGTraits::insertCondBranchEnd(dstBlk, AMDGPU::PREDICATED_BREAK, passRep,
1491 *iter);
1492 }
1493
1494 // Loop contOnRegs are check after the ENDLOOP: cont the loop outside this
1495 // loop.
1496 for (std::set<RegiT>::const_iterator iter = loopLand->contOnRegs.begin(),
1497 iterEnd = loopLand->contOnRegs.end(); iter != iterEnd; ++iter) {
1498 CFGTraits::insertCondBranchEnd(dstBlk, AMDGPU::CONTINUE_LOGICALNZ_i32,
1499 passRep, *iter);
1500 }
1501
1502 dstBlk->splice(dstBlk->end(), landBlk, landBlk->begin(), landBlk->end());
1503
1504 for (typename BlockT::succ_iterator iter = landBlk->succ_begin(),
1505 iterEnd = landBlk->succ_end(); iter != iterEnd; ++iter) {
1506 dstBlk->addSuccessor(*iter); // *iter's predecessor is also taken care of.
1507 }
1508
1509 removeSuccessor(landBlk);
1510 retireBlock(dstBlk, landBlk);
1511} //mergeLooplandBlock
1512
1513template<class PassT>
1514void CFGStructurizer<PassT>::reversePredicateSetter(typename BlockT::iterator I) {
1515 while (I--) {
1516 if (I->getOpcode() == AMDGPU::PRED_X) {
1517 switch (static_cast<MachineInstr *>(I)->getOperand(2).getImm()) {
1518 case OPCODE_IS_ZERO_INT:
1519 static_cast<MachineInstr *>(I)->getOperand(2).setImm(OPCODE_IS_NOT_ZERO_INT);
1520 return;
1521 case OPCODE_IS_NOT_ZERO_INT:
1522 static_cast<MachineInstr *>(I)->getOperand(2).setImm(OPCODE_IS_ZERO_INT);
1523 return;
1524 case OPCODE_IS_ZERO:
1525 static_cast<MachineInstr *>(I)->getOperand(2).setImm(OPCODE_IS_NOT_ZERO);
1526 return;
1527 case OPCODE_IS_NOT_ZERO:
1528 static_cast<MachineInstr *>(I)->getOperand(2).setImm(OPCODE_IS_ZERO);
1529 return;
1530 default:
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001531 llvm_unreachable("PRED_X Opcode invalid!");
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001532 }
1533 }
1534 }
1535}
1536
1537template<class PassT>
1538void CFGStructurizer<PassT>::mergeLoopbreakBlock(BlockT *exitingBlk,
1539 BlockT *exitBlk,
1540 BlockT *exitLandBlk,
1541 RegiT setReg) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001542 DEBUG(
1543 dbgs() << "loopbreakPattern exiting = BB" << exitingBlk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001544 << " exit = BB" << exitBlk->getNumber()
1545 << " land = BB" << exitLandBlk->getNumber() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001546 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001547
1548 InstrT *branchInstr = CFGTraits::getLoopendBlockBranchInstr(exitingBlk);
1549 assert(branchInstr && CFGTraits::isCondBranch(branchInstr));
1550
1551 DebugLoc DL = branchInstr->getDebugLoc();
1552
1553 BlockT *trueBranch = CFGTraits::getTrueBranch(branchInstr);
1554
1555 // transform exitingBlk to
1556 // if ( ) {
1557 // exitBlk (if exitBlk != exitLandBlk)
1558 // setReg = 1
1559 // break
1560 // }endif
1561 // successor = {orgSuccessor(exitingBlk) - exitBlk}
1562
1563 typename BlockT::iterator branchInstrPos =
1564 CFGTraits::getInstrPos(exitingBlk, branchInstr);
1565
1566 if (exitBlk == exitLandBlk && setReg == INVALIDREGNUM) {
1567 //break_logical
1568
1569 if (trueBranch != exitBlk) {
1570 reversePredicateSetter(branchInstrPos);
1571 }
1572 CFGTraits::insertCondBranchBefore(branchInstrPos, AMDGPU::PREDICATED_BREAK, passRep, DL);
1573 } else {
1574 if (trueBranch != exitBlk) {
1575 reversePredicateSetter(branchInstr);
1576 }
1577 CFGTraits::insertCondBranchBefore(branchInstrPos, AMDGPU::PREDICATED_BREAK, passRep, DL);
1578 if (exitBlk != exitLandBlk) {
1579 //splice is insert-before ...
1580 exitingBlk->splice(branchInstrPos, exitBlk, exitBlk->begin(),
1581 exitBlk->end());
1582 }
1583 if (setReg != INVALIDREGNUM) {
1584 CFGTraits::insertAssignInstrBefore(branchInstrPos, passRep, setReg, 1);
1585 }
1586 CFGTraits::insertInstrBefore(branchInstrPos, AMDGPU::BREAK, passRep);
1587 } //if_logical
1588
1589 //now branchInst can be erase safely
1590 branchInstr->eraseFromParent();
1591
1592 //now take care of successors, retire blocks
1593 exitingBlk->removeSuccessor(exitBlk);
1594 if (exitBlk != exitLandBlk) {
1595 //splice is insert-before ...
1596 exitBlk->removeSuccessor(exitLandBlk);
1597 retireBlock(exitingBlk, exitBlk);
1598 }
1599
1600} //mergeLoopbreakBlock
1601
1602template<class PassT>
1603void CFGStructurizer<PassT>::settleLoopcontBlock(BlockT *contingBlk,
1604 BlockT *contBlk,
1605 RegiT setReg) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001606 DEBUG(
1607 dbgs() << "settleLoopcontBlock conting = BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001608 << contingBlk->getNumber()
1609 << ", cont = BB" << contBlk->getNumber() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001610 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001611
1612 InstrT *branchInstr = CFGTraits::getLoopendBlockBranchInstr(contingBlk);
1613 if (branchInstr) {
1614 assert(CFGTraits::isCondBranch(branchInstr));
1615 typename BlockT::iterator branchInstrPos =
1616 CFGTraits::getInstrPos(contingBlk, branchInstr);
1617 BlockT *trueBranch = CFGTraits::getTrueBranch(branchInstr);
1618 int oldOpcode = branchInstr->getOpcode();
1619 DebugLoc DL = branchInstr->getDebugLoc();
1620
1621 // transform contingBlk to
1622 // if () {
1623 // move instr after branchInstr
1624 // continue
1625 // or
1626 // setReg = 1
1627 // break
1628 // }endif
1629 // successor = {orgSuccessor(contingBlk) - loopHeader}
1630
1631 bool useContinueLogical =
1632 (setReg == INVALIDREGNUM && (&*contingBlk->rbegin()) == branchInstr);
1633
1634 if (useContinueLogical == false) {
1635 int branchOpcode =
1636 trueBranch == contBlk ? CFGTraits::getBranchNzeroOpcode(oldOpcode)
1637 : CFGTraits::getBranchZeroOpcode(oldOpcode);
1638
1639 CFGTraits::insertCondBranchBefore(branchInstrPos, branchOpcode, passRep, DL);
1640
1641 if (setReg != INVALIDREGNUM) {
1642 CFGTraits::insertAssignInstrBefore(branchInstrPos, passRep, setReg, 1);
1643 // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
1644 CFGTraits::insertInstrEnd(contingBlk, AMDGPU::BREAK, passRep, DL);
1645 } else {
1646 // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
1647 CFGTraits::insertInstrEnd(contingBlk, AMDGPU::CONTINUE, passRep, DL);
1648 }
1649
1650 CFGTraits::insertInstrEnd(contingBlk, AMDGPU::ENDIF, passRep, DL);
1651 } else {
1652 int branchOpcode =
1653 trueBranch == contBlk ? CFGTraits::getContinueNzeroOpcode(oldOpcode)
1654 : CFGTraits::getContinueZeroOpcode(oldOpcode);
1655
1656 CFGTraits::insertCondBranchBefore(branchInstrPos, branchOpcode, passRep, DL);
1657 }
1658
1659 branchInstr->eraseFromParent();
1660 } else {
1661 // if we've arrived here then we've already erased the branch instruction
1662 // travel back up the basic block to see the last reference of our debug location
1663 // we've just inserted that reference here so it should be representative
1664 if (setReg != INVALIDREGNUM) {
1665 CFGTraits::insertAssignInstrBefore(contingBlk, passRep, setReg, 1);
1666 // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
1667 CFGTraits::insertInstrEnd(contingBlk, AMDGPU::BREAK, passRep, CFGTraits::getLastDebugLocInBB(contingBlk));
1668 } else {
1669 // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
1670 CFGTraits::insertInstrEnd(contingBlk, AMDGPU::CONTINUE, passRep, CFGTraits::getLastDebugLocInBB(contingBlk));
1671 }
1672 } //else
1673
1674} //settleLoopcontBlock
1675
1676// BBs in exitBlkSet are determined as in break-path for loopRep,
1677// before we can put code for BBs as inside loop-body for loopRep
1678// check whether those BBs are determined as cont-BB for parentLoopRep
1679// earlier.
1680// If so, generate a new BB newBlk
1681// (1) set newBlk common successor of BBs in exitBlkSet
1682// (2) change the continue-instr in BBs in exitBlkSet to break-instr
1683// (3) generate continue-instr in newBlk
1684//
1685template<class PassT>
1686typename CFGStructurizer<PassT>::BlockT *
1687CFGStructurizer<PassT>::relocateLoopcontBlock(LoopT *parentLoopRep,
1688 LoopT *loopRep,
1689 std::set<BlockT *> &exitBlkSet,
1690 BlockT *exitLandBlk) {
1691 std::set<BlockT *> endBlkSet;
1692
1693
1694
1695 for (typename std::set<BlockT *>::const_iterator iter = exitBlkSet.begin(),
1696 iterEnd = exitBlkSet.end();
1697 iter != iterEnd; ++iter) {
1698 BlockT *exitBlk = *iter;
1699 BlockT *endBlk = singlePathEnd(exitBlk, exitLandBlk);
1700
1701 if (endBlk == NULL || CFGTraits::getContinueInstr(endBlk) == NULL)
1702 return NULL;
1703
1704 endBlkSet.insert(endBlk);
1705 }
1706
1707 BlockT *newBlk = funcRep->CreateMachineBasicBlock();
1708 funcRep->push_back(newBlk); //insert to function
1709 CFGTraits::insertInstrEnd(newBlk, AMDGPU::CONTINUE, passRep);
1710 SHOWNEWBLK(newBlk, "New continue block: ");
1711
1712 for (typename std::set<BlockT*>::const_iterator iter = endBlkSet.begin(),
1713 iterEnd = endBlkSet.end();
1714 iter != iterEnd; ++iter) {
1715 BlockT *endBlk = *iter;
1716 InstrT *contInstr = CFGTraits::getContinueInstr(endBlk);
1717 if (contInstr) {
1718 contInstr->eraseFromParent();
1719 }
1720 endBlk->addSuccessor(newBlk);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001721 DEBUG(
1722 dbgs() << "Add new continue Block to BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001723 << endBlk->getNumber() << " successors\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001724 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001725 }
1726
1727 return newBlk;
1728} //relocateLoopcontBlock
1729
1730
1731// LoopEndbranchBlock is a BB created by the CFGStructurizer to use as
1732// LoopLandBlock. This BB branch on the loop endBranchInit register to the
1733// pathes corresponding to the loop exiting branches.
1734
1735template<class PassT>
1736typename CFGStructurizer<PassT>::BlockT *
1737CFGStructurizer<PassT>::addLoopEndbranchBlock(LoopT *loopRep,
1738 BlockTSmallerVector &exitingBlks,
1739 BlockTSmallerVector &exitBlks) {
1740 const AMDGPUInstrInfo *tii =
1741 static_cast<const AMDGPUInstrInfo *>(passRep->getTargetInstrInfo());
1742 const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
1743
1744 RegiT endBranchReg = static_cast<int>
1745 (funcRep->getRegInfo().createVirtualRegister(I32RC));
1746 assert(endBranchReg >= 0);
1747
1748 // reg = 0 before entering the loop
1749 addLoopEndbranchInitReg(loopRep, endBranchReg);
1750
1751 uint32_t numBlks = static_cast<uint32_t>(exitingBlks.size());
1752 assert(numBlks >=2 && numBlks == exitBlks.size());
1753
1754 BlockT *preExitingBlk = exitingBlks[0];
1755 BlockT *preExitBlk = exitBlks[0];
1756 BlockT *preBranchBlk = funcRep->CreateMachineBasicBlock();
1757 funcRep->push_back(preBranchBlk); //insert to function
1758 SHOWNEWBLK(preBranchBlk, "New loopEndbranch block: ");
1759
1760 BlockT *newLandBlk = preBranchBlk;
1761
1762 CFGTraits::replaceInstrUseOfBlockWith(preExitingBlk, preExitBlk,
1763 newLandBlk);
1764 preExitingBlk->removeSuccessor(preExitBlk);
1765 preExitingBlk->addSuccessor(newLandBlk);
1766
1767 //it is redundant to add reg = 0 to exitingBlks[0]
1768
1769 // For 1..n th exiting path (the last iteration handles two pathes) create the
1770 // branch to the previous path and the current path.
1771 for (uint32_t i = 1; i < numBlks; ++i) {
1772 BlockT *curExitingBlk = exitingBlks[i];
1773 BlockT *curExitBlk = exitBlks[i];
1774 BlockT *curBranchBlk;
1775
1776 if (i == numBlks - 1) {
1777 curBranchBlk = curExitBlk;
1778 } else {
1779 curBranchBlk = funcRep->CreateMachineBasicBlock();
1780 funcRep->push_back(curBranchBlk); //insert to function
1781 SHOWNEWBLK(curBranchBlk, "New loopEndbranch block: ");
1782 }
1783
1784 // Add reg = i to exitingBlks[i].
1785 CFGTraits::insertAssignInstrBefore(curExitingBlk, passRep,
1786 endBranchReg, i);
1787
1788 // Remove the edge (exitingBlks[i] exitBlks[i]) add new edge
1789 // (exitingBlks[i], newLandBlk).
1790 CFGTraits::replaceInstrUseOfBlockWith(curExitingBlk, curExitBlk,
1791 newLandBlk);
1792 curExitingBlk->removeSuccessor(curExitBlk);
1793 curExitingBlk->addSuccessor(newLandBlk);
1794
1795 // add to preBranchBlk the branch instruction:
1796 // if (endBranchReg == preVal)
1797 // preExitBlk
1798 // else
1799 // curBranchBlk
1800 //
1801 // preValReg = i - 1
1802
1803 DebugLoc DL;
1804 RegiT preValReg = static_cast<int>
1805 (funcRep->getRegInfo().createVirtualRegister(I32RC));
1806
1807 preBranchBlk->insert(preBranchBlk->begin(),
1808 tii->getMovImmInstr(preBranchBlk->getParent(), preValReg,
1809 i - 1));
1810
1811 // condResReg = (endBranchReg == preValReg)
1812 RegiT condResReg = static_cast<int>
1813 (funcRep->getRegInfo().createVirtualRegister(I32RC));
1814 BuildMI(preBranchBlk, DL, tii->get(tii->getIEQOpcode()), condResReg)
1815 .addReg(endBranchReg).addReg(preValReg);
1816
1817 BuildMI(preBranchBlk, DL, tii->get(AMDGPU::BRANCH_COND_i32))
1818 .addMBB(preExitBlk).addReg(condResReg);
1819
1820 preBranchBlk->addSuccessor(preExitBlk);
1821 preBranchBlk->addSuccessor(curBranchBlk);
1822
1823 // Update preExitingBlk, preExitBlk, preBranchBlk.
1824 preExitingBlk = curExitingBlk;
1825 preExitBlk = curExitBlk;
1826 preBranchBlk = curBranchBlk;
1827
1828 } //end for 1 .. n blocks
1829
1830 return newLandBlk;
1831} //addLoopEndbranchBlock
1832
1833template<class PassT>
1834typename CFGStructurizer<PassT>::PathToKind
1835CFGStructurizer<PassT>::singlePathTo(BlockT *srcBlk, BlockT *dstBlk,
1836 bool allowSideEntry) {
1837 assert(dstBlk);
1838
1839 if (srcBlk == dstBlk) {
1840 return SinglePath_InPath;
1841 }
1842
1843 while (srcBlk && srcBlk->succ_size() == 1) {
1844 srcBlk = *srcBlk->succ_begin();
1845 if (srcBlk == dstBlk) {
1846 return SinglePath_InPath;
1847 }
1848
1849 if (!allowSideEntry && srcBlk->pred_size() > 1) {
1850 return Not_SinglePath;
1851 }
1852 }
1853
1854 if (srcBlk && srcBlk->succ_size()==0) {
1855 return SinglePath_NotInPath;
1856 }
1857
1858 return Not_SinglePath;
1859} //singlePathTo
1860
1861// If there is a single path from srcBlk to dstBlk, return the last block before
1862// dstBlk If there is a single path from srcBlk->end without dstBlk, return the
1863// last block in the path Otherwise, return NULL
1864template<class PassT>
1865typename CFGStructurizer<PassT>::BlockT *
1866CFGStructurizer<PassT>::singlePathEnd(BlockT *srcBlk, BlockT *dstBlk,
1867 bool allowSideEntry) {
1868 assert(dstBlk);
1869
1870 if (srcBlk == dstBlk) {
1871 return srcBlk;
1872 }
1873
1874 if (srcBlk->succ_size() == 0) {
1875 return srcBlk;
1876 }
1877
1878 while (srcBlk && srcBlk->succ_size() == 1) {
1879 BlockT *preBlk = srcBlk;
1880
1881 srcBlk = *srcBlk->succ_begin();
1882 if (srcBlk == NULL) {
1883 return preBlk;
1884 }
1885
1886 if (!allowSideEntry && srcBlk->pred_size() > 1) {
1887 return NULL;
1888 }
1889 }
1890
1891 if (srcBlk && srcBlk->succ_size()==0) {
1892 return srcBlk;
1893 }
1894
1895 return NULL;
1896
1897} //singlePathEnd
1898
1899template<class PassT>
1900int CFGStructurizer<PassT>::cloneOnSideEntryTo(BlockT *preBlk, BlockT *srcBlk,
1901 BlockT *dstBlk) {
1902 int cloned = 0;
1903 assert(preBlk->isSuccessor(srcBlk));
1904 while (srcBlk && srcBlk != dstBlk) {
1905 assert(srcBlk->succ_size() == 1);
1906 if (srcBlk->pred_size() > 1) {
1907 srcBlk = cloneBlockForPredecessor(srcBlk, preBlk);
1908 ++cloned;
1909 }
1910
1911 preBlk = srcBlk;
1912 srcBlk = *srcBlk->succ_begin();
1913 }
1914
1915 return cloned;
1916} //cloneOnSideEntryTo
1917
1918template<class PassT>
1919typename CFGStructurizer<PassT>::BlockT *
1920CFGStructurizer<PassT>::cloneBlockForPredecessor(BlockT *curBlk,
1921 BlockT *predBlk) {
1922 assert(predBlk->isSuccessor(curBlk) &&
1923 "succBlk is not a prececessor of curBlk");
1924
1925 BlockT *cloneBlk = CFGTraits::clone(curBlk); //clone instructions
1926 CFGTraits::replaceInstrUseOfBlockWith(predBlk, curBlk, cloneBlk);
1927 //srcBlk, oldBlk, newBlk
1928
1929 predBlk->removeSuccessor(curBlk);
1930 predBlk->addSuccessor(cloneBlk);
1931
1932 // add all successor to cloneBlk
1933 CFGTraits::cloneSuccessorList(cloneBlk, curBlk);
1934
1935 numClonedInstr += curBlk->size();
1936
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001937 DEBUG(
1938 dbgs() << "Cloned block: " << "BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001939 << curBlk->getNumber() << "size " << curBlk->size() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001940 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001941
1942 SHOWNEWBLK(cloneBlk, "result of Cloned block: ");
1943
1944 return cloneBlk;
1945} //cloneBlockForPredecessor
1946
1947template<class PassT>
1948typename CFGStructurizer<PassT>::BlockT *
1949CFGStructurizer<PassT>::exitingBlock2ExitBlock(LoopT *loopRep,
1950 BlockT *exitingBlk) {
1951 BlockT *exitBlk = NULL;
1952
1953 for (typename BlockT::succ_iterator iterSucc = exitingBlk->succ_begin(),
1954 iterSuccEnd = exitingBlk->succ_end();
1955 iterSucc != iterSuccEnd; ++iterSucc) {
1956 BlockT *curBlk = *iterSucc;
1957 if (!loopRep->contains(curBlk)) {
1958 assert(exitBlk == NULL);
1959 exitBlk = curBlk;
1960 }
1961 }
1962
1963 assert(exitBlk != NULL);
1964
1965 return exitBlk;
1966} //exitingBlock2ExitBlock
1967
1968template<class PassT>
1969void CFGStructurizer<PassT>::migrateInstruction(BlockT *srcBlk,
1970 BlockT *dstBlk,
1971 InstrIterator insertPos) {
1972 InstrIterator spliceEnd;
1973 //look for the input branchinstr, not the AMDGPU branchinstr
1974 InstrT *branchInstr = CFGTraits::getNormalBlockBranchInstr(srcBlk);
1975 if (branchInstr == NULL) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001976 DEBUG(
1977 dbgs() << "migrateInstruction don't see branch instr\n" ;
1978 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001979 spliceEnd = srcBlk->end();
1980 } else {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001981 DEBUG(
1982 dbgs() << "migrateInstruction see branch instr\n" ;
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001983 branchInstr->dump();
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001984 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001985 spliceEnd = CFGTraits::getInstrPos(srcBlk, branchInstr);
1986 }
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001987 DEBUG(
1988 dbgs() << "migrateInstruction before splice dstSize = " << dstBlk->size()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001989 << "srcSize = " << srcBlk->size() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001990 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001991
1992 //splice insert before insertPos
1993 dstBlk->splice(insertPos, srcBlk, srcBlk->begin(), spliceEnd);
1994
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001995 DEBUG(
1996 dbgs() << "migrateInstruction after splice dstSize = " << dstBlk->size()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001997 << "srcSize = " << srcBlk->size() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00001998 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00001999} //migrateInstruction
2000
2001// normalizeInfiniteLoopExit change
2002// B1:
2003// uncond_br LoopHeader
2004//
2005// to
2006// B1:
2007// cond_br 1 LoopHeader dummyExit
2008// and return the newly added dummy exit block
2009//
2010template<class PassT>
2011typename CFGStructurizer<PassT>::BlockT *
2012CFGStructurizer<PassT>::normalizeInfiniteLoopExit(LoopT* LoopRep) {
2013 BlockT *loopHeader;
2014 BlockT *loopLatch;
2015 loopHeader = LoopRep->getHeader();
2016 loopLatch = LoopRep->getLoopLatch();
2017 BlockT *dummyExitBlk = NULL;
2018 const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
2019 if (loopHeader!=NULL && loopLatch!=NULL) {
2020 InstrT *branchInstr = CFGTraits::getLoopendBlockBranchInstr(loopLatch);
2021 if (branchInstr!=NULL && CFGTraits::isUncondBranch(branchInstr)) {
2022 dummyExitBlk = funcRep->CreateMachineBasicBlock();
2023 funcRep->push_back(dummyExitBlk); //insert to function
2024 SHOWNEWBLK(dummyExitBlk, "DummyExitBlock to normalize infiniteLoop: ");
2025
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002026 DEBUG(dbgs() << "Old branch instr: " << *branchInstr << "\n";);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002027
2028 typename BlockT::iterator insertPos =
2029 CFGTraits::getInstrPos(loopLatch, branchInstr);
2030 unsigned immReg =
2031 funcRep->getRegInfo().createVirtualRegister(I32RC);
2032 CFGTraits::insertAssignInstrBefore(insertPos, passRep, immReg, 1);
2033 InstrT *newInstr =
2034 CFGTraits::insertInstrBefore(insertPos, AMDGPU::BRANCH_COND_i32, passRep);
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002035 MachineInstrBuilder MIB(*funcRep, newInstr);
2036 MIB.addMBB(loopHeader);
2037 MIB.addReg(immReg, false);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002038
2039 SHOWNEWINSTR(newInstr);
2040
2041 branchInstr->eraseFromParent();
2042 loopLatch->addSuccessor(dummyExitBlk);
2043 }
2044 }
2045
2046 return dummyExitBlk;
2047} //normalizeInfiniteLoopExit
2048
2049template<class PassT>
2050void CFGStructurizer<PassT>::removeUnconditionalBranch(BlockT *srcBlk) {
2051 InstrT *branchInstr;
2052
2053 // I saw two unconditional branch in one basic block in example
2054 // test_fc_do_while_or.c need to fix the upstream on this to remove the loop.
2055 while ((branchInstr = CFGTraits::getLoopendBlockBranchInstr(srcBlk))
2056 && CFGTraits::isUncondBranch(branchInstr)) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002057 DEBUG(
2058 dbgs() << "Removing unconditional branch instruction" ;
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002059 branchInstr->dump();
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002060 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002061 branchInstr->eraseFromParent();
2062 }
2063} //removeUnconditionalBranch
2064
2065template<class PassT>
2066void CFGStructurizer<PassT>::removeRedundantConditionalBranch(BlockT *srcBlk) {
2067 if (srcBlk->succ_size() == 2) {
2068 BlockT *blk1 = *srcBlk->succ_begin();
2069 BlockT *blk2 = *(++srcBlk->succ_begin());
2070
2071 if (blk1 == blk2) {
2072 InstrT *branchInstr = CFGTraits::getNormalBlockBranchInstr(srcBlk);
2073 assert(branchInstr && CFGTraits::isCondBranch(branchInstr));
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002074 DEBUG(
2075 dbgs() << "Removing unneeded conditional branch instruction" ;
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002076 branchInstr->dump();
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002077 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002078 branchInstr->eraseFromParent();
2079 SHOWNEWBLK(blk1, "Removing redundant successor");
2080 srcBlk->removeSuccessor(blk1);
2081 }
2082 }
2083} //removeRedundantConditionalBranch
2084
2085template<class PassT>
Craig Toppera0ec3f92013-07-14 04:42:23 +00002086void CFGStructurizer<PassT>::addDummyExitBlock(SmallVectorImpl<BlockT *>
2087 &retBlks) {
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002088 BlockT *dummyExitBlk = funcRep->CreateMachineBasicBlock();
2089 funcRep->push_back(dummyExitBlk); //insert to function
2090 CFGTraits::insertInstrEnd(dummyExitBlk, AMDGPU::RETURN, passRep);
2091
Craig Topper365ef0b2013-07-03 15:07:05 +00002092 for (typename SmallVectorImpl<BlockT *>::iterator iter =
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002093 retBlks.begin(),
2094 iterEnd = retBlks.end(); iter != iterEnd; ++iter) {
2095 BlockT *curBlk = *iter;
2096 InstrT *curInstr = CFGTraits::getReturnInstr(curBlk);
2097 if (curInstr) {
2098 curInstr->eraseFromParent();
2099 }
2100 curBlk->addSuccessor(dummyExitBlk);
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002101 DEBUG(
2102 dbgs() << "Add dummyExitBlock to BB" << curBlk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002103 << " successors\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002104 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002105 } //for
2106
2107 SHOWNEWBLK(dummyExitBlk, "DummyExitBlock: ");
2108} //addDummyExitBlock
2109
2110template<class PassT>
2111void CFGStructurizer<PassT>::removeSuccessor(BlockT *srcBlk) {
2112 while (srcBlk->succ_size()) {
2113 srcBlk->removeSuccessor(*srcBlk->succ_begin());
2114 }
2115}
2116
2117template<class PassT>
2118void CFGStructurizer<PassT>::recordSccnum(BlockT *srcBlk, int sccNum) {
2119 BlockInfo *&srcBlkInfo = blockInfoMap[srcBlk];
2120
2121 if (srcBlkInfo == NULL) {
2122 srcBlkInfo = new BlockInfo();
2123 }
2124
2125 srcBlkInfo->sccNum = sccNum;
2126}
2127
2128template<class PassT>
2129int CFGStructurizer<PassT>::getSCCNum(BlockT *srcBlk) {
2130 BlockInfo *srcBlkInfo = blockInfoMap[srcBlk];
2131 return srcBlkInfo ? srcBlkInfo->sccNum : INVALIDSCCNUM;
2132}
2133
2134template<class PassT>
2135void CFGStructurizer<PassT>::retireBlock(BlockT *dstBlk, BlockT *srcBlk) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002136 DEBUG(
2137 dbgs() << "Retiring BB" << srcBlk->getNumber() << "\n";
2138 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002139
2140 BlockInfo *&srcBlkInfo = blockInfoMap[srcBlk];
2141
2142 if (srcBlkInfo == NULL) {
2143 srcBlkInfo = new BlockInfo();
2144 }
2145
2146 srcBlkInfo->isRetired = true;
2147 assert(srcBlk->succ_size() == 0 && srcBlk->pred_size() == 0
2148 && "can't retire block yet");
2149}
2150
2151template<class PassT>
2152bool CFGStructurizer<PassT>::isRetiredBlock(BlockT *srcBlk) {
2153 BlockInfo *srcBlkInfo = blockInfoMap[srcBlk];
2154 return (srcBlkInfo && srcBlkInfo->isRetired);
2155}
2156
2157template<class PassT>
2158bool CFGStructurizer<PassT>::isActiveLoophead(BlockT *curBlk) {
2159 LoopT *loopRep = loopInfo->getLoopFor(curBlk);
2160 while (loopRep && loopRep->getHeader() == curBlk) {
2161 LoopLandInfo *loopLand = getLoopLandInfo(loopRep);
2162
2163 if(loopLand == NULL)
2164 return true;
2165
2166 BlockT *landBlk = loopLand->landBlk;
2167 assert(landBlk);
2168 if (!isRetiredBlock(landBlk)) {
2169 return true;
2170 }
2171
2172 loopRep = loopRep->getParentLoop();
2173 }
2174
2175 return false;
2176} //isActiveLoophead
2177
2178template<class PassT>
2179bool CFGStructurizer<PassT>::needMigrateBlock(BlockT *blk) {
2180 const unsigned blockSizeThreshold = 30;
2181 const unsigned cloneInstrThreshold = 100;
2182
2183 bool multiplePreds = blk && (blk->pred_size() > 1);
2184
2185 if(!multiplePreds)
2186 return false;
2187
2188 unsigned blkSize = blk->size();
2189 return ((blkSize > blockSizeThreshold)
2190 && (blkSize * (blk->pred_size() - 1) > cloneInstrThreshold));
2191} //needMigrateBlock
2192
2193template<class PassT>
2194typename CFGStructurizer<PassT>::BlockT *
2195CFGStructurizer<PassT>::recordLoopLandBlock(LoopT *loopRep, BlockT *landBlk,
2196 BlockTSmallerVector &exitBlks,
2197 std::set<BlockT *> &exitBlkSet) {
2198 SmallVector<BlockT *, DEFAULT_VEC_SLOTS> inpathBlks; //in exit path blocks
2199
2200 for (typename BlockT::pred_iterator predIter = landBlk->pred_begin(),
2201 predIterEnd = landBlk->pred_end();
2202 predIter != predIterEnd; ++predIter) {
2203 BlockT *curBlk = *predIter;
2204 if (loopRep->contains(curBlk) || exitBlkSet.count(curBlk)) {
2205 inpathBlks.push_back(curBlk);
2206 }
2207 } //for
2208
2209 //if landBlk has predecessors that are not in the given loop,
2210 //create a new block
2211 BlockT *newLandBlk = landBlk;
2212 if (inpathBlks.size() != landBlk->pred_size()) {
2213 newLandBlk = funcRep->CreateMachineBasicBlock();
2214 funcRep->push_back(newLandBlk); //insert to function
2215 newLandBlk->addSuccessor(landBlk);
Craig Topper365ef0b2013-07-03 15:07:05 +00002216 for (typename SmallVectorImpl<BlockT *>::iterator iter =
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002217 inpathBlks.begin(),
2218 iterEnd = inpathBlks.end(); iter != iterEnd; ++iter) {
2219 BlockT *curBlk = *iter;
2220 CFGTraits::replaceInstrUseOfBlockWith(curBlk, landBlk, newLandBlk);
2221 //srcBlk, oldBlk, newBlk
2222 curBlk->removeSuccessor(landBlk);
2223 curBlk->addSuccessor(newLandBlk);
2224 }
2225 for (size_t i = 0, tot = exitBlks.size(); i < tot; ++i) {
2226 if (exitBlks[i] == landBlk) {
2227 exitBlks[i] = newLandBlk;
2228 }
2229 }
2230 SHOWNEWBLK(newLandBlk, "NewLandingBlock: ");
2231 }
2232
2233 setLoopLandBlock(loopRep, newLandBlk);
2234
2235 return newLandBlk;
2236} // recordLoopbreakLand
2237
2238template<class PassT>
2239void CFGStructurizer<PassT>::setLoopLandBlock(LoopT *loopRep, BlockT *blk) {
2240 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
2241
2242 if (theEntry == NULL) {
2243 theEntry = new LoopLandInfo();
2244 }
2245 assert(theEntry->landBlk == NULL);
2246
2247 if (blk == NULL) {
2248 blk = funcRep->CreateMachineBasicBlock();
2249 funcRep->push_back(blk); //insert to function
2250 SHOWNEWBLK(blk, "DummyLandingBlock for loop without break: ");
2251 }
2252
2253 theEntry->landBlk = blk;
2254
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002255 DEBUG(
2256 dbgs() << "setLoopLandBlock loop-header = BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002257 << loopRep->getHeader()->getNumber()
2258 << " landing-block = BB" << blk->getNumber() << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002259 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002260} // setLoopLandBlock
2261
2262template<class PassT>
2263void CFGStructurizer<PassT>::addLoopBreakOnReg(LoopT *loopRep, RegiT regNum) {
2264 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
2265
2266 if (theEntry == NULL) {
2267 theEntry = new LoopLandInfo();
2268 }
2269
2270 theEntry->breakOnRegs.insert(regNum);
2271
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002272 DEBUG(
2273 dbgs() << "addLoopBreakOnReg loop-header = BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002274 << loopRep->getHeader()->getNumber()
2275 << " regNum = " << regNum << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002276 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002277} // addLoopBreakOnReg
2278
2279template<class PassT>
2280void CFGStructurizer<PassT>::addLoopContOnReg(LoopT *loopRep, RegiT regNum) {
2281 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
2282
2283 if (theEntry == NULL) {
2284 theEntry = new LoopLandInfo();
2285 }
2286 theEntry->contOnRegs.insert(regNum);
2287
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002288 DEBUG(
2289 dbgs() << "addLoopContOnReg loop-header = BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002290 << loopRep->getHeader()->getNumber()
2291 << " regNum = " << regNum << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002292 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002293} // addLoopContOnReg
2294
2295template<class PassT>
2296void CFGStructurizer<PassT>::addLoopBreakInitReg(LoopT *loopRep, RegiT regNum) {
2297 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
2298
2299 if (theEntry == NULL) {
2300 theEntry = new LoopLandInfo();
2301 }
2302 theEntry->breakInitRegs.insert(regNum);
2303
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002304 DEBUG(
2305 dbgs() << "addLoopBreakInitReg loop-header = BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002306 << loopRep->getHeader()->getNumber()
2307 << " regNum = " << regNum << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002308 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002309} // addLoopBreakInitReg
2310
2311template<class PassT>
2312void CFGStructurizer<PassT>::addLoopContInitReg(LoopT *loopRep, RegiT regNum) {
2313 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
2314
2315 if (theEntry == NULL) {
2316 theEntry = new LoopLandInfo();
2317 }
2318 theEntry->contInitRegs.insert(regNum);
2319
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002320 DEBUG(
2321 dbgs() << "addLoopContInitReg loop-header = BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002322 << loopRep->getHeader()->getNumber()
2323 << " regNum = " << regNum << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002324 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002325} // addLoopContInitReg
2326
2327template<class PassT>
2328void CFGStructurizer<PassT>::addLoopEndbranchInitReg(LoopT *loopRep,
2329 RegiT regNum) {
2330 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
2331
2332 if (theEntry == NULL) {
2333 theEntry = new LoopLandInfo();
2334 }
2335 theEntry->endbranchInitRegs.insert(regNum);
2336
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002337 DEBUG(
2338 dbgs() << "addLoopEndbranchInitReg loop-header = BB"
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002339 << loopRep->getHeader()->getNumber()
2340 << " regNum = " << regNum << "\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002341 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002342} // addLoopEndbranchInitReg
2343
2344template<class PassT>
2345typename CFGStructurizer<PassT>::LoopLandInfo *
2346CFGStructurizer<PassT>::getLoopLandInfo(LoopT *loopRep) {
2347 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
2348
2349 return theEntry;
2350} // getLoopLandInfo
2351
2352template<class PassT>
2353typename CFGStructurizer<PassT>::BlockT *
2354CFGStructurizer<PassT>::getLoopLandBlock(LoopT *loopRep) {
2355 LoopLandInfo *&theEntry = loopLandInfoMap[loopRep];
2356
2357 return theEntry ? theEntry->landBlk : NULL;
2358} // getLoopLandBlock
2359
2360
2361template<class PassT>
2362bool CFGStructurizer<PassT>::hasBackEdge(BlockT *curBlk) {
2363 LoopT *loopRep = loopInfo->getLoopFor(curBlk);
2364 if (loopRep == NULL)
2365 return false;
2366
2367 BlockT *loopHeader = loopRep->getHeader();
2368
2369 return curBlk->isSuccessor(loopHeader);
2370
2371} //hasBackEdge
2372
2373template<class PassT>
2374unsigned CFGStructurizer<PassT>::getLoopDepth(LoopT *loopRep) {
2375 return loopRep ? loopRep->getLoopDepth() : 0;
2376} //getLoopDepth
2377
2378template<class PassT>
2379int CFGStructurizer<PassT>::countActiveBlock
Craig Topper365ef0b2013-07-03 15:07:05 +00002380(typename SmallVectorImpl<BlockT *>::const_iterator iterStart,
2381 typename SmallVectorImpl<BlockT *>::const_iterator iterEnd) {
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002382 int count = 0;
2383 while (iterStart != iterEnd) {
2384 if (!isRetiredBlock(*iterStart)) {
2385 ++count;
2386 }
2387 ++iterStart;
2388 }
2389
2390 return count;
2391} //countActiveBlock
2392
2393// This is work around solution for findNearestCommonDominator not avaiable to
2394// post dom a proper fix should go to Dominators.h.
2395
2396template<class PassT>
2397typename CFGStructurizer<PassT>::BlockT*
2398CFGStructurizer<PassT>::findNearestCommonPostDom(BlockT *blk1, BlockT *blk2) {
2399
2400 if (postDomTree->dominates(blk1, blk2)) {
2401 return blk1;
2402 }
2403 if (postDomTree->dominates(blk2, blk1)) {
2404 return blk2;
2405 }
2406
2407 DomTreeNodeT *node1 = postDomTree->getNode(blk1);
2408 DomTreeNodeT *node2 = postDomTree->getNode(blk2);
2409
2410 // Handle newly cloned node.
2411 if (node1 == NULL && blk1->succ_size() == 1) {
2412 return findNearestCommonPostDom(*blk1->succ_begin(), blk2);
2413 }
2414 if (node2 == NULL && blk2->succ_size() == 1) {
2415 return findNearestCommonPostDom(blk1, *blk2->succ_begin());
2416 }
2417
2418 if (node1 == NULL || node2 == NULL) {
2419 return NULL;
2420 }
2421
2422 node1 = node1->getIDom();
2423 while (node1) {
2424 if (postDomTree->dominates(node1, node2)) {
2425 return node1->getBlock();
2426 }
2427 node1 = node1->getIDom();
2428 }
2429
2430 return NULL;
2431}
2432
2433template<class PassT>
2434typename CFGStructurizer<PassT>::BlockT *
2435CFGStructurizer<PassT>::findNearestCommonPostDom
2436(typename std::set<BlockT *> &blks) {
2437 BlockT *commonDom;
2438 typename std::set<BlockT *>::const_iterator iter = blks.begin();
2439 typename std::set<BlockT *>::const_iterator iterEnd = blks.end();
2440 for (commonDom = *iter; iter != iterEnd && commonDom != NULL; ++iter) {
2441 BlockT *curBlk = *iter;
2442 if (curBlk != commonDom) {
2443 commonDom = findNearestCommonPostDom(curBlk, commonDom);
2444 }
2445 }
2446
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002447 DEBUG(
2448 dbgs() << "Common post dominator for exit blocks is ";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002449 if (commonDom) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002450 dbgs() << "BB" << commonDom->getNumber() << "\n";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002451 } else {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002452 dbgs() << "NULL\n";
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002453 }
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002454 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002455
2456 return commonDom;
2457} //findNearestCommonPostDom
2458
Benjamin Kramer879b0712013-05-23 15:43:05 +00002459} // end anonymous namespace
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002460
2461//todo: move-end
2462
2463
2464//===----------------------------------------------------------------------===//
2465//
2466// CFGStructurizer for AMDGPU
2467//
2468//===----------------------------------------------------------------------===//
2469
2470
Benjamin Kramer879b0712013-05-23 15:43:05 +00002471namespace {
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002472class AMDGPUCFGStructurizer : public MachineFunctionPass {
2473public:
2474 typedef MachineInstr InstructionType;
2475 typedef MachineFunction FunctionType;
2476 typedef MachineBasicBlock BlockType;
2477 typedef MachineLoopInfo LoopinfoType;
2478 typedef MachineDominatorTree DominatortreeType;
2479 typedef MachinePostDominatorTree PostDominatortreeType;
2480 typedef MachineDomTreeNode DomTreeNodeType;
2481 typedef MachineLoop LoopType;
2482
2483protected:
2484 TargetMachine &TM;
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002485
2486public:
2487 AMDGPUCFGStructurizer(char &pid, TargetMachine &tm);
2488 const TargetInstrInfo *getTargetInstrInfo() const;
Bill Wendlingb5632b52013-06-07 20:28:55 +00002489 const AMDGPURegisterInfo *getTargetRegisterInfo() const;
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002490};
2491
Benjamin Kramer879b0712013-05-23 15:43:05 +00002492} // end anonymous namespace
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002493AMDGPUCFGStructurizer::AMDGPUCFGStructurizer(char &pid, TargetMachine &tm)
Bill Wendlingb5632b52013-06-07 20:28:55 +00002494 : MachineFunctionPass(pid), TM(tm) {
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002495}
2496
2497const TargetInstrInfo *AMDGPUCFGStructurizer::getTargetInstrInfo() const {
Bill Wendlingb5632b52013-06-07 20:28:55 +00002498 return TM.getInstrInfo();
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002499}
Bill Wendlingb5632b52013-06-07 20:28:55 +00002500
2501const AMDGPURegisterInfo *AMDGPUCFGStructurizer::getTargetRegisterInfo() const {
2502 return static_cast<const AMDGPURegisterInfo *>(TM.getRegisterInfo());
2503}
2504
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002505//===----------------------------------------------------------------------===//
2506//
2507// CFGPrepare
2508//
2509//===----------------------------------------------------------------------===//
2510
2511
Benjamin Kramer879b0712013-05-23 15:43:05 +00002512namespace {
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002513class AMDGPUCFGPrepare : public AMDGPUCFGStructurizer {
2514public:
2515 static char ID;
2516
2517public:
2518 AMDGPUCFGPrepare(TargetMachine &tm);
2519
2520 virtual const char *getPassName() const;
2521 virtual void getAnalysisUsage(AnalysisUsage &AU) const;
2522
2523 bool runOnMachineFunction(MachineFunction &F);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002524};
2525
2526char AMDGPUCFGPrepare::ID = 0;
Benjamin Kramer879b0712013-05-23 15:43:05 +00002527} // end anonymous namespace
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002528
2529AMDGPUCFGPrepare::AMDGPUCFGPrepare(TargetMachine &tm)
2530 : AMDGPUCFGStructurizer(ID, tm ) {
2531}
2532const char *AMDGPUCFGPrepare::getPassName() const {
2533 return "AMD IL Control Flow Graph Preparation Pass";
2534}
2535
2536void AMDGPUCFGPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
2537 AU.addPreserved<MachineFunctionAnalysis>();
2538 AU.addRequired<MachineFunctionAnalysis>();
2539 AU.addRequired<MachineDominatorTree>();
2540 AU.addRequired<MachinePostDominatorTree>();
2541 AU.addRequired<MachineLoopInfo>();
2542}
2543
2544//===----------------------------------------------------------------------===//
2545//
2546// CFGPerform
2547//
2548//===----------------------------------------------------------------------===//
2549
2550
Benjamin Kramer879b0712013-05-23 15:43:05 +00002551namespace {
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002552class AMDGPUCFGPerform : public AMDGPUCFGStructurizer {
2553public:
2554 static char ID;
2555
2556public:
2557 AMDGPUCFGPerform(TargetMachine &tm);
2558 virtual const char *getPassName() const;
2559 virtual void getAnalysisUsage(AnalysisUsage &AU) const;
2560 bool runOnMachineFunction(MachineFunction &F);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002561};
2562
2563char AMDGPUCFGPerform::ID = 0;
Benjamin Kramer879b0712013-05-23 15:43:05 +00002564} // end anonymous namespace
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002565
2566 AMDGPUCFGPerform::AMDGPUCFGPerform(TargetMachine &tm)
2567: AMDGPUCFGStructurizer(ID, tm) {
2568}
2569
2570const char *AMDGPUCFGPerform::getPassName() const {
2571 return "AMD IL Control Flow Graph structurizer Pass";
2572}
2573
2574void AMDGPUCFGPerform::getAnalysisUsage(AnalysisUsage &AU) const {
2575 AU.addPreserved<MachineFunctionAnalysis>();
2576 AU.addRequired<MachineFunctionAnalysis>();
2577 AU.addRequired<MachineDominatorTree>();
2578 AU.addRequired<MachinePostDominatorTree>();
2579 AU.addRequired<MachineLoopInfo>();
2580}
2581
2582//===----------------------------------------------------------------------===//
2583//
2584// CFGStructTraits<AMDGPUCFGStructurizer>
2585//
2586//===----------------------------------------------------------------------===//
2587
Benjamin Kramer879b0712013-05-23 15:43:05 +00002588namespace {
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002589// this class is tailor to the AMDGPU backend
2590template<>
2591struct CFGStructTraits<AMDGPUCFGStructurizer> {
2592 typedef int RegiT;
2593
2594 static int getBranchNzeroOpcode(int oldOpcode) {
2595 switch(oldOpcode) {
Vincent Lejeunefd49dac2013-03-11 18:15:06 +00002596 case AMDGPU::JUMP_COND:
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002597 case AMDGPU::JUMP: return AMDGPU::IF_PREDICATE_SET;
2598 case AMDGPU::BRANCH_COND_i32:
2599 case AMDGPU::BRANCH_COND_f32: return AMDGPU::IF_LOGICALNZ_f32;
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002600 default:
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002601 llvm_unreachable("internal error");
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002602 }
2603 return -1;
2604 }
2605
2606 static int getBranchZeroOpcode(int oldOpcode) {
2607 switch(oldOpcode) {
Vincent Lejeunefd49dac2013-03-11 18:15:06 +00002608 case AMDGPU::JUMP_COND:
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002609 case AMDGPU::JUMP: return AMDGPU::IF_PREDICATE_SET;
2610 case AMDGPU::BRANCH_COND_i32:
2611 case AMDGPU::BRANCH_COND_f32: return AMDGPU::IF_LOGICALZ_f32;
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002612 default:
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002613 llvm_unreachable("internal error");
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002614 }
2615 return -1;
2616 }
2617
2618 static int getContinueNzeroOpcode(int oldOpcode) {
2619 switch(oldOpcode) {
Vincent Lejeunefd49dac2013-03-11 18:15:06 +00002620 case AMDGPU::JUMP_COND:
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002621 case AMDGPU::JUMP: return AMDGPU::CONTINUE_LOGICALNZ_i32;
2622 default:
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002623 llvm_unreachable("internal error");
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002624 };
2625 return -1;
2626 }
2627
2628 static int getContinueZeroOpcode(int oldOpcode) {
2629 switch(oldOpcode) {
Vincent Lejeunefd49dac2013-03-11 18:15:06 +00002630 case AMDGPU::JUMP_COND:
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002631 case AMDGPU::JUMP: return AMDGPU::CONTINUE_LOGICALZ_i32;
2632 default:
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002633 llvm_unreachable("internal error");
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002634 }
2635 return -1;
2636 }
2637
2638 static MachineBasicBlock *getTrueBranch(MachineInstr *instr) {
2639 return instr->getOperand(0).getMBB();
2640 }
2641
2642 static void setTrueBranch(MachineInstr *instr, MachineBasicBlock *blk) {
2643 instr->getOperand(0).setMBB(blk);
2644 }
2645
2646 static MachineBasicBlock *
2647 getFalseBranch(MachineBasicBlock *blk, MachineInstr *instr) {
2648 assert(blk->succ_size() == 2);
2649 MachineBasicBlock *trueBranch = getTrueBranch(instr);
2650 MachineBasicBlock::succ_iterator iter = blk->succ_begin();
2651 MachineBasicBlock::succ_iterator iterNext = iter;
2652 ++iterNext;
2653
2654 return (*iter == trueBranch) ? *iterNext : *iter;
2655 }
2656
2657 static bool isCondBranch(MachineInstr *instr) {
2658 switch (instr->getOpcode()) {
Vincent Lejeunefd49dac2013-03-11 18:15:06 +00002659 case AMDGPU::JUMP_COND:
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002660 case AMDGPU::BRANCH_COND_i32:
2661 case AMDGPU::BRANCH_COND_f32:
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002662 break;
2663 default:
2664 return false;
2665 }
2666 return true;
2667 }
2668
2669 static bool isUncondBranch(MachineInstr *instr) {
2670 switch (instr->getOpcode()) {
2671 case AMDGPU::JUMP:
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002672 case AMDGPU::BRANCH:
2673 return true;
2674 default:
2675 return false;
2676 }
2677 return true;
2678 }
2679
2680 static DebugLoc getLastDebugLocInBB(MachineBasicBlock *blk) {
2681 //get DebugLoc from the first MachineBasicBlock instruction with debug info
2682 DebugLoc DL;
2683 for (MachineBasicBlock::iterator iter = blk->begin(); iter != blk->end(); ++iter) {
2684 MachineInstr *instr = &(*iter);
2685 if (instr->getDebugLoc().isUnknown() == false) {
2686 DL = instr->getDebugLoc();
2687 }
2688 }
2689 return DL;
2690 }
2691
2692 static MachineInstr *getNormalBlockBranchInstr(MachineBasicBlock *blk) {
2693 MachineBasicBlock::reverse_iterator iter = blk->rbegin();
2694 MachineInstr *instr = &*iter;
2695 if (instr && (isCondBranch(instr) || isUncondBranch(instr))) {
2696 return instr;
2697 }
2698 return NULL;
2699 }
2700
2701 // The correct naming for this is getPossibleLoopendBlockBranchInstr.
2702 //
2703 // BB with backward-edge could have move instructions after the branch
2704 // instruction. Such move instruction "belong to" the loop backward-edge.
2705 //
2706 static MachineInstr *getLoopendBlockBranchInstr(MachineBasicBlock *blk) {
2707 const AMDGPUInstrInfo * TII = static_cast<const AMDGPUInstrInfo *>(
2708 blk->getParent()->getTarget().getInstrInfo());
2709
2710 for (MachineBasicBlock::reverse_iterator iter = blk->rbegin(),
2711 iterEnd = blk->rend(); iter != iterEnd; ++iter) {
2712 // FIXME: Simplify
2713 MachineInstr *instr = &*iter;
2714 if (instr) {
2715 if (isCondBranch(instr) || isUncondBranch(instr)) {
2716 return instr;
2717 } else if (!TII->isMov(instr->getOpcode())) {
2718 break;
2719 }
2720 }
2721 }
2722 return NULL;
2723 }
2724
2725 static MachineInstr *getReturnInstr(MachineBasicBlock *blk) {
2726 MachineBasicBlock::reverse_iterator iter = blk->rbegin();
2727 if (iter != blk->rend()) {
2728 MachineInstr *instr = &(*iter);
2729 if (instr->getOpcode() == AMDGPU::RETURN) {
2730 return instr;
2731 }
2732 }
2733 return NULL;
2734 }
2735
2736 static MachineInstr *getContinueInstr(MachineBasicBlock *blk) {
2737 MachineBasicBlock::reverse_iterator iter = blk->rbegin();
2738 if (iter != blk->rend()) {
2739 MachineInstr *instr = &(*iter);
2740 if (instr->getOpcode() == AMDGPU::CONTINUE) {
2741 return instr;
2742 }
2743 }
2744 return NULL;
2745 }
2746
2747 static MachineInstr *getLoopBreakInstr(MachineBasicBlock *blk) {
2748 for (MachineBasicBlock::iterator iter = blk->begin(); (iter != blk->end()); ++iter) {
2749 MachineInstr *instr = &(*iter);
2750 if (instr->getOpcode() == AMDGPU::PREDICATED_BREAK) {
2751 return instr;
2752 }
2753 }
2754 return NULL;
2755 }
2756
2757 static bool isReturnBlock(MachineBasicBlock *blk) {
2758 MachineInstr *instr = getReturnInstr(blk);
2759 bool isReturn = (blk->succ_size() == 0);
2760 if (instr) {
2761 assert(isReturn);
2762 } else if (isReturn) {
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002763 DEBUG(
2764 dbgs() << "BB" << blk->getNumber()
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002765 <<" is return block without RETURN instr\n";
Vincent Lejeune9e8ba2b2013-07-19 21:44:56 +00002766 );
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002767 }
2768
2769 return isReturn;
2770 }
2771
2772 static MachineBasicBlock::iterator
2773 getInstrPos(MachineBasicBlock *blk, MachineInstr *instr) {
2774 assert(instr->getParent() == blk && "instruction doesn't belong to block");
2775 MachineBasicBlock::iterator iter = blk->begin();
2776 MachineBasicBlock::iterator iterEnd = blk->end();
2777 while (&(*iter) != instr && iter != iterEnd) {
2778 ++iter;
2779 }
2780
2781 assert(iter != iterEnd);
2782 return iter;
2783 }//getInstrPos
2784
2785 static MachineInstr *insertInstrBefore(MachineBasicBlock *blk, int newOpcode,
2786 AMDGPUCFGStructurizer *passRep) {
2787 return insertInstrBefore(blk,newOpcode,passRep,DebugLoc());
2788 } //insertInstrBefore
2789
2790 static MachineInstr *insertInstrBefore(MachineBasicBlock *blk, int newOpcode,
2791 AMDGPUCFGStructurizer *passRep, DebugLoc DL) {
2792 const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
2793 MachineInstr *newInstr =
2794 blk->getParent()->CreateMachineInstr(tii->get(newOpcode), DL);
2795
2796 MachineBasicBlock::iterator res;
2797 if (blk->begin() != blk->end()) {
2798 blk->insert(blk->begin(), newInstr);
2799 } else {
2800 blk->push_back(newInstr);
2801 }
2802
2803 SHOWNEWINSTR(newInstr);
2804
2805 return newInstr;
2806 } //insertInstrBefore
2807
2808 static void insertInstrEnd(MachineBasicBlock *blk, int newOpcode,
2809 AMDGPUCFGStructurizer *passRep) {
2810 insertInstrEnd(blk,newOpcode,passRep,DebugLoc());
2811 } //insertInstrEnd
2812
2813 static void insertInstrEnd(MachineBasicBlock *blk, int newOpcode,
2814 AMDGPUCFGStructurizer *passRep, DebugLoc DL) {
2815 const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
2816 MachineInstr *newInstr = blk->getParent()
2817 ->CreateMachineInstr(tii->get(newOpcode), DL);
2818
2819 blk->push_back(newInstr);
2820 //assume the instruction doesn't take any reg operand ...
2821
2822 SHOWNEWINSTR(newInstr);
2823 } //insertInstrEnd
2824
2825 static MachineInstr *insertInstrBefore(MachineBasicBlock::iterator instrPos,
2826 int newOpcode,
2827 AMDGPUCFGStructurizer *passRep) {
2828 MachineInstr *oldInstr = &(*instrPos);
2829 const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
2830 MachineBasicBlock *blk = oldInstr->getParent();
2831 MachineInstr *newInstr =
2832 blk->getParent()->CreateMachineInstr(tii->get(newOpcode),
2833 DebugLoc());
2834
2835 blk->insert(instrPos, newInstr);
2836 //assume the instruction doesn't take any reg operand ...
2837
2838 SHOWNEWINSTR(newInstr);
2839 return newInstr;
2840 } //insertInstrBefore
2841
2842 static void insertCondBranchBefore(MachineBasicBlock::iterator instrPos,
2843 int newOpcode,
2844 AMDGPUCFGStructurizer *passRep,
2845 DebugLoc DL) {
2846 MachineInstr *oldInstr = &(*instrPos);
2847 const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
2848 MachineBasicBlock *blk = oldInstr->getParent();
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002849 MachineFunction *MF = blk->getParent();
2850 MachineInstr *newInstr = MF->CreateMachineInstr(tii->get(newOpcode), DL);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002851
2852 blk->insert(instrPos, newInstr);
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002853 MachineInstrBuilder MIB(*MF, newInstr);
2854 MIB.addReg(oldInstr->getOperand(1).getReg(), false);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002855
2856 SHOWNEWINSTR(newInstr);
2857 //erase later oldInstr->eraseFromParent();
2858 } //insertCondBranchBefore
2859
2860 static void insertCondBranchBefore(MachineBasicBlock *blk,
2861 MachineBasicBlock::iterator insertPos,
2862 int newOpcode,
2863 AMDGPUCFGStructurizer *passRep,
2864 RegiT regNum,
2865 DebugLoc DL) {
2866 const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002867 MachineFunction *MF = blk->getParent();
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002868
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002869 MachineInstr *newInstr = MF->CreateMachineInstr(tii->get(newOpcode), DL);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002870
2871 //insert before
2872 blk->insert(insertPos, newInstr);
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002873 MachineInstrBuilder(*MF, newInstr).addReg(regNum, false);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002874
2875 SHOWNEWINSTR(newInstr);
2876 } //insertCondBranchBefore
2877
2878 static void insertCondBranchEnd(MachineBasicBlock *blk,
2879 int newOpcode,
2880 AMDGPUCFGStructurizer *passRep,
2881 RegiT regNum) {
2882 const TargetInstrInfo *tii = passRep->getTargetInstrInfo();
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002883 MachineFunction *MF = blk->getParent();
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002884 MachineInstr *newInstr =
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002885 MF->CreateMachineInstr(tii->get(newOpcode), DebugLoc());
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002886
2887 blk->push_back(newInstr);
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002888 MachineInstrBuilder(*MF, newInstr).addReg(regNum, false);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002889
2890 SHOWNEWINSTR(newInstr);
2891 } //insertCondBranchEnd
2892
2893
2894 static void insertAssignInstrBefore(MachineBasicBlock::iterator instrPos,
2895 AMDGPUCFGStructurizer *passRep,
2896 RegiT regNum, int regVal) {
2897 MachineInstr *oldInstr = &(*instrPos);
2898 const AMDGPUInstrInfo *tii =
2899 static_cast<const AMDGPUInstrInfo *>(passRep->getTargetInstrInfo());
2900 MachineBasicBlock *blk = oldInstr->getParent();
2901 MachineInstr *newInstr = tii->getMovImmInstr(blk->getParent(), regNum,
2902 regVal);
2903 blk->insert(instrPos, newInstr);
2904
2905 SHOWNEWINSTR(newInstr);
2906 } //insertAssignInstrBefore
2907
2908 static void insertAssignInstrBefore(MachineBasicBlock *blk,
2909 AMDGPUCFGStructurizer *passRep,
2910 RegiT regNum, int regVal) {
2911 const AMDGPUInstrInfo *tii =
2912 static_cast<const AMDGPUInstrInfo *>(passRep->getTargetInstrInfo());
2913
2914 MachineInstr *newInstr = tii->getMovImmInstr(blk->getParent(), regNum,
2915 regVal);
2916 if (blk->begin() != blk->end()) {
2917 blk->insert(blk->begin(), newInstr);
2918 } else {
2919 blk->push_back(newInstr);
2920 }
2921
2922 SHOWNEWINSTR(newInstr);
2923
2924 } //insertInstrBefore
2925
2926 static void insertCompareInstrBefore(MachineBasicBlock *blk,
2927 MachineBasicBlock::iterator instrPos,
2928 AMDGPUCFGStructurizer *passRep,
2929 RegiT dstReg, RegiT src1Reg,
2930 RegiT src2Reg) {
2931 const AMDGPUInstrInfo *tii =
2932 static_cast<const AMDGPUInstrInfo *>(passRep->getTargetInstrInfo());
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002933 MachineFunction *MF = blk->getParent();
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002934 MachineInstr *newInstr =
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002935 MF->CreateMachineInstr(tii->get(tii->getIEQOpcode()), DebugLoc());
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002936
NAKAMURA Takumi6b207d32012-12-20 00:22:11 +00002937 MachineInstrBuilder MIB(*MF, newInstr);
2938 MIB.addReg(dstReg, RegState::Define); //set target
2939 MIB.addReg(src1Reg); //set src value
2940 MIB.addReg(src2Reg); //set src value
Tom Stellardf98f2ce2012-12-11 21:25:42 +00002941
2942 blk->insert(instrPos, newInstr);
2943 SHOWNEWINSTR(newInstr);
2944
2945 } //insertCompareInstrBefore
2946
2947 static void cloneSuccessorList(MachineBasicBlock *dstBlk,
2948 MachineBasicBlock *srcBlk) {
2949 for (MachineBasicBlock::succ_iterator iter = srcBlk->succ_begin(),
2950 iterEnd = srcBlk->succ_end(); iter != iterEnd; ++iter) {
2951 dstBlk->addSuccessor(*iter); // *iter's predecessor is also taken care of
2952 }
2953 } //cloneSuccessorList
2954
2955 static MachineBasicBlock *clone(MachineBasicBlock *srcBlk) {
2956 MachineFunction *func = srcBlk->getParent();
2957 MachineBasicBlock *newBlk = func->CreateMachineBasicBlock();
2958 func->push_back(newBlk); //insert to function
2959 for (MachineBasicBlock::iterator iter = srcBlk->begin(),
2960 iterEnd = srcBlk->end();
2961 iter != iterEnd; ++iter) {
2962 MachineInstr *instr = func->CloneMachineInstr(iter);
2963 newBlk->push_back(instr);
2964 }
2965 return newBlk;
2966 }
2967
2968 //MachineBasicBlock::ReplaceUsesOfBlockWith doesn't serve the purpose because
2969 //the AMDGPU instruction is not recognized as terminator fix this and retire
2970 //this routine
2971 static void replaceInstrUseOfBlockWith(MachineBasicBlock *srcBlk,
2972 MachineBasicBlock *oldBlk,
2973 MachineBasicBlock *newBlk) {
2974 MachineInstr *branchInstr = getLoopendBlockBranchInstr(srcBlk);
2975 if (branchInstr && isCondBranch(branchInstr) &&
2976 getTrueBranch(branchInstr) == oldBlk) {
2977 setTrueBranch(branchInstr, newBlk);
2978 }
2979 }
2980
2981 static void wrapup(MachineBasicBlock *entryBlk) {
2982 assert((!entryBlk->getParent()->getJumpTableInfo()
2983 || entryBlk->getParent()->getJumpTableInfo()->isEmpty())
2984 && "found a jump table");
2985
2986 //collect continue right before endloop
2987 SmallVector<MachineInstr *, DEFAULT_VEC_SLOTS> contInstr;
2988 MachineBasicBlock::iterator pre = entryBlk->begin();
2989 MachineBasicBlock::iterator iterEnd = entryBlk->end();
2990 MachineBasicBlock::iterator iter = pre;
2991 while (iter != iterEnd) {
2992 if (pre->getOpcode() == AMDGPU::CONTINUE
2993 && iter->getOpcode() == AMDGPU::ENDLOOP) {
2994 contInstr.push_back(pre);
2995 }
2996 pre = iter;
2997 ++iter;
2998 } //end while
2999
3000 //delete continue right before endloop
3001 for (unsigned i = 0; i < contInstr.size(); ++i) {
3002 contInstr[i]->eraseFromParent();
3003 }
3004
3005 // TODO to fix up jump table so later phase won't be confused. if
3006 // (jumpTableInfo->isEmpty() == false) { need to clean the jump table, but
3007 // there isn't such an interface yet. alternatively, replace all the other
3008 // blocks in the jump table with the entryBlk //}
3009
3010 } //wrapup
3011
3012 static MachineDominatorTree *getDominatorTree(AMDGPUCFGStructurizer &pass) {
3013 return &pass.getAnalysis<MachineDominatorTree>();
3014 }
3015
3016 static MachinePostDominatorTree*
3017 getPostDominatorTree(AMDGPUCFGStructurizer &pass) {
3018 return &pass.getAnalysis<MachinePostDominatorTree>();
3019 }
3020
3021 static MachineLoopInfo *getLoopInfo(AMDGPUCFGStructurizer &pass) {
3022 return &pass.getAnalysis<MachineLoopInfo>();
3023 }
3024}; // template class CFGStructTraits
Benjamin Kramer879b0712013-05-23 15:43:05 +00003025} // end anonymous namespace
Tom Stellardf98f2ce2012-12-11 21:25:42 +00003026
3027// createAMDGPUCFGPreparationPass- Returns a pass
Benjamin Kramer879b0712013-05-23 15:43:05 +00003028FunctionPass *llvm::createAMDGPUCFGPreparationPass(TargetMachine &tm) {
3029 return new AMDGPUCFGPrepare(tm);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00003030}
3031
3032bool AMDGPUCFGPrepare::runOnMachineFunction(MachineFunction &func) {
Bill Wendlingb5632b52013-06-07 20:28:55 +00003033 return CFGStructurizer<AMDGPUCFGStructurizer>().prepare(func, *this,
3034 getTargetRegisterInfo());
Tom Stellardf98f2ce2012-12-11 21:25:42 +00003035}
3036
3037// createAMDGPUCFGStructurizerPass- Returns a pass
Benjamin Kramer879b0712013-05-23 15:43:05 +00003038FunctionPass *llvm::createAMDGPUCFGStructurizerPass(TargetMachine &tm) {
3039 return new AMDGPUCFGPerform(tm);
Tom Stellardf98f2ce2012-12-11 21:25:42 +00003040}
3041
3042bool AMDGPUCFGPerform::runOnMachineFunction(MachineFunction &func) {
Bill Wendlingb5632b52013-06-07 20:28:55 +00003043 return CFGStructurizer<AMDGPUCFGStructurizer>().run(func, *this,
3044 getTargetRegisterInfo());
Tom Stellardf98f2ce2012-12-11 21:25:42 +00003045}