blob: a5fa9f7cd87345ffef0c0fa0b5ca3663766ee48c [file] [log] [blame]
Tom Stellard75aadc22012-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 Stellarda6c6e1b2013-06-07 20:37:48 +000011#include "AMDGPU.h"
Eric Christopherd9134482014-08-04 21:25:23 +000012#include "AMDGPUSubtarget.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000013#include "R600InstrInfo.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000014#include "R600RegisterInfo.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000015#include "llvm/ADT/DepthFirstIterator.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000016#include "llvm/ADT/SCCIterator.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000017#include "llvm/ADT/SmallPtrSet.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000018#include "llvm/ADT/SmallVector.h"
19#include "llvm/ADT/Statistic.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000020#include "llvm/ADT/StringRef.h"
21#include "llvm/CodeGen/MachineBasicBlock.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000022#include "llvm/CodeGen/MachineDominators.h"
23#include "llvm/CodeGen/MachineFunction.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000024#include "llvm/CodeGen/MachineFunctionPass.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000025#include "llvm/CodeGen/MachineInstr.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000026#include "llvm/CodeGen/MachineInstrBuilder.h"
Eugene Zelenko06f90ef2017-01-21 01:34:25 +000027#include "llvm/CodeGen/MachineJumpTableInfo.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000028#include "llvm/CodeGen/MachineLoopInfo.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000029#include "llvm/CodeGen/MachineOperand.h"
Chandler Carruthbe810232013-01-02 10:22:59 +000030#include "llvm/CodeGen/MachinePostDominators.h"
Tom Stellard75aadc22012-12-11 21:25:42 +000031#include "llvm/CodeGen/MachineRegisterInfo.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000032#include "llvm/CodeGen/MachineValueType.h"
33#include "llvm/IR/DebugLoc.h"
34#include "llvm/IR/LLVMContext.h"
35#include "llvm/Pass.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000036#include "llvm/Support/Debug.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000037#include "llvm/Support/ErrorHandling.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000038#include "llvm/Support/raw_ostream.h"
Eugene Zelenko66203762017-01-21 00:53:49 +000039#include <cassert>
40#include <cstddef>
Benjamin Kramer799003b2015-03-23 19:32:43 +000041#include <deque>
Eugene Zelenko66203762017-01-21 00:53:49 +000042#include <iterator>
43#include <map>
44#include <utility>
45#include <vector>
Tom Stellard75aadc22012-12-11 21:25:42 +000046
47using namespace llvm;
48
Chandler Carruth84e68b22014-04-22 02:41:26 +000049#define DEBUG_TYPE "structcfg"
50
Tom Stellarda6c6e1b2013-06-07 20:37:48 +000051#define DEFAULT_VEC_SLOTS 8
52
Tom Stellard75aadc22012-12-11 21:25:42 +000053// TODO: move-begin.
54
55//===----------------------------------------------------------------------===//
56//
57// Statistics for CFGStructurizer.
58//
59//===----------------------------------------------------------------------===//
60
61STATISTIC(numSerialPatternMatch, "CFGStructurizer number of serial pattern "
62 "matched");
63STATISTIC(numIfPatternMatch, "CFGStructurizer number of if pattern "
64 "matched");
Tom Stellard75aadc22012-12-11 21:25:42 +000065STATISTIC(numClonedBlock, "CFGStructurizer cloned blocks");
66STATISTIC(numClonedInstr, "CFGStructurizer cloned instructions");
67
Tom Stellardf2ba9722013-12-11 17:51:47 +000068namespace llvm {
Eugene Zelenko66203762017-01-21 00:53:49 +000069
Tom Stellardf2ba9722013-12-11 17:51:47 +000070 void initializeAMDGPUCFGStructurizerPass(PassRegistry&);
Eugene Zelenko66203762017-01-21 00:53:49 +000071
72} // end namespace llvm
73
74namespace {
Tom Stellardf2ba9722013-12-11 17:51:47 +000075
Tom Stellard75aadc22012-12-11 21:25:42 +000076//===----------------------------------------------------------------------===//
77//
78// Miscellaneous utility for CFGStructurizer.
79//
80//===----------------------------------------------------------------------===//
Eugene Zelenko66203762017-01-21 00:53:49 +000081
Tom Stellard75aadc22012-12-11 21:25:42 +000082#define SHOWNEWINSTR(i) \
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +000083 DEBUG(dbgs() << "New instr: " << *i << "\n");
Tom Stellard75aadc22012-12-11 21:25:42 +000084
85#define SHOWNEWBLK(b, msg) \
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +000086DEBUG( \
87 dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
88 dbgs() << "\n"; \
89);
Tom Stellard75aadc22012-12-11 21:25:42 +000090
91#define SHOWBLK_DETAIL(b, msg) \
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +000092DEBUG( \
Tom Stellard75aadc22012-12-11 21:25:42 +000093 if (b) { \
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +000094 dbgs() << msg << "BB" << b->getNumber() << "size " << b->size(); \
95 b->print(dbgs()); \
96 dbgs() << "\n"; \
Tom Stellard75aadc22012-12-11 21:25:42 +000097 } \
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +000098);
Tom Stellard75aadc22012-12-11 21:25:42 +000099
100#define INVALIDSCCNUM -1
Tom Stellard75aadc22012-12-11 21:25:42 +0000101
Tom Stellard75aadc22012-12-11 21:25:42 +0000102//===----------------------------------------------------------------------===//
103//
104// supporting data structure for CFGStructurizer
105//
106//===----------------------------------------------------------------------===//
107
Tom Stellard75aadc22012-12-11 21:25:42 +0000108class BlockInformation {
109public:
Eugene Zelenko66203762017-01-21 00:53:49 +0000110 bool IsRetired = false;
111 int SccNum = INVALIDSCCNUM;
Tom Stellard75aadc22012-12-11 21:25:42 +0000112
Eugene Zelenko66203762017-01-21 00:53:49 +0000113 BlockInformation() = default;
114};
Tom Stellard75aadc22012-12-11 21:25:42 +0000115
116//===----------------------------------------------------------------------===//
117//
118// CFGStructurizer
119//
120//===----------------------------------------------------------------------===//
121
Vincent Lejeune960a6222013-07-19 21:45:06 +0000122class AMDGPUCFGStructurizer : public MachineFunctionPass {
Tom Stellard75aadc22012-12-11 21:25:42 +0000123public:
Vincent Lejeune960a6222013-07-19 21:45:06 +0000124 typedef SmallVector<MachineBasicBlock *, 32> MBBVector;
125 typedef std::map<MachineBasicBlock *, BlockInformation *> MBBInfoMap;
126 typedef std::map<MachineLoop *, MachineBasicBlock *> LoopLandInfoMap;
127
128 enum PathToKind {
Tom Stellard75aadc22012-12-11 21:25:42 +0000129 Not_SinglePath = 0,
130 SinglePath_InPath = 1,
131 SinglePath_NotInPath = 2
Vincent Lejeune960a6222013-07-19 21:45:06 +0000132 };
Tom Stellard75aadc22012-12-11 21:25:42 +0000133
Vincent Lejeune960a6222013-07-19 21:45:06 +0000134 static char ID;
Tom Stellard75aadc22012-12-11 21:25:42 +0000135
Eugene Zelenko66203762017-01-21 00:53:49 +0000136 AMDGPUCFGStructurizer() : MachineFunctionPass(ID) {
Tom Stellardf2ba9722013-12-11 17:51:47 +0000137 initializeAMDGPUCFGStructurizerPass(*PassRegistry::getPassRegistry());
138 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000139
Mehdi Amini117296c2016-10-01 02:56:57 +0000140 StringRef getPassName() const override {
Tom Stellardf2ba9722013-12-11 17:51:47 +0000141 return "AMDGPU Control Flow Graph structurizer Pass";
Vincent Lejeune960a6222013-07-19 21:45:06 +0000142 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000143
Craig Topper5656db42014-04-29 07:57:24 +0000144 void getAnalysisUsage(AnalysisUsage &AU) const override {
Vincent Lejeune960a6222013-07-19 21:45:06 +0000145 AU.addRequired<MachineDominatorTree>();
146 AU.addRequired<MachinePostDominatorTree>();
147 AU.addRequired<MachineLoopInfo>();
Matthias Braun733fe362016-08-24 01:52:46 +0000148 MachineFunctionPass::getAnalysisUsage(AU);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000149 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000150
151 /// Perform the CFG structurization
Vincent Lejeune960a6222013-07-19 21:45:06 +0000152 bool run();
Tom Stellard75aadc22012-12-11 21:25:42 +0000153
154 /// Perform the CFG preparation
Vincent Lejeune960a6222013-07-19 21:45:06 +0000155 /// This step will remove every unconditionnal/dead jump instructions and make
156 /// sure all loops have an exit block
157 bool prepare();
Tom Stellard75aadc22012-12-11 21:25:42 +0000158
Craig Topper5656db42014-04-29 07:57:24 +0000159 bool runOnMachineFunction(MachineFunction &MF) override {
Matt Arsenault43e92fe2016-06-24 06:30:11 +0000160 TII = MF.getSubtarget<R600Subtarget>().getInstrInfo();
Tom Stellardf2ba9722013-12-11 17:51:47 +0000161 TRI = &TII->getRegisterInfo();
Vincent Lejeune960a6222013-07-19 21:45:06 +0000162 DEBUG(MF.dump(););
163 OrderedBlks.clear();
Jan Vesely7a9cca92015-03-13 17:32:46 +0000164 Visited.clear();
Vincent Lejeune960a6222013-07-19 21:45:06 +0000165 FuncRep = &MF;
166 MLI = &getAnalysis<MachineLoopInfo>();
167 DEBUG(dbgs() << "LoopInfo:\n"; PrintLoopinfo(*MLI););
168 MDT = &getAnalysis<MachineDominatorTree>();
Eugene Zelenko66203762017-01-21 00:53:49 +0000169 DEBUG(MDT->print(dbgs(), (const Module*)nullptr););
Vincent Lejeune960a6222013-07-19 21:45:06 +0000170 PDT = &getAnalysis<MachinePostDominatorTree>();
171 DEBUG(PDT->print(dbgs()););
172 prepare();
173 run();
174 DEBUG(MF.dump(););
175 return true;
176 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000177
Vincent Lejeune960a6222013-07-19 21:45:06 +0000178protected:
Vincent Lejeune960a6222013-07-19 21:45:06 +0000179 MachineDominatorTree *MDT;
180 MachinePostDominatorTree *PDT;
181 MachineLoopInfo *MLI;
Eugene Zelenko66203762017-01-21 00:53:49 +0000182 const R600InstrInfo *TII = nullptr;
183 const R600RegisterInfo *TRI = nullptr;
Tom Stellard75aadc22012-12-11 21:25:42 +0000184
Vincent Lejeune960a6222013-07-19 21:45:06 +0000185 // PRINT FUNCTIONS
186 /// Print the ordered Blocks.
187 void printOrderedBlocks() const {
188 size_t i = 0;
189 for (MBBVector::const_iterator iterBlk = OrderedBlks.begin(),
190 iterBlkEnd = OrderedBlks.end(); iterBlk != iterBlkEnd; ++iterBlk, ++i) {
191 dbgs() << "BB" << (*iterBlk)->getNumber();
192 dbgs() << "(" << getSCCNum(*iterBlk) << "," << (*iterBlk)->size() << ")";
193 if (i != 0 && i % 10 == 0) {
194 dbgs() << "\n";
195 } else {
196 dbgs() << " ";
197 }
198 }
199 }
Eugene Zelenko66203762017-01-21 00:53:49 +0000200
Vincent Lejeune960a6222013-07-19 21:45:06 +0000201 static void PrintLoopinfo(const MachineLoopInfo &LoopInfo) {
202 for (MachineLoop::iterator iter = LoopInfo.begin(),
203 iterEnd = LoopInfo.end(); iter != iterEnd; ++iter) {
204 (*iter)->print(dbgs(), 0);
205 }
206 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000207
Vincent Lejeune960a6222013-07-19 21:45:06 +0000208 // UTILITY FUNCTIONS
209 int getSCCNum(MachineBasicBlock *MBB) const;
210 MachineBasicBlock *getLoopLandInfo(MachineLoop *LoopRep) const;
211 bool hasBackEdge(MachineBasicBlock *MBB) const;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000212 bool isRetiredBlock(MachineBasicBlock *MBB) const;
213 bool isActiveLoophead(MachineBasicBlock *MBB) const;
214 PathToKind singlePathTo(MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
215 bool AllowSideEntry = true) const;
216 int countActiveBlock(MBBVector::const_iterator It,
217 MBBVector::const_iterator E) const;
218 bool needMigrateBlock(MachineBasicBlock *MBB) const;
219
220 // Utility Functions
Hans Wennborg0dd9ed12016-08-13 01:12:49 +0000221 void reversePredicateSetter(MachineBasicBlock::iterator I,
222 MachineBasicBlock &MBB);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000223 /// Compute the reversed DFS post order of Blocks
224 void orderBlocks(MachineFunction *MF);
225
Alp Tokercb402912014-01-24 17:20:08 +0000226 // Function originally from CFGStructTraits
Vincent Lejeune960a6222013-07-19 21:45:06 +0000227 void insertInstrEnd(MachineBasicBlock *MBB, int NewOpcode,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000228 const DebugLoc &DL = DebugLoc());
Vincent Lejeune960a6222013-07-19 21:45:06 +0000229 MachineInstr *insertInstrBefore(MachineBasicBlock *MBB, int NewOpcode,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000230 const DebugLoc &DL = DebugLoc());
Vincent Lejeune960a6222013-07-19 21:45:06 +0000231 MachineInstr *insertInstrBefore(MachineBasicBlock::iterator I, int NewOpcode);
232 void insertCondBranchBefore(MachineBasicBlock::iterator I, int NewOpcode,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000233 const DebugLoc &DL);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000234 void insertCondBranchBefore(MachineBasicBlock *MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000235 MachineBasicBlock::iterator I, int NewOpcode,
236 int RegNum, const DebugLoc &DL);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000237 static int getBranchNzeroOpcode(int OldOpcode);
238 static int getBranchZeroOpcode(int OldOpcode);
239 static int getContinueNzeroOpcode(int OldOpcode);
240 static int getContinueZeroOpcode(int OldOpcode);
241 static MachineBasicBlock *getTrueBranch(MachineInstr *MI);
242 static void setTrueBranch(MachineInstr *MI, MachineBasicBlock *MBB);
243 static MachineBasicBlock *getFalseBranch(MachineBasicBlock *MBB,
244 MachineInstr *MI);
245 static bool isCondBranch(MachineInstr *MI);
246 static bool isUncondBranch(MachineInstr *MI);
247 static DebugLoc getLastDebugLocInBB(MachineBasicBlock *MBB);
248 static MachineInstr *getNormalBlockBranchInstr(MachineBasicBlock *MBB);
249 /// The correct naming for this is getPossibleLoopendBlockBranchInstr.
250 ///
251 /// BB with backward-edge could have move instructions after the branch
252 /// instruction. Such move instruction "belong to" the loop backward-edge.
253 MachineInstr *getLoopendBlockBranchInstr(MachineBasicBlock *MBB);
254 static MachineInstr *getReturnInstr(MachineBasicBlock *MBB);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000255 static bool isReturnBlock(MachineBasicBlock *MBB);
256 static void cloneSuccessorList(MachineBasicBlock *DstMBB,
257 MachineBasicBlock *SrcMBB) ;
258 static MachineBasicBlock *clone(MachineBasicBlock *MBB);
259 /// MachineBasicBlock::ReplaceUsesOfBlockWith doesn't serve the purpose
260 /// because the AMDGPU instruction is not recognized as terminator fix this
261 /// and retire this routine
262 void replaceInstrUseOfBlockWith(MachineBasicBlock *SrcMBB,
263 MachineBasicBlock *OldMBB, MachineBasicBlock *NewBlk);
264 static void wrapup(MachineBasicBlock *MBB);
265
Vincent Lejeune960a6222013-07-19 21:45:06 +0000266 int patternMatch(MachineBasicBlock *MBB);
267 int patternMatchGroup(MachineBasicBlock *MBB);
268 int serialPatternMatch(MachineBasicBlock *MBB);
269 int ifPatternMatch(MachineBasicBlock *MBB);
270 int loopendPatternMatch();
271 int mergeLoop(MachineLoop *LoopRep);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000272
Vincent Lejeune960a6222013-07-19 21:45:06 +0000273 /// return true iff src1Blk->succ_size() == 0 && src1Blk and src2Blk are in
274 /// the same loop with LoopLandInfo without explicitly keeping track of
275 /// loopContBlks and loopBreakBlks, this is a method to get the information.
276 bool isSameloopDetachedContbreak(MachineBasicBlock *Src1MBB,
277 MachineBasicBlock *Src2MBB);
278 int handleJumpintoIf(MachineBasicBlock *HeadMBB,
279 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
280 int handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
281 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB);
282 int improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
283 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
284 MachineBasicBlock **LandMBBPtr);
285 void showImproveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
286 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
287 MachineBasicBlock *LandMBB, bool Detail = false);
288 int cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
289 MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB);
290 void mergeSerialBlock(MachineBasicBlock *DstMBB,
291 MachineBasicBlock *SrcMBB);
292
293 void mergeIfthenelseBlock(MachineInstr *BranchMI,
294 MachineBasicBlock *MBB, MachineBasicBlock *TrueMBB,
295 MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB);
296 void mergeLooplandBlock(MachineBasicBlock *DstMBB,
297 MachineBasicBlock *LandMBB);
298 void mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
299 MachineBasicBlock *LandMBB);
300 void settleLoopcontBlock(MachineBasicBlock *ContingMBB,
301 MachineBasicBlock *ContMBB);
302 /// normalizeInfiniteLoopExit change
303 /// B1:
304 /// uncond_br LoopHeader
305 ///
306 /// to
307 /// B1:
308 /// cond_br 1 LoopHeader dummyExit
309 /// and return the newly added dummy exit block
310 MachineBasicBlock *normalizeInfiniteLoopExit(MachineLoop *LoopRep);
311 void removeUnconditionalBranch(MachineBasicBlock *MBB);
312 /// Remove duplicate branches instructions in a block.
313 /// For instance
314 /// B0:
315 /// cond_br X B1 B2
316 /// cond_br X B1 B2
317 /// is transformed to
318 /// B0:
319 /// cond_br X B1 B2
320 void removeRedundantConditionalBranch(MachineBasicBlock *MBB);
321 void addDummyExitBlock(SmallVectorImpl<MachineBasicBlock *> &RetMBB);
322 void removeSuccessor(MachineBasicBlock *MBB);
323 MachineBasicBlock *cloneBlockForPredecessor(MachineBasicBlock *MBB,
324 MachineBasicBlock *PredMBB);
325 void migrateInstruction(MachineBasicBlock *SrcMBB,
326 MachineBasicBlock *DstMBB, MachineBasicBlock::iterator I);
327 void recordSccnum(MachineBasicBlock *MBB, int SCCNum);
328 void retireBlock(MachineBasicBlock *MBB);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000329
Vincent Lejeune960a6222013-07-19 21:45:06 +0000330private:
331 MBBInfoMap BlockInfoMap;
332 LoopLandInfoMap LLInfoMap;
333 std::map<MachineLoop *, bool> Visited;
334 MachineFunction *FuncRep;
335 SmallVector<MachineBasicBlock *, DEFAULT_VEC_SLOTS> OrderedBlks;
336};
337
Eugene Zelenko66203762017-01-21 00:53:49 +0000338char AMDGPUCFGStructurizer::ID = 0;
339
340} // end anonymous namespace
341
Vincent Lejeune960a6222013-07-19 21:45:06 +0000342int AMDGPUCFGStructurizer::getSCCNum(MachineBasicBlock *MBB) const {
343 MBBInfoMap::const_iterator It = BlockInfoMap.find(MBB);
344 if (It == BlockInfoMap.end())
345 return INVALIDSCCNUM;
346 return (*It).second->SccNum;
Tom Stellard75aadc22012-12-11 21:25:42 +0000347}
348
Vincent Lejeune960a6222013-07-19 21:45:06 +0000349MachineBasicBlock *AMDGPUCFGStructurizer::getLoopLandInfo(MachineLoop *LoopRep)
350 const {
351 LoopLandInfoMap::const_iterator It = LLInfoMap.find(LoopRep);
352 if (It == LLInfoMap.end())
Craig Topper062a2ba2014-04-25 05:30:21 +0000353 return nullptr;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000354 return (*It).second;
355}
356
357bool AMDGPUCFGStructurizer::hasBackEdge(MachineBasicBlock *MBB) const {
358 MachineLoop *LoopRep = MLI->getLoopFor(MBB);
359 if (!LoopRep)
360 return false;
361 MachineBasicBlock *LoopHeader = LoopRep->getHeader();
362 return MBB->isSuccessor(LoopHeader);
363}
364
Vincent Lejeune960a6222013-07-19 21:45:06 +0000365bool AMDGPUCFGStructurizer::isRetiredBlock(MachineBasicBlock *MBB) const {
366 MBBInfoMap::const_iterator It = BlockInfoMap.find(MBB);
367 if (It == BlockInfoMap.end())
368 return false;
369 return (*It).second->IsRetired;
370}
371
372bool AMDGPUCFGStructurizer::isActiveLoophead(MachineBasicBlock *MBB) const {
373 MachineLoop *LoopRep = MLI->getLoopFor(MBB);
374 while (LoopRep && LoopRep->getHeader() == MBB) {
375 MachineBasicBlock *LoopLand = getLoopLandInfo(LoopRep);
376 if(!LoopLand)
377 return true;
378 if (!isRetiredBlock(LoopLand))
379 return true;
380 LoopRep = LoopRep->getParentLoop();
381 }
382 return false;
383}
Eugene Zelenko66203762017-01-21 00:53:49 +0000384
Vincent Lejeune960a6222013-07-19 21:45:06 +0000385AMDGPUCFGStructurizer::PathToKind AMDGPUCFGStructurizer::singlePathTo(
386 MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB,
387 bool AllowSideEntry) const {
388 assert(DstMBB);
389 if (SrcMBB == DstMBB)
390 return SinglePath_InPath;
391 while (SrcMBB && SrcMBB->succ_size() == 1) {
392 SrcMBB = *SrcMBB->succ_begin();
393 if (SrcMBB == DstMBB)
394 return SinglePath_InPath;
395 if (!AllowSideEntry && SrcMBB->pred_size() > 1)
396 return Not_SinglePath;
397 }
398 if (SrcMBB && SrcMBB->succ_size()==0)
399 return SinglePath_NotInPath;
400 return Not_SinglePath;
401}
402
403int AMDGPUCFGStructurizer::countActiveBlock(MBBVector::const_iterator It,
404 MBBVector::const_iterator E) const {
405 int Count = 0;
406 while (It != E) {
407 if (!isRetiredBlock(*It))
408 ++Count;
409 ++It;
410 }
411 return Count;
412}
413
414bool AMDGPUCFGStructurizer::needMigrateBlock(MachineBasicBlock *MBB) const {
415 unsigned BlockSizeThreshold = 30;
416 unsigned CloneInstrThreshold = 100;
417 bool MultiplePreds = MBB && (MBB->pred_size() > 1);
418
419 if(!MultiplePreds)
420 return false;
421 unsigned BlkSize = MBB->size();
422 return ((BlkSize > BlockSizeThreshold) &&
423 (BlkSize * (MBB->pred_size() - 1) > CloneInstrThreshold));
424}
425
426void AMDGPUCFGStructurizer::reversePredicateSetter(
Hans Wennborg0dd9ed12016-08-13 01:12:49 +0000427 MachineBasicBlock::iterator I, MachineBasicBlock &MBB) {
Duncan P. N. Exon Smithf197b1f2016-08-12 05:05:36 +0000428 assert(I.isValid() && "Expected valid iterator");
Duncan P. N. Exon Smith221847e2016-07-08 19:00:17 +0000429 for (;; --I) {
Hans Wennborg0dd9ed12016-08-13 01:12:49 +0000430 if (I == MBB.end())
431 continue;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000432 if (I->getOpcode() == AMDGPU::PRED_X) {
Duncan P. N. Exon Smithf197b1f2016-08-12 05:05:36 +0000433 switch (I->getOperand(2).getImm()) {
Matt Arsenault44f6d692016-08-13 01:43:46 +0000434 case AMDGPU::PRED_SETE_INT:
435 I->getOperand(2).setImm(AMDGPU::PRED_SETNE_INT);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000436 return;
Matt Arsenault44f6d692016-08-13 01:43:46 +0000437 case AMDGPU::PRED_SETNE_INT:
438 I->getOperand(2).setImm(AMDGPU::PRED_SETE_INT);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000439 return;
Matt Arsenault44f6d692016-08-13 01:43:46 +0000440 case AMDGPU::PRED_SETE:
441 I->getOperand(2).setImm(AMDGPU::PRED_SETNE);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000442 return;
Matt Arsenault44f6d692016-08-13 01:43:46 +0000443 case AMDGPU::PRED_SETNE:
444 I->getOperand(2).setImm(AMDGPU::PRED_SETE);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000445 return;
446 default:
447 llvm_unreachable("PRED_X Opcode invalid!");
448 }
449 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000450 }
451}
452
Vincent Lejeune960a6222013-07-19 21:45:06 +0000453void AMDGPUCFGStructurizer::insertInstrEnd(MachineBasicBlock *MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000454 int NewOpcode, const DebugLoc &DL) {
455 MachineInstr *MI =
456 MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DL);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000457 MBB->push_back(MI);
458 //assume the instruction doesn't take any reg operand ...
459 SHOWNEWINSTR(MI);
460}
Tom Stellard75aadc22012-12-11 21:25:42 +0000461
Vincent Lejeune960a6222013-07-19 21:45:06 +0000462MachineInstr *AMDGPUCFGStructurizer::insertInstrBefore(MachineBasicBlock *MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000463 int NewOpcode,
464 const DebugLoc &DL) {
Vincent Lejeune960a6222013-07-19 21:45:06 +0000465 MachineInstr *MI =
466 MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DL);
467 if (MBB->begin() != MBB->end())
468 MBB->insert(MBB->begin(), MI);
469 else
470 MBB->push_back(MI);
471 SHOWNEWINSTR(MI);
472 return MI;
473}
474
475MachineInstr *AMDGPUCFGStructurizer::insertInstrBefore(
476 MachineBasicBlock::iterator I, int NewOpcode) {
477 MachineInstr *OldMI = &(*I);
478 MachineBasicBlock *MBB = OldMI->getParent();
479 MachineInstr *NewMBB =
480 MBB->getParent()->CreateMachineInstr(TII->get(NewOpcode), DebugLoc());
481 MBB->insert(I, NewMBB);
482 //assume the instruction doesn't take any reg operand ...
483 SHOWNEWINSTR(NewMBB);
484 return NewMBB;
485}
486
487void AMDGPUCFGStructurizer::insertCondBranchBefore(
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000488 MachineBasicBlock::iterator I, int NewOpcode, const DebugLoc &DL) {
Vincent Lejeune960a6222013-07-19 21:45:06 +0000489 MachineInstr *OldMI = &(*I);
490 MachineBasicBlock *MBB = OldMI->getParent();
491 MachineFunction *MF = MBB->getParent();
492 MachineInstr *NewMI = MF->CreateMachineInstr(TII->get(NewOpcode), DL);
493 MBB->insert(I, NewMI);
494 MachineInstrBuilder MIB(*MF, NewMI);
495 MIB.addReg(OldMI->getOperand(1).getReg(), false);
496 SHOWNEWINSTR(NewMI);
497 //erase later oldInstr->eraseFromParent();
498}
499
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000500void AMDGPUCFGStructurizer::insertCondBranchBefore(
501 MachineBasicBlock *blk, MachineBasicBlock::iterator I, int NewOpcode,
502 int RegNum, const DebugLoc &DL) {
Vincent Lejeune960a6222013-07-19 21:45:06 +0000503 MachineFunction *MF = blk->getParent();
504 MachineInstr *NewInstr = MF->CreateMachineInstr(TII->get(NewOpcode), DL);
505 //insert before
506 blk->insert(I, NewInstr);
507 MachineInstrBuilder(*MF, NewInstr).addReg(RegNum, false);
508 SHOWNEWINSTR(NewInstr);
509}
510
Vincent Lejeune960a6222013-07-19 21:45:06 +0000511int AMDGPUCFGStructurizer::getBranchNzeroOpcode(int OldOpcode) {
512 switch(OldOpcode) {
513 case AMDGPU::JUMP_COND:
514 case AMDGPU::JUMP: return AMDGPU::IF_PREDICATE_SET;
515 case AMDGPU::BRANCH_COND_i32:
516 case AMDGPU::BRANCH_COND_f32: return AMDGPU::IF_LOGICALNZ_f32;
517 default: llvm_unreachable("internal error");
518 }
519 return -1;
520}
521
522int AMDGPUCFGStructurizer::getBranchZeroOpcode(int OldOpcode) {
523 switch(OldOpcode) {
524 case AMDGPU::JUMP_COND:
525 case AMDGPU::JUMP: return AMDGPU::IF_PREDICATE_SET;
526 case AMDGPU::BRANCH_COND_i32:
527 case AMDGPU::BRANCH_COND_f32: return AMDGPU::IF_LOGICALZ_f32;
528 default: llvm_unreachable("internal error");
529 }
530 return -1;
531}
532
533int AMDGPUCFGStructurizer::getContinueNzeroOpcode(int OldOpcode) {
534 switch(OldOpcode) {
535 case AMDGPU::JUMP_COND:
536 case AMDGPU::JUMP: return AMDGPU::CONTINUE_LOGICALNZ_i32;
537 default: llvm_unreachable("internal error");
538 };
539 return -1;
540}
541
542int AMDGPUCFGStructurizer::getContinueZeroOpcode(int OldOpcode) {
543 switch(OldOpcode) {
544 case AMDGPU::JUMP_COND:
545 case AMDGPU::JUMP: return AMDGPU::CONTINUE_LOGICALZ_i32;
546 default: llvm_unreachable("internal error");
547 }
548 return -1;
549}
550
551MachineBasicBlock *AMDGPUCFGStructurizer::getTrueBranch(MachineInstr *MI) {
552 return MI->getOperand(0).getMBB();
553}
554
555void AMDGPUCFGStructurizer::setTrueBranch(MachineInstr *MI,
556 MachineBasicBlock *MBB) {
557 MI->getOperand(0).setMBB(MBB);
558}
559
560MachineBasicBlock *
561AMDGPUCFGStructurizer::getFalseBranch(MachineBasicBlock *MBB,
562 MachineInstr *MI) {
563 assert(MBB->succ_size() == 2);
564 MachineBasicBlock *TrueBranch = getTrueBranch(MI);
565 MachineBasicBlock::succ_iterator It = MBB->succ_begin();
566 MachineBasicBlock::succ_iterator Next = It;
567 ++Next;
568 return (*It == TrueBranch) ? *Next : *It;
569}
570
571bool AMDGPUCFGStructurizer::isCondBranch(MachineInstr *MI) {
572 switch (MI->getOpcode()) {
573 case AMDGPU::JUMP_COND:
574 case AMDGPU::BRANCH_COND_i32:
575 case AMDGPU::BRANCH_COND_f32: return true;
576 default:
577 return false;
578 }
579 return false;
580}
581
582bool AMDGPUCFGStructurizer::isUncondBranch(MachineInstr *MI) {
583 switch (MI->getOpcode()) {
584 case AMDGPU::JUMP:
585 case AMDGPU::BRANCH:
586 return true;
587 default:
588 return false;
589 }
590 return false;
591}
592
593DebugLoc AMDGPUCFGStructurizer::getLastDebugLocInBB(MachineBasicBlock *MBB) {
594 //get DebugLoc from the first MachineBasicBlock instruction with debug info
595 DebugLoc DL;
596 for (MachineBasicBlock::iterator It = MBB->begin(); It != MBB->end();
597 ++It) {
598 MachineInstr *instr = &(*It);
Duncan P. N. Exon Smith9dffcd02015-03-30 19:14:47 +0000599 if (instr->getDebugLoc())
Vincent Lejeune960a6222013-07-19 21:45:06 +0000600 DL = instr->getDebugLoc();
601 }
602 return DL;
603}
604
605MachineInstr *AMDGPUCFGStructurizer::getNormalBlockBranchInstr(
606 MachineBasicBlock *MBB) {
607 MachineBasicBlock::reverse_iterator It = MBB->rbegin();
608 MachineInstr *MI = &*It;
609 if (MI && (isCondBranch(MI) || isUncondBranch(MI)))
610 return MI;
Craig Topper062a2ba2014-04-25 05:30:21 +0000611 return nullptr;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000612}
613
614MachineInstr *AMDGPUCFGStructurizer::getLoopendBlockBranchInstr(
615 MachineBasicBlock *MBB) {
616 for (MachineBasicBlock::reverse_iterator It = MBB->rbegin(), E = MBB->rend();
617 It != E; ++It) {
618 // FIXME: Simplify
619 MachineInstr *MI = &*It;
620 if (MI) {
621 if (isCondBranch(MI) || isUncondBranch(MI))
622 return MI;
623 else if (!TII->isMov(MI->getOpcode()))
624 break;
625 }
626 }
Craig Topper062a2ba2014-04-25 05:30:21 +0000627 return nullptr;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000628}
629
630MachineInstr *AMDGPUCFGStructurizer::getReturnInstr(MachineBasicBlock *MBB) {
631 MachineBasicBlock::reverse_iterator It = MBB->rbegin();
632 if (It != MBB->rend()) {
633 MachineInstr *instr = &(*It);
634 if (instr->getOpcode() == AMDGPU::RETURN)
635 return instr;
636 }
Craig Topper062a2ba2014-04-25 05:30:21 +0000637 return nullptr;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000638}
639
Vincent Lejeune960a6222013-07-19 21:45:06 +0000640bool AMDGPUCFGStructurizer::isReturnBlock(MachineBasicBlock *MBB) {
641 MachineInstr *MI = getReturnInstr(MBB);
642 bool IsReturn = (MBB->succ_size() == 0);
643 if (MI)
644 assert(IsReturn);
645 else if (IsReturn)
646 DEBUG(
647 dbgs() << "BB" << MBB->getNumber()
648 <<" is return block without RETURN instr\n";);
649 return IsReturn;
650}
651
652void AMDGPUCFGStructurizer::cloneSuccessorList(MachineBasicBlock *DstMBB,
653 MachineBasicBlock *SrcMBB) {
654 for (MachineBasicBlock::succ_iterator It = SrcMBB->succ_begin(),
655 iterEnd = SrcMBB->succ_end(); It != iterEnd; ++It)
656 DstMBB->addSuccessor(*It); // *iter's predecessor is also taken care of
657}
658
659MachineBasicBlock *AMDGPUCFGStructurizer::clone(MachineBasicBlock *MBB) {
660 MachineFunction *Func = MBB->getParent();
661 MachineBasicBlock *NewMBB = Func->CreateMachineBasicBlock();
662 Func->push_back(NewMBB); //insert to function
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000663 for (const MachineInstr &It : *MBB)
664 NewMBB->push_back(Func->CloneMachineInstr(&It));
Vincent Lejeune960a6222013-07-19 21:45:06 +0000665 return NewMBB;
666}
667
668void AMDGPUCFGStructurizer::replaceInstrUseOfBlockWith(
669 MachineBasicBlock *SrcMBB, MachineBasicBlock *OldMBB,
670 MachineBasicBlock *NewBlk) {
671 MachineInstr *BranchMI = getLoopendBlockBranchInstr(SrcMBB);
672 if (BranchMI && isCondBranch(BranchMI) &&
673 getTrueBranch(BranchMI) == OldMBB)
674 setTrueBranch(BranchMI, NewBlk);
675}
676
677void AMDGPUCFGStructurizer::wrapup(MachineBasicBlock *MBB) {
678 assert((!MBB->getParent()->getJumpTableInfo()
679 || MBB->getParent()->getJumpTableInfo()->isEmpty())
680 && "found a jump table");
681
682 //collect continue right before endloop
683 SmallVector<MachineInstr *, DEFAULT_VEC_SLOTS> ContInstr;
684 MachineBasicBlock::iterator Pre = MBB->begin();
685 MachineBasicBlock::iterator E = MBB->end();
686 MachineBasicBlock::iterator It = Pre;
687 while (It != E) {
688 if (Pre->getOpcode() == AMDGPU::CONTINUE
689 && It->getOpcode() == AMDGPU::ENDLOOP)
Duncan P. N. Exon Smith4d295112016-07-08 19:16:05 +0000690 ContInstr.push_back(&*Pre);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000691 Pre = It;
692 ++It;
693 }
694
695 //delete continue right before endloop
696 for (unsigned i = 0; i < ContInstr.size(); ++i)
697 ContInstr[i]->eraseFromParent();
698
699 // TODO to fix up jump table so later phase won't be confused. if
700 // (jumpTableInfo->isEmpty() == false) { need to clean the jump table, but
701 // there isn't such an interface yet. alternatively, replace all the other
702 // blocks in the jump table with the entryBlk //}
Vincent Lejeune960a6222013-07-19 21:45:06 +0000703}
704
Vincent Lejeune960a6222013-07-19 21:45:06 +0000705bool AMDGPUCFGStructurizer::prepare() {
706 bool Changed = false;
Tom Stellard75aadc22012-12-11 21:25:42 +0000707
708 //FIXME: if not reducible flow graph, make it so ???
709
Vincent Lejeune960a6222013-07-19 21:45:06 +0000710 DEBUG(dbgs() << "AMDGPUCFGStructurizer::prepare\n";);
Tom Stellard75aadc22012-12-11 21:25:42 +0000711
Vincent Lejeune960a6222013-07-19 21:45:06 +0000712 orderBlocks(FuncRep);
Tom Stellard75aadc22012-12-11 21:25:42 +0000713
Vincent Lejeune960a6222013-07-19 21:45:06 +0000714 SmallVector<MachineBasicBlock *, DEFAULT_VEC_SLOTS> RetBlks;
Tom Stellard75aadc22012-12-11 21:25:42 +0000715
Vincent Lejeune960a6222013-07-19 21:45:06 +0000716 // Add an ExitBlk to loop that don't have one
717 for (MachineLoopInfo::iterator It = MLI->begin(),
718 E = MLI->end(); It != E; ++It) {
719 MachineLoop *LoopRep = (*It);
720 MBBVector ExitingMBBs;
721 LoopRep->getExitingBlocks(ExitingMBBs);
Tom Stellard75aadc22012-12-11 21:25:42 +0000722
Vincent Lejeune960a6222013-07-19 21:45:06 +0000723 if (ExitingMBBs.size() == 0) {
724 MachineBasicBlock* DummyExitBlk = normalizeInfiniteLoopExit(LoopRep);
725 if (DummyExitBlk)
726 RetBlks.push_back(DummyExitBlk);
Tom Stellard75aadc22012-12-11 21:25:42 +0000727 }
728 }
729
730 // Remove unconditional branch instr.
731 // Add dummy exit block iff there are multiple returns.
Vincent Lejeune960a6222013-07-19 21:45:06 +0000732 for (SmallVectorImpl<MachineBasicBlock *>::const_iterator
733 It = OrderedBlks.begin(), E = OrderedBlks.end(); It != E; ++It) {
734 MachineBasicBlock *MBB = *It;
735 removeUnconditionalBranch(MBB);
736 removeRedundantConditionalBranch(MBB);
737 if (isReturnBlock(MBB)) {
738 RetBlks.push_back(MBB);
Tom Stellard75aadc22012-12-11 21:25:42 +0000739 }
Vincent Lejeune960a6222013-07-19 21:45:06 +0000740 assert(MBB->succ_size() <= 2);
Tom Stellard75aadc22012-12-11 21:25:42 +0000741 }
742
Vincent Lejeune960a6222013-07-19 21:45:06 +0000743 if (RetBlks.size() >= 2) {
744 addDummyExitBlock(RetBlks);
745 Changed = true;
746 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000747
Vincent Lejeune960a6222013-07-19 21:45:06 +0000748 return Changed;
749}
750
751bool AMDGPUCFGStructurizer::run() {
Tom Stellard75aadc22012-12-11 21:25:42 +0000752 //Assume reducible CFG...
Matt Arsenaultdb8b1d52014-03-24 20:29:02 +0000753 DEBUG(dbgs() << "AMDGPUCFGStructurizer::run\n");
Tom Stellard75aadc22012-12-11 21:25:42 +0000754
Tom Stellard75aadc22012-12-11 21:25:42 +0000755#ifdef STRESSTEST
756 //Use the worse block ordering to test the algorithm.
757 ReverseVector(orderedBlks);
758#endif
759
Vincent Lejeune960a6222013-07-19 21:45:06 +0000760 DEBUG(dbgs() << "Ordered blocks:\n"; printOrderedBlocks(););
761 int NumIter = 0;
762 bool Finish = false;
763 MachineBasicBlock *MBB;
764 bool MakeProgress = false;
765 int NumRemainedBlk = countActiveBlock(OrderedBlks.begin(),
766 OrderedBlks.end());
Tom Stellard75aadc22012-12-11 21:25:42 +0000767
768 do {
Vincent Lejeune960a6222013-07-19 21:45:06 +0000769 ++NumIter;
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000770 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +0000771 dbgs() << "numIter = " << NumIter
772 << ", numRemaintedBlk = " << NumRemainedBlk << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000773 );
Tom Stellard75aadc22012-12-11 21:25:42 +0000774
Vincent Lejeune960a6222013-07-19 21:45:06 +0000775 SmallVectorImpl<MachineBasicBlock *>::const_iterator It =
776 OrderedBlks.begin();
777 SmallVectorImpl<MachineBasicBlock *>::const_iterator E =
778 OrderedBlks.end();
Tom Stellard75aadc22012-12-11 21:25:42 +0000779
Vincent Lejeune960a6222013-07-19 21:45:06 +0000780 SmallVectorImpl<MachineBasicBlock *>::const_iterator SccBeginIter =
781 It;
Craig Topper062a2ba2014-04-25 05:30:21 +0000782 MachineBasicBlock *SccBeginMBB = nullptr;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000783 int SccNumBlk = 0; // The number of active blocks, init to a
Tom Stellard75aadc22012-12-11 21:25:42 +0000784 // maximum possible number.
Vincent Lejeune960a6222013-07-19 21:45:06 +0000785 int SccNumIter; // Number of iteration in this SCC.
Tom Stellard75aadc22012-12-11 21:25:42 +0000786
Vincent Lejeune960a6222013-07-19 21:45:06 +0000787 while (It != E) {
788 MBB = *It;
Tom Stellard75aadc22012-12-11 21:25:42 +0000789
Vincent Lejeune960a6222013-07-19 21:45:06 +0000790 if (!SccBeginMBB) {
791 SccBeginIter = It;
792 SccBeginMBB = MBB;
793 SccNumIter = 0;
794 SccNumBlk = NumRemainedBlk; // Init to maximum possible number.
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000795 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +0000796 dbgs() << "start processing SCC" << getSCCNum(SccBeginMBB);
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000797 dbgs() << "\n";
798 );
Tom Stellard75aadc22012-12-11 21:25:42 +0000799 }
800
Vincent Lejeune960a6222013-07-19 21:45:06 +0000801 if (!isRetiredBlock(MBB))
802 patternMatch(MBB);
Tom Stellard75aadc22012-12-11 21:25:42 +0000803
Vincent Lejeune960a6222013-07-19 21:45:06 +0000804 ++It;
Tom Stellard75aadc22012-12-11 21:25:42 +0000805
Vincent Lejeune960a6222013-07-19 21:45:06 +0000806 bool ContNextScc = true;
807 if (It == E
808 || getSCCNum(SccBeginMBB) != getSCCNum(*It)) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000809 // Just finish one scc.
Vincent Lejeune960a6222013-07-19 21:45:06 +0000810 ++SccNumIter;
811 int sccRemainedNumBlk = countActiveBlock(SccBeginIter, It);
812 if (sccRemainedNumBlk != 1 && sccRemainedNumBlk >= SccNumBlk) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000813 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +0000814 dbgs() << "Can't reduce SCC " << getSCCNum(MBB)
815 << ", sccNumIter = " << SccNumIter;
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000816 dbgs() << "doesn't make any progress\n";
817 );
Vincent Lejeune960a6222013-07-19 21:45:06 +0000818 ContNextScc = true;
819 } else if (sccRemainedNumBlk != 1 && sccRemainedNumBlk < SccNumBlk) {
820 SccNumBlk = sccRemainedNumBlk;
821 It = SccBeginIter;
822 ContNextScc = false;
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000823 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +0000824 dbgs() << "repeat processing SCC" << getSCCNum(MBB)
Matt Arsenaultdb8b1d52014-03-24 20:29:02 +0000825 << "sccNumIter = " << SccNumIter << '\n';
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000826 );
Tom Stellard75aadc22012-12-11 21:25:42 +0000827 } else {
828 // Finish the current scc.
Vincent Lejeune960a6222013-07-19 21:45:06 +0000829 ContNextScc = true;
Tom Stellard75aadc22012-12-11 21:25:42 +0000830 }
831 } else {
832 // Continue on next component in the current scc.
Vincent Lejeune960a6222013-07-19 21:45:06 +0000833 ContNextScc = false;
Tom Stellard75aadc22012-12-11 21:25:42 +0000834 }
835
Vincent Lejeune960a6222013-07-19 21:45:06 +0000836 if (ContNextScc)
Craig Topper062a2ba2014-04-25 05:30:21 +0000837 SccBeginMBB = nullptr;
Tom Stellard75aadc22012-12-11 21:25:42 +0000838 } //while, "one iteration" over the function.
839
Vincent Lejeune960a6222013-07-19 21:45:06 +0000840 MachineBasicBlock *EntryMBB =
Tim Shenb5e0f5a2016-08-19 21:20:13 +0000841 *GraphTraits<MachineFunction *>::nodes_begin(FuncRep);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000842 if (EntryMBB->succ_size() == 0) {
843 Finish = true;
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000844 DEBUG(
845 dbgs() << "Reduce to one block\n";
846 );
Tom Stellard75aadc22012-12-11 21:25:42 +0000847 } else {
Vincent Lejeune960a6222013-07-19 21:45:06 +0000848 int NewnumRemainedBlk
849 = countActiveBlock(OrderedBlks.begin(), OrderedBlks.end());
Tom Stellard75aadc22012-12-11 21:25:42 +0000850 // consider cloned blocks ??
Vincent Lejeune960a6222013-07-19 21:45:06 +0000851 if (NewnumRemainedBlk == 1 || NewnumRemainedBlk < NumRemainedBlk) {
852 MakeProgress = true;
853 NumRemainedBlk = NewnumRemainedBlk;
Tom Stellard75aadc22012-12-11 21:25:42 +0000854 } else {
Vincent Lejeune960a6222013-07-19 21:45:06 +0000855 MakeProgress = false;
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000856 DEBUG(
857 dbgs() << "No progress\n";
858 );
Tom Stellard75aadc22012-12-11 21:25:42 +0000859 }
860 }
Vincent Lejeune960a6222013-07-19 21:45:06 +0000861 } while (!Finish && MakeProgress);
Tom Stellard75aadc22012-12-11 21:25:42 +0000862
863 // Misc wrap up to maintain the consistency of the Function representation.
Tim Shenb5e0f5a2016-08-19 21:20:13 +0000864 wrapup(*GraphTraits<MachineFunction *>::nodes_begin(FuncRep));
Tom Stellard75aadc22012-12-11 21:25:42 +0000865
866 // Detach retired Block, release memory.
Vincent Lejeune960a6222013-07-19 21:45:06 +0000867 for (MBBInfoMap::iterator It = BlockInfoMap.begin(), E = BlockInfoMap.end();
868 It != E; ++It) {
869 if ((*It).second && (*It).second->IsRetired) {
870 assert(((*It).first)->getNumber() != -1);
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000871 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +0000872 dbgs() << "Erase BB" << ((*It).first)->getNumber() << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000873 );
Vincent Lejeune960a6222013-07-19 21:45:06 +0000874 (*It).first->eraseFromParent(); //Remove from the parent Function.
Tom Stellard75aadc22012-12-11 21:25:42 +0000875 }
Vincent Lejeune960a6222013-07-19 21:45:06 +0000876 delete (*It).second;
Tom Stellard75aadc22012-12-11 21:25:42 +0000877 }
Vincent Lejeune960a6222013-07-19 21:45:06 +0000878 BlockInfoMap.clear();
879 LLInfoMap.clear();
Tom Stellard75aadc22012-12-11 21:25:42 +0000880
Matt Arsenaultdb8b1d52014-03-24 20:29:02 +0000881 if (!Finish) {
882 DEBUG(FuncRep->viewCFG());
Matt Arsenault5de68cb2016-03-02 03:33:55 +0000883 report_fatal_error("IRREDUCIBLE_CFG");
Matt Arsenaultdb8b1d52014-03-24 20:29:02 +0000884 }
Tom Stellard75aadc22012-12-11 21:25:42 +0000885
886 return true;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000887}
Tom Stellard75aadc22012-12-11 21:25:42 +0000888
Vincent Lejeune960a6222013-07-19 21:45:06 +0000889void AMDGPUCFGStructurizer::orderBlocks(MachineFunction *MF) {
890 int SccNum = 0;
891 MachineBasicBlock *MBB;
Duncan P. N. Exon Smith8e661ef2014-02-04 19:19:07 +0000892 for (scc_iterator<MachineFunction *> It = scc_begin(MF); !It.isAtEnd();
893 ++It, ++SccNum) {
Duncan P. N. Exon Smithd2b2fac2014-04-25 18:24:50 +0000894 const std::vector<MachineBasicBlock *> &SccNext = *It;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000895 for (std::vector<MachineBasicBlock *>::const_iterator
896 blockIter = SccNext.begin(), blockEnd = SccNext.end();
Tom Stellard75aadc22012-12-11 21:25:42 +0000897 blockIter != blockEnd; ++blockIter) {
Vincent Lejeune960a6222013-07-19 21:45:06 +0000898 MBB = *blockIter;
899 OrderedBlks.push_back(MBB);
900 recordSccnum(MBB, SccNum);
Tom Stellard75aadc22012-12-11 21:25:42 +0000901 }
902 }
903
Daniel Berlin58a6e572017-02-09 20:37:24 +0000904 // walk through all the block in func to check for unreachable
Daniel Berlin73ad5cb2017-02-09 20:37:46 +0000905 for (auto *MBB : nodes(MF)) {
Vincent Lejeune960a6222013-07-19 21:45:06 +0000906 SccNum = getSCCNum(MBB);
907 if (SccNum == INVALIDSCCNUM)
908 dbgs() << "unreachable block BB" << MBB->getNumber() << "\n";
Tom Stellard75aadc22012-12-11 21:25:42 +0000909 }
Vincent Lejeune960a6222013-07-19 21:45:06 +0000910}
Tom Stellard75aadc22012-12-11 21:25:42 +0000911
Vincent Lejeune960a6222013-07-19 21:45:06 +0000912int AMDGPUCFGStructurizer::patternMatch(MachineBasicBlock *MBB) {
913 int NumMatch = 0;
914 int CurMatch;
Tom Stellard75aadc22012-12-11 21:25:42 +0000915
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000916 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +0000917 dbgs() << "Begin patternMatch BB" << MBB->getNumber() << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000918 );
Tom Stellard75aadc22012-12-11 21:25:42 +0000919
Vincent Lejeune960a6222013-07-19 21:45:06 +0000920 while ((CurMatch = patternMatchGroup(MBB)) > 0)
921 NumMatch += CurMatch;
Tom Stellard75aadc22012-12-11 21:25:42 +0000922
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000923 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +0000924 dbgs() << "End patternMatch BB" << MBB->getNumber()
925 << ", numMatch = " << NumMatch << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +0000926 );
Tom Stellard75aadc22012-12-11 21:25:42 +0000927
Vincent Lejeune960a6222013-07-19 21:45:06 +0000928 return NumMatch;
929}
Tom Stellard75aadc22012-12-11 21:25:42 +0000930
Vincent Lejeune960a6222013-07-19 21:45:06 +0000931int AMDGPUCFGStructurizer::patternMatchGroup(MachineBasicBlock *MBB) {
932 int NumMatch = 0;
933 NumMatch += loopendPatternMatch();
934 NumMatch += serialPatternMatch(MBB);
935 NumMatch += ifPatternMatch(MBB);
936 return NumMatch;
937}
Tom Stellard75aadc22012-12-11 21:25:42 +0000938
Vincent Lejeune960a6222013-07-19 21:45:06 +0000939int AMDGPUCFGStructurizer::serialPatternMatch(MachineBasicBlock *MBB) {
940 if (MBB->succ_size() != 1)
Tom Stellard75aadc22012-12-11 21:25:42 +0000941 return 0;
Tom Stellard75aadc22012-12-11 21:25:42 +0000942
Vincent Lejeune960a6222013-07-19 21:45:06 +0000943 MachineBasicBlock *childBlk = *MBB->succ_begin();
944 if (childBlk->pred_size() != 1 || isActiveLoophead(childBlk))
Tom Stellard75aadc22012-12-11 21:25:42 +0000945 return 0;
Tom Stellard75aadc22012-12-11 21:25:42 +0000946
Vincent Lejeune960a6222013-07-19 21:45:06 +0000947 mergeSerialBlock(MBB, childBlk);
Tom Stellard75aadc22012-12-11 21:25:42 +0000948 ++numSerialPatternMatch;
949 return 1;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000950}
Tom Stellard75aadc22012-12-11 21:25:42 +0000951
Vincent Lejeune960a6222013-07-19 21:45:06 +0000952int AMDGPUCFGStructurizer::ifPatternMatch(MachineBasicBlock *MBB) {
Tom Stellard75aadc22012-12-11 21:25:42 +0000953 //two edges
Vincent Lejeune960a6222013-07-19 21:45:06 +0000954 if (MBB->succ_size() != 2)
Tom Stellard75aadc22012-12-11 21:25:42 +0000955 return 0;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000956 if (hasBackEdge(MBB))
Tom Stellard75aadc22012-12-11 21:25:42 +0000957 return 0;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000958 MachineInstr *BranchMI = getNormalBlockBranchInstr(MBB);
959 if (!BranchMI)
Tom Stellard75aadc22012-12-11 21:25:42 +0000960 return 0;
Tom Stellard75aadc22012-12-11 21:25:42 +0000961
Vincent Lejeune960a6222013-07-19 21:45:06 +0000962 assert(isCondBranch(BranchMI));
Tom Stellard827ec9b2013-11-18 19:43:38 +0000963 int NumMatch = 0;
Tom Stellard75aadc22012-12-11 21:25:42 +0000964
Vincent Lejeune960a6222013-07-19 21:45:06 +0000965 MachineBasicBlock *TrueMBB = getTrueBranch(BranchMI);
Tom Stellard827ec9b2013-11-18 19:43:38 +0000966 NumMatch += serialPatternMatch(TrueMBB);
967 NumMatch += ifPatternMatch(TrueMBB);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000968 MachineBasicBlock *FalseMBB = getFalseBranch(MBB, BranchMI);
Tom Stellard827ec9b2013-11-18 19:43:38 +0000969 NumMatch += serialPatternMatch(FalseMBB);
970 NumMatch += ifPatternMatch(FalseMBB);
Vincent Lejeune960a6222013-07-19 21:45:06 +0000971 MachineBasicBlock *LandBlk;
972 int Cloned = 0;
Tom Stellard75aadc22012-12-11 21:25:42 +0000973
Vincent Lejeune960a6222013-07-19 21:45:06 +0000974 assert (!TrueMBB->succ_empty() || !FalseMBB->succ_empty());
Tom Stellard75aadc22012-12-11 21:25:42 +0000975 // TODO: Simplify
Vincent Lejeune960a6222013-07-19 21:45:06 +0000976 if (TrueMBB->succ_size() == 1 && FalseMBB->succ_size() == 1
977 && *TrueMBB->succ_begin() == *FalseMBB->succ_begin()) {
978 // Diamond pattern
979 LandBlk = *TrueMBB->succ_begin();
980 } else if (TrueMBB->succ_size() == 1 && *TrueMBB->succ_begin() == FalseMBB) {
981 // Triangle pattern, false is empty
982 LandBlk = FalseMBB;
Craig Topper062a2ba2014-04-25 05:30:21 +0000983 FalseMBB = nullptr;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000984 } else if (FalseMBB->succ_size() == 1
985 && *FalseMBB->succ_begin() == TrueMBB) {
986 // Triangle pattern, true is empty
Vincent Lejeune8b8a7b52013-07-19 21:45:15 +0000987 // We reverse the predicate to make a triangle, empty false pattern;
988 std::swap(TrueMBB, FalseMBB);
Hans Wennborg0dd9ed12016-08-13 01:12:49 +0000989 reversePredicateSetter(MBB->end(), *MBB);
Vincent Lejeune8b8a7b52013-07-19 21:45:15 +0000990 LandBlk = FalseMBB;
Craig Topper062a2ba2014-04-25 05:30:21 +0000991 FalseMBB = nullptr;
Vincent Lejeune960a6222013-07-19 21:45:06 +0000992 } else if (FalseMBB->succ_size() == 1
993 && isSameloopDetachedContbreak(TrueMBB, FalseMBB)) {
994 LandBlk = *FalseMBB->succ_begin();
995 } else if (TrueMBB->succ_size() == 1
996 && isSameloopDetachedContbreak(FalseMBB, TrueMBB)) {
997 LandBlk = *TrueMBB->succ_begin();
Tom Stellard75aadc22012-12-11 21:25:42 +0000998 } else {
Tom Stellard827ec9b2013-11-18 19:43:38 +0000999 return NumMatch + handleJumpintoIf(MBB, TrueMBB, FalseMBB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001000 }
1001
1002 // improveSimpleJumpinfoIf can handle the case where landBlk == NULL but the
1003 // new BB created for landBlk==NULL may introduce new challenge to the
1004 // reduction process.
Vincent Lejeune960a6222013-07-19 21:45:06 +00001005 if (LandBlk &&
1006 ((TrueMBB && TrueMBB->pred_size() > 1)
1007 || (FalseMBB && FalseMBB->pred_size() > 1))) {
1008 Cloned += improveSimpleJumpintoIf(MBB, TrueMBB, FalseMBB, &LandBlk);
Tom Stellard75aadc22012-12-11 21:25:42 +00001009 }
1010
Vincent Lejeune960a6222013-07-19 21:45:06 +00001011 if (TrueMBB && TrueMBB->pred_size() > 1) {
1012 TrueMBB = cloneBlockForPredecessor(TrueMBB, MBB);
1013 ++Cloned;
Tom Stellard75aadc22012-12-11 21:25:42 +00001014 }
1015
Vincent Lejeune960a6222013-07-19 21:45:06 +00001016 if (FalseMBB && FalseMBB->pred_size() > 1) {
1017 FalseMBB = cloneBlockForPredecessor(FalseMBB, MBB);
1018 ++Cloned;
Tom Stellard75aadc22012-12-11 21:25:42 +00001019 }
1020
Vincent Lejeune960a6222013-07-19 21:45:06 +00001021 mergeIfthenelseBlock(BranchMI, MBB, TrueMBB, FalseMBB, LandBlk);
Tom Stellard75aadc22012-12-11 21:25:42 +00001022
1023 ++numIfPatternMatch;
1024
Vincent Lejeune960a6222013-07-19 21:45:06 +00001025 numClonedBlock += Cloned;
Tom Stellard75aadc22012-12-11 21:25:42 +00001026
Tom Stellard827ec9b2013-11-18 19:43:38 +00001027 return 1 + Cloned + NumMatch;
Vincent Lejeune960a6222013-07-19 21:45:06 +00001028}
Tom Stellard75aadc22012-12-11 21:25:42 +00001029
Vincent Lejeune960a6222013-07-19 21:45:06 +00001030int AMDGPUCFGStructurizer::loopendPatternMatch() {
Jan Vesely18b289f2015-03-13 17:32:43 +00001031 std::deque<MachineLoop *> NestedLoops;
1032 for (auto &It: *MLI)
1033 for (MachineLoop *ML : depth_first(It))
1034 NestedLoops.push_front(ML);
David Blaikieceec2bd2014-04-11 01:50:01 +00001035
Eugene Zelenko66203762017-01-21 00:53:49 +00001036 if (NestedLoops.empty())
Tom Stellard75aadc22012-12-11 21:25:42 +00001037 return 0;
Tom Stellard75aadc22012-12-11 21:25:42 +00001038
Jan Vesely18b289f2015-03-13 17:32:43 +00001039 // Process nested loop outside->inside (we did push_front),
1040 // so "continue" to a outside loop won't be mistaken as "break"
1041 // of the current loop.
Vincent Lejeune960a6222013-07-19 21:45:06 +00001042 int Num = 0;
Jan Vesely18b289f2015-03-13 17:32:43 +00001043 for (MachineLoop *ExaminedLoop : NestedLoops) {
Vincent Lejeune960a6222013-07-19 21:45:06 +00001044 if (ExaminedLoop->getNumBlocks() == 0 || Visited[ExaminedLoop])
Tom Stellard75aadc22012-12-11 21:25:42 +00001045 continue;
Vincent Lejeune960a6222013-07-19 21:45:06 +00001046 DEBUG(dbgs() << "Processing:\n"; ExaminedLoop->dump(););
1047 int NumBreak = mergeLoop(ExaminedLoop);
1048 if (NumBreak == -1)
Tom Stellard75aadc22012-12-11 21:25:42 +00001049 break;
Vincent Lejeune960a6222013-07-19 21:45:06 +00001050 Num += NumBreak;
1051 }
1052 return Num;
1053}
Tom Stellard75aadc22012-12-11 21:25:42 +00001054
Vincent Lejeune960a6222013-07-19 21:45:06 +00001055int AMDGPUCFGStructurizer::mergeLoop(MachineLoop *LoopRep) {
1056 MachineBasicBlock *LoopHeader = LoopRep->getHeader();
1057 MBBVector ExitingMBBs;
1058 LoopRep->getExitingBlocks(ExitingMBBs);
1059 assert(!ExitingMBBs.empty() && "Infinite Loop not supported");
1060 DEBUG(dbgs() << "Loop has " << ExitingMBBs.size() << " exiting blocks\n";);
1061 // We assume a single ExitBlk
1062 MBBVector ExitBlks;
1063 LoopRep->getExitBlocks(ExitBlks);
1064 SmallPtrSet<MachineBasicBlock *, 2> ExitBlkSet;
1065 for (unsigned i = 0, e = ExitBlks.size(); i < e; ++i)
1066 ExitBlkSet.insert(ExitBlks[i]);
1067 assert(ExitBlkSet.size() == 1);
1068 MachineBasicBlock *ExitBlk = *ExitBlks.begin();
1069 assert(ExitBlk && "Loop has several exit block");
1070 MBBVector LatchBlks;
Daniel Berlin73ad5cb2017-02-09 20:37:46 +00001071 for (auto *LB : inverse_children<MachineBasicBlock*>(LoopHeader))
Daniel Berlin58a6e572017-02-09 20:37:24 +00001072 if (LoopRep->contains(LB))
1073 LatchBlks.push_back(LB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001074
Vincent Lejeune960a6222013-07-19 21:45:06 +00001075 for (unsigned i = 0, e = ExitingMBBs.size(); i < e; ++i)
1076 mergeLoopbreakBlock(ExitingMBBs[i], ExitBlk);
1077 for (unsigned i = 0, e = LatchBlks.size(); i < e; ++i)
1078 settleLoopcontBlock(LatchBlks[i], LoopHeader);
1079 int Match = 0;
1080 do {
1081 Match = 0;
1082 Match += serialPatternMatch(LoopHeader);
1083 Match += ifPatternMatch(LoopHeader);
1084 } while (Match > 0);
1085 mergeLooplandBlock(LoopHeader, ExitBlk);
1086 MachineLoop *ParentLoop = LoopRep->getParentLoop();
1087 if (ParentLoop)
1088 MLI->changeLoopFor(LoopHeader, ParentLoop);
1089 else
1090 MLI->removeBlock(LoopHeader);
1091 Visited[LoopRep] = true;
1092 return 1;
1093}
Tom Stellard75aadc22012-12-11 21:25:42 +00001094
Vincent Lejeune960a6222013-07-19 21:45:06 +00001095bool AMDGPUCFGStructurizer::isSameloopDetachedContbreak(
1096 MachineBasicBlock *Src1MBB, MachineBasicBlock *Src2MBB) {
1097 if (Src1MBB->succ_size() == 0) {
1098 MachineLoop *LoopRep = MLI->getLoopFor(Src1MBB);
1099 if (LoopRep&& LoopRep == MLI->getLoopFor(Src2MBB)) {
1100 MachineBasicBlock *&TheEntry = LLInfoMap[LoopRep];
1101 if (TheEntry) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001102 DEBUG(
1103 dbgs() << "isLoopContBreakBlock yes src1 = BB"
Vincent Lejeune960a6222013-07-19 21:45:06 +00001104 << Src1MBB->getNumber()
1105 << " src2 = BB" << Src2MBB->getNumber() << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001106 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001107 return true;
1108 }
1109 }
1110 }
1111 return false;
Vincent Lejeune960a6222013-07-19 21:45:06 +00001112}
Tom Stellard75aadc22012-12-11 21:25:42 +00001113
Vincent Lejeune960a6222013-07-19 21:45:06 +00001114int AMDGPUCFGStructurizer::handleJumpintoIf(MachineBasicBlock *HeadMBB,
1115 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
1116 int Num = handleJumpintoIfImp(HeadMBB, TrueMBB, FalseMBB);
1117 if (Num == 0) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001118 DEBUG(
1119 dbgs() << "handleJumpintoIf swap trueBlk and FalseBlk" << "\n";
1120 );
Vincent Lejeune960a6222013-07-19 21:45:06 +00001121 Num = handleJumpintoIfImp(HeadMBB, FalseMBB, TrueMBB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001122 }
Vincent Lejeune960a6222013-07-19 21:45:06 +00001123 return Num;
Tom Stellard75aadc22012-12-11 21:25:42 +00001124}
1125
Vincent Lejeune960a6222013-07-19 21:45:06 +00001126int AMDGPUCFGStructurizer::handleJumpintoIfImp(MachineBasicBlock *HeadMBB,
1127 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB) {
1128 int Num = 0;
1129 MachineBasicBlock *DownBlk;
Tom Stellard75aadc22012-12-11 21:25:42 +00001130
1131 //trueBlk could be the common post dominator
Vincent Lejeune960a6222013-07-19 21:45:06 +00001132 DownBlk = TrueMBB;
Tom Stellard75aadc22012-12-11 21:25:42 +00001133
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001134 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +00001135 dbgs() << "handleJumpintoIfImp head = BB" << HeadMBB->getNumber()
1136 << " true = BB" << TrueMBB->getNumber()
1137 << ", numSucc=" << TrueMBB->succ_size()
1138 << " false = BB" << FalseMBB->getNumber() << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001139 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001140
Vincent Lejeune960a6222013-07-19 21:45:06 +00001141 while (DownBlk) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001142 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +00001143 dbgs() << "check down = BB" << DownBlk->getNumber();
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001144 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001145
Vincent Lejeune960a6222013-07-19 21:45:06 +00001146 if (singlePathTo(FalseMBB, DownBlk) == SinglePath_InPath) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001147 DEBUG(
1148 dbgs() << " working\n";
1149 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001150
Vincent Lejeune960a6222013-07-19 21:45:06 +00001151 Num += cloneOnSideEntryTo(HeadMBB, TrueMBB, DownBlk);
1152 Num += cloneOnSideEntryTo(HeadMBB, FalseMBB, DownBlk);
Tom Stellard75aadc22012-12-11 21:25:42 +00001153
Vincent Lejeune960a6222013-07-19 21:45:06 +00001154 numClonedBlock += Num;
1155 Num += serialPatternMatch(*HeadMBB->succ_begin());
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00001156 Num += serialPatternMatch(*std::next(HeadMBB->succ_begin()));
Vincent Lejeune960a6222013-07-19 21:45:06 +00001157 Num += ifPatternMatch(HeadMBB);
1158 assert(Num > 0);
Tom Stellard75aadc22012-12-11 21:25:42 +00001159
1160 break;
1161 }
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001162 DEBUG(
1163 dbgs() << " not working\n";
1164 );
Craig Topper062a2ba2014-04-25 05:30:21 +00001165 DownBlk = (DownBlk->succ_size() == 1) ? (*DownBlk->succ_begin()) : nullptr;
Tom Stellard75aadc22012-12-11 21:25:42 +00001166 } // walk down the postDomTree
1167
Vincent Lejeune960a6222013-07-19 21:45:06 +00001168 return Num;
1169}
Tom Stellard75aadc22012-12-11 21:25:42 +00001170
Florian Hahn6b3216a2017-07-31 10:07:49 +00001171#ifndef NDEBUG
Vincent Lejeune960a6222013-07-19 21:45:06 +00001172void AMDGPUCFGStructurizer::showImproveSimpleJumpintoIf(
1173 MachineBasicBlock *HeadMBB, MachineBasicBlock *TrueMBB,
1174 MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB, bool Detail) {
1175 dbgs() << "head = BB" << HeadMBB->getNumber()
1176 << " size = " << HeadMBB->size();
1177 if (Detail) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001178 dbgs() << "\n";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001179 HeadMBB->print(dbgs());
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001180 dbgs() << "\n";
Tom Stellard75aadc22012-12-11 21:25:42 +00001181 }
1182
Vincent Lejeune960a6222013-07-19 21:45:06 +00001183 if (TrueMBB) {
1184 dbgs() << ", true = BB" << TrueMBB->getNumber() << " size = "
1185 << TrueMBB->size() << " numPred = " << TrueMBB->pred_size();
1186 if (Detail) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001187 dbgs() << "\n";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001188 TrueMBB->print(dbgs());
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001189 dbgs() << "\n";
Tom Stellard75aadc22012-12-11 21:25:42 +00001190 }
1191 }
Vincent Lejeune960a6222013-07-19 21:45:06 +00001192 if (FalseMBB) {
1193 dbgs() << ", false = BB" << FalseMBB->getNumber() << " size = "
1194 << FalseMBB->size() << " numPred = " << FalseMBB->pred_size();
1195 if (Detail) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001196 dbgs() << "\n";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001197 FalseMBB->print(dbgs());
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001198 dbgs() << "\n";
Tom Stellard75aadc22012-12-11 21:25:42 +00001199 }
1200 }
Vincent Lejeune960a6222013-07-19 21:45:06 +00001201 if (LandMBB) {
1202 dbgs() << ", land = BB" << LandMBB->getNumber() << " size = "
1203 << LandMBB->size() << " numPred = " << LandMBB->pred_size();
1204 if (Detail) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001205 dbgs() << "\n";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001206 LandMBB->print(dbgs());
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001207 dbgs() << "\n";
Tom Stellard75aadc22012-12-11 21:25:42 +00001208 }
1209 }
1210
Eugene Zelenko66203762017-01-21 00:53:49 +00001211 dbgs() << "\n";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001212}
Florian Hahn6b3216a2017-07-31 10:07:49 +00001213#endif
Tom Stellard75aadc22012-12-11 21:25:42 +00001214
Vincent Lejeune960a6222013-07-19 21:45:06 +00001215int AMDGPUCFGStructurizer::improveSimpleJumpintoIf(MachineBasicBlock *HeadMBB,
1216 MachineBasicBlock *TrueMBB, MachineBasicBlock *FalseMBB,
1217 MachineBasicBlock **LandMBBPtr) {
1218 bool MigrateTrue = false;
1219 bool MigrateFalse = false;
Tom Stellard75aadc22012-12-11 21:25:42 +00001220
Vincent Lejeune960a6222013-07-19 21:45:06 +00001221 MachineBasicBlock *LandBlk = *LandMBBPtr;
Tom Stellard75aadc22012-12-11 21:25:42 +00001222
Vincent Lejeune960a6222013-07-19 21:45:06 +00001223 assert((!TrueMBB || TrueMBB->succ_size() <= 1)
1224 && (!FalseMBB || FalseMBB->succ_size() <= 1));
Tom Stellard75aadc22012-12-11 21:25:42 +00001225
Vincent Lejeune960a6222013-07-19 21:45:06 +00001226 if (TrueMBB == FalseMBB)
Tom Stellard75aadc22012-12-11 21:25:42 +00001227 return 0;
Tom Stellard75aadc22012-12-11 21:25:42 +00001228
Vincent Lejeune960a6222013-07-19 21:45:06 +00001229 MigrateTrue = needMigrateBlock(TrueMBB);
1230 MigrateFalse = needMigrateBlock(FalseMBB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001231
Vincent Lejeune960a6222013-07-19 21:45:06 +00001232 if (!MigrateTrue && !MigrateFalse)
Tom Stellard75aadc22012-12-11 21:25:42 +00001233 return 0;
Tom Stellard75aadc22012-12-11 21:25:42 +00001234
1235 // If we need to migrate either trueBlk and falseBlk, migrate the rest that
1236 // have more than one predecessors. without doing this, its predecessor
1237 // rather than headBlk will have undefined value in initReg.
Vincent Lejeune960a6222013-07-19 21:45:06 +00001238 if (!MigrateTrue && TrueMBB && TrueMBB->pred_size() > 1)
1239 MigrateTrue = true;
1240 if (!MigrateFalse && FalseMBB && FalseMBB->pred_size() > 1)
1241 MigrateFalse = true;
Tom Stellard75aadc22012-12-11 21:25:42 +00001242
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001243 DEBUG(
1244 dbgs() << "before improveSimpleJumpintoIf: ";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001245 showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0);
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001246 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001247
1248 // org: headBlk => if () {trueBlk} else {falseBlk} => landBlk
1249 //
1250 // new: headBlk => if () {initReg = 1; org trueBlk branch} else
1251 // {initReg = 0; org falseBlk branch }
1252 // => landBlk => if (initReg) {org trueBlk} else {org falseBlk}
1253 // => org landBlk
1254 // if landBlk->pred_size() > 2, put the about if-else inside
1255 // if (initReg !=2) {...}
1256 //
1257 // add initReg = initVal to headBlk
1258
1259 const TargetRegisterClass * I32RC = TRI->getCFGStructurizerRegClass(MVT::i32);
Tom Stellardb34186a2013-10-16 17:06:02 +00001260 if (!MigrateTrue || !MigrateFalse) {
1261 // XXX: We have an opportunity here to optimize the "branch into if" case
1262 // here. Branch into if looks like this:
1263 // entry
Benjamin Kramera9fe95b2013-10-18 14:12:50 +00001264 // / |
Tom Stellardb34186a2013-10-16 17:06:02 +00001265 // diamond_head branch_from
1266 // / \ |
1267 // diamond_false diamond_true
1268 // \ /
1269 // done
1270 //
1271 // The diamond_head block begins the "if" and the diamond_true block
1272 // is the block being "branched into".
1273 //
1274 // If MigrateTrue is true, then TrueBB is the block being "branched into"
1275 // and if MigrateFalse is true, then FalseBB is the block being
1276 // "branched into"
Matt Arsenaulte0b44042015-09-10 21:51:19 +00001277 //
Tom Stellardb34186a2013-10-16 17:06:02 +00001278 // Here is the pseudo code for how I think the optimization should work:
1279 // 1. Insert MOV GPR0, 0 before the branch instruction in diamond_head.
1280 // 2. Insert MOV GPR0, 1 before the branch instruction in branch_from.
1281 // 3. Move the branch instruction from diamond_head into its own basic
1282 // block (new_block).
1283 // 4. Add an unconditional branch from diamond_head to new_block
1284 // 5. Replace the branch instruction in branch_from with an unconditional
1285 // branch to new_block. If branch_from has multiple predecessors, then
1286 // we need to replace the True/False block in the branch
1287 // instruction instead of replacing it.
1288 // 6. Change the condition of the branch instruction in new_block from
1289 // COND to (COND || GPR0)
1290 //
1291 // In order insert these MOV instruction, we will need to use the
1292 // RegisterScavenger. Usually liveness stops being tracked during
1293 // the late machine optimization passes, however if we implement
1294 // bool TargetRegisterInfo::requiresRegisterScavenging(
1295 // const MachineFunction &MF)
Matt Arsenaulte0b44042015-09-10 21:51:19 +00001296 // and have it return true, liveness will be tracked correctly
Tom Stellardb34186a2013-10-16 17:06:02 +00001297 // by generic optimization passes. We will also need to make sure that
1298 // all of our target-specific passes that run after regalloc and before
1299 // the CFGStructurizer track liveness and we will need to modify this pass
1300 // to correctly track liveness.
1301 //
1302 // After the above changes, the new CFG should look like this:
1303 // entry
Benjamin Kramera9fe95b2013-10-18 14:12:50 +00001304 // / |
Tom Stellardb34186a2013-10-16 17:06:02 +00001305 // diamond_head branch_from
1306 // \ /
1307 // new_block
Benjamin Kramera9fe95b2013-10-18 14:12:50 +00001308 // / |
Tom Stellardb34186a2013-10-16 17:06:02 +00001309 // diamond_false diamond_true
1310 // \ /
1311 // done
1312 //
1313 // Without this optimization, we are forced to duplicate the diamond_true
1314 // block and we will end up with a CFG like this:
1315 //
1316 // entry
Benjamin Kramera9fe95b2013-10-18 14:12:50 +00001317 // / |
Tom Stellardb34186a2013-10-16 17:06:02 +00001318 // diamond_head branch_from
1319 // / \ |
1320 // diamond_false diamond_true diamond_true (duplicate)
1321 // \ / |
1322 // done --------------------|
1323 //
1324 // Duplicating diamond_true can be very costly especially if it has a
1325 // lot of instructions.
1326 return 0;
1327 }
Tom Stellard75aadc22012-12-11 21:25:42 +00001328
Vincent Lejeune960a6222013-07-19 21:45:06 +00001329 int NumNewBlk = 0;
Tom Stellard75aadc22012-12-11 21:25:42 +00001330
Vincent Lejeune960a6222013-07-19 21:45:06 +00001331 bool LandBlkHasOtherPred = (LandBlk->pred_size() > 2);
Tom Stellard75aadc22012-12-11 21:25:42 +00001332
1333 //insert AMDGPU::ENDIF to avoid special case "input landBlk == NULL"
Vincent Lejeune960a6222013-07-19 21:45:06 +00001334 MachineBasicBlock::iterator I = insertInstrBefore(LandBlk, AMDGPU::ENDIF);
Tom Stellard75aadc22012-12-11 21:25:42 +00001335
Vincent Lejeune960a6222013-07-19 21:45:06 +00001336 if (LandBlkHasOtherPred) {
Matt Arsenault5de68cb2016-03-02 03:33:55 +00001337 report_fatal_error("Extra register needed to handle CFG");
Vincent Lejeune960a6222013-07-19 21:45:06 +00001338 unsigned CmpResReg =
1339 HeadMBB->getParent()->getRegInfo().createVirtualRegister(I32RC);
Matt Arsenault5de68cb2016-03-02 03:33:55 +00001340 report_fatal_error("Extra compare instruction needed to handle CFG");
Vincent Lejeune960a6222013-07-19 21:45:06 +00001341 insertCondBranchBefore(LandBlk, I, AMDGPU::IF_PREDICATE_SET,
1342 CmpResReg, DebugLoc());
Tom Stellard75aadc22012-12-11 21:25:42 +00001343 }
1344
Tom Stellard69f86d12013-10-16 17:05:56 +00001345 // XXX: We are running this after RA, so creating virtual registers will
1346 // cause an assertion failure in the PostRA scheduling pass.
1347 unsigned InitReg =
1348 HeadMBB->getParent()->getRegInfo().createVirtualRegister(I32RC);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001349 insertCondBranchBefore(LandBlk, I, AMDGPU::IF_PREDICATE_SET, InitReg,
1350 DebugLoc());
Tom Stellard75aadc22012-12-11 21:25:42 +00001351
Vincent Lejeune960a6222013-07-19 21:45:06 +00001352 if (MigrateTrue) {
1353 migrateInstruction(TrueMBB, LandBlk, I);
Tom Stellard75aadc22012-12-11 21:25:42 +00001354 // need to uncondionally insert the assignment to ensure a path from its
1355 // predecessor rather than headBlk has valid value in initReg if
1356 // (initVal != 1).
Matt Arsenault5de68cb2016-03-02 03:33:55 +00001357 report_fatal_error("Extra register needed to handle CFG");
Tom Stellard75aadc22012-12-11 21:25:42 +00001358 }
Vincent Lejeune960a6222013-07-19 21:45:06 +00001359 insertInstrBefore(I, AMDGPU::ELSE);
Tom Stellard75aadc22012-12-11 21:25:42 +00001360
Vincent Lejeune960a6222013-07-19 21:45:06 +00001361 if (MigrateFalse) {
1362 migrateInstruction(FalseMBB, LandBlk, I);
Tom Stellard75aadc22012-12-11 21:25:42 +00001363 // need to uncondionally insert the assignment to ensure a path from its
1364 // predecessor rather than headBlk has valid value in initReg if
1365 // (initVal != 0)
Matt Arsenault5de68cb2016-03-02 03:33:55 +00001366 report_fatal_error("Extra register needed to handle CFG");
Tom Stellard75aadc22012-12-11 21:25:42 +00001367 }
1368
Vincent Lejeune960a6222013-07-19 21:45:06 +00001369 if (LandBlkHasOtherPred) {
Tom Stellard75aadc22012-12-11 21:25:42 +00001370 // add endif
Vincent Lejeune960a6222013-07-19 21:45:06 +00001371 insertInstrBefore(I, AMDGPU::ENDIF);
Tom Stellard75aadc22012-12-11 21:25:42 +00001372
1373 // put initReg = 2 to other predecessors of landBlk
Vincent Lejeune960a6222013-07-19 21:45:06 +00001374 for (MachineBasicBlock::pred_iterator PI = LandBlk->pred_begin(),
1375 PE = LandBlk->pred_end(); PI != PE; ++PI) {
1376 MachineBasicBlock *MBB = *PI;
1377 if (MBB != TrueMBB && MBB != FalseMBB)
Matt Arsenault5de68cb2016-03-02 03:33:55 +00001378 report_fatal_error("Extra register needed to handle CFG");
Vincent Lejeune960a6222013-07-19 21:45:06 +00001379 }
Tom Stellard75aadc22012-12-11 21:25:42 +00001380 }
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001381 DEBUG(
1382 dbgs() << "result from improveSimpleJumpintoIf: ";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001383 showImproveSimpleJumpintoIf(HeadMBB, TrueMBB, FalseMBB, LandBlk, 0);
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001384 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001385
1386 // update landBlk
Vincent Lejeune960a6222013-07-19 21:45:06 +00001387 *LandMBBPtr = LandBlk;
Tom Stellard75aadc22012-12-11 21:25:42 +00001388
Vincent Lejeune960a6222013-07-19 21:45:06 +00001389 return NumNewBlk;
1390}
Tom Stellard75aadc22012-12-11 21:25:42 +00001391
Vincent Lejeune960a6222013-07-19 21:45:06 +00001392void AMDGPUCFGStructurizer::mergeSerialBlock(MachineBasicBlock *DstMBB,
1393 MachineBasicBlock *SrcMBB) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001394 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +00001395 dbgs() << "serialPattern BB" << DstMBB->getNumber()
1396 << " <= BB" << SrcMBB->getNumber() << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001397 );
Vincent Lejeune960a6222013-07-19 21:45:06 +00001398 DstMBB->splice(DstMBB->end(), SrcMBB, SrcMBB->begin(), SrcMBB->end());
Tom Stellard75aadc22012-12-11 21:25:42 +00001399
Cong Houc1069892015-12-13 09:26:17 +00001400 DstMBB->removeSuccessor(SrcMBB, true);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001401 cloneSuccessorList(DstMBB, SrcMBB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001402
Vincent Lejeune960a6222013-07-19 21:45:06 +00001403 removeSuccessor(SrcMBB);
1404 MLI->removeBlock(SrcMBB);
1405 retireBlock(SrcMBB);
1406}
Tom Stellard75aadc22012-12-11 21:25:42 +00001407
Vincent Lejeune960a6222013-07-19 21:45:06 +00001408void AMDGPUCFGStructurizer::mergeIfthenelseBlock(MachineInstr *BranchMI,
1409 MachineBasicBlock *MBB, MachineBasicBlock *TrueMBB,
1410 MachineBasicBlock *FalseMBB, MachineBasicBlock *LandMBB) {
Vincent Lejeune8b8a7b52013-07-19 21:45:15 +00001411 assert (TrueMBB);
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001412 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +00001413 dbgs() << "ifPattern BB" << MBB->getNumber();
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001414 dbgs() << "{ ";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001415 if (TrueMBB) {
1416 dbgs() << "BB" << TrueMBB->getNumber();
Tom Stellard75aadc22012-12-11 21:25:42 +00001417 }
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001418 dbgs() << " } else ";
1419 dbgs() << "{ ";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001420 if (FalseMBB) {
1421 dbgs() << "BB" << FalseMBB->getNumber();
Tom Stellard75aadc22012-12-11 21:25:42 +00001422 }
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001423 dbgs() << " }\n ";
1424 dbgs() << "landBlock: ";
Vincent Lejeune960a6222013-07-19 21:45:06 +00001425 if (!LandMBB) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001426 dbgs() << "NULL";
Tom Stellard75aadc22012-12-11 21:25:42 +00001427 } else {
Vincent Lejeune960a6222013-07-19 21:45:06 +00001428 dbgs() << "BB" << LandMBB->getNumber();
Tom Stellard75aadc22012-12-11 21:25:42 +00001429 }
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001430 dbgs() << "\n";
1431 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001432
Vincent Lejeune960a6222013-07-19 21:45:06 +00001433 int OldOpcode = BranchMI->getOpcode();
1434 DebugLoc BranchDL = BranchMI->getDebugLoc();
Tom Stellard75aadc22012-12-11 21:25:42 +00001435
1436// transform to
1437// if cond
1438// trueBlk
1439// else
1440// falseBlk
1441// endif
1442// landBlk
1443
Vincent Lejeune960a6222013-07-19 21:45:06 +00001444 MachineBasicBlock::iterator I = BranchMI;
1445 insertCondBranchBefore(I, getBranchNzeroOpcode(OldOpcode),
1446 BranchDL);
Tom Stellard75aadc22012-12-11 21:25:42 +00001447
Vincent Lejeune960a6222013-07-19 21:45:06 +00001448 if (TrueMBB) {
1449 MBB->splice(I, TrueMBB, TrueMBB->begin(), TrueMBB->end());
Cong Houc1069892015-12-13 09:26:17 +00001450 MBB->removeSuccessor(TrueMBB, true);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001451 if (LandMBB && TrueMBB->succ_size()!=0)
Cong Houc1069892015-12-13 09:26:17 +00001452 TrueMBB->removeSuccessor(LandMBB, true);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001453 retireBlock(TrueMBB);
1454 MLI->removeBlock(TrueMBB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001455 }
1456
Vincent Lejeune960a6222013-07-19 21:45:06 +00001457 if (FalseMBB) {
1458 insertInstrBefore(I, AMDGPU::ELSE);
1459 MBB->splice(I, FalseMBB, FalseMBB->begin(),
1460 FalseMBB->end());
Cong Houc1069892015-12-13 09:26:17 +00001461 MBB->removeSuccessor(FalseMBB, true);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001462 if (LandMBB && FalseMBB->succ_size() != 0)
Cong Houc1069892015-12-13 09:26:17 +00001463 FalseMBB->removeSuccessor(LandMBB, true);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001464 retireBlock(FalseMBB);
1465 MLI->removeBlock(FalseMBB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001466 }
Vincent Lejeune960a6222013-07-19 21:45:06 +00001467 insertInstrBefore(I, AMDGPU::ENDIF);
1468
1469 BranchMI->eraseFromParent();
1470
1471 if (LandMBB && TrueMBB && FalseMBB)
1472 MBB->addSuccessor(LandMBB);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001473}
1474
1475void AMDGPUCFGStructurizer::mergeLooplandBlock(MachineBasicBlock *DstBlk,
1476 MachineBasicBlock *LandMBB) {
1477 DEBUG(dbgs() << "loopPattern header = BB" << DstBlk->getNumber()
1478 << " land = BB" << LandMBB->getNumber() << "\n";);
Tom Stellard75aadc22012-12-11 21:25:42 +00001479
Vincent Lejeune0c5ed2b2013-07-31 19:31:14 +00001480 insertInstrBefore(DstBlk, AMDGPU::WHILELOOP, DebugLoc());
1481 insertInstrEnd(DstBlk, AMDGPU::ENDLOOP, DebugLoc());
Cong Houd97c1002015-12-01 05:29:22 +00001482 DstBlk->replaceSuccessor(DstBlk, LandMBB);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001483}
Tom Stellard75aadc22012-12-11 21:25:42 +00001484
Vincent Lejeune960a6222013-07-19 21:45:06 +00001485void AMDGPUCFGStructurizer::mergeLoopbreakBlock(MachineBasicBlock *ExitingMBB,
1486 MachineBasicBlock *LandMBB) {
1487 DEBUG(dbgs() << "loopbreakPattern exiting = BB" << ExitingMBB->getNumber()
1488 << " land = BB" << LandMBB->getNumber() << "\n";);
1489 MachineInstr *BranchMI = getLoopendBlockBranchInstr(ExitingMBB);
1490 assert(BranchMI && isCondBranch(BranchMI));
1491 DebugLoc DL = BranchMI->getDebugLoc();
1492 MachineBasicBlock *TrueBranch = getTrueBranch(BranchMI);
1493 MachineBasicBlock::iterator I = BranchMI;
1494 if (TrueBranch != LandMBB)
Hans Wennborg0dd9ed12016-08-13 01:12:49 +00001495 reversePredicateSetter(I, *I->getParent());
Vincent Lejeune0c5ed2b2013-07-31 19:31:14 +00001496 insertCondBranchBefore(ExitingMBB, I, AMDGPU::IF_PREDICATE_SET, AMDGPU::PREDICATE_BIT, DL);
1497 insertInstrBefore(I, AMDGPU::BREAK);
1498 insertInstrBefore(I, AMDGPU::ENDIF);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001499 //now branchInst can be erase safely
1500 BranchMI->eraseFromParent();
1501 //now take care of successors, retire blocks
Cong Houc1069892015-12-13 09:26:17 +00001502 ExitingMBB->removeSuccessor(LandMBB, true);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001503}
Tom Stellard75aadc22012-12-11 21:25:42 +00001504
Vincent Lejeune960a6222013-07-19 21:45:06 +00001505void AMDGPUCFGStructurizer::settleLoopcontBlock(MachineBasicBlock *ContingMBB,
1506 MachineBasicBlock *ContMBB) {
1507 DEBUG(dbgs() << "settleLoopcontBlock conting = BB"
1508 << ContingMBB->getNumber()
1509 << ", cont = BB" << ContMBB->getNumber() << "\n";);
Tom Stellard75aadc22012-12-11 21:25:42 +00001510
Vincent Lejeune960a6222013-07-19 21:45:06 +00001511 MachineInstr *MI = getLoopendBlockBranchInstr(ContingMBB);
1512 if (MI) {
1513 assert(isCondBranch(MI));
1514 MachineBasicBlock::iterator I = MI;
1515 MachineBasicBlock *TrueBranch = getTrueBranch(MI);
1516 int OldOpcode = MI->getOpcode();
1517 DebugLoc DL = MI->getDebugLoc();
Tom Stellard75aadc22012-12-11 21:25:42 +00001518
Vincent Lejeune960a6222013-07-19 21:45:06 +00001519 bool UseContinueLogical = ((&*ContingMBB->rbegin()) == MI);
1520
David Blaikie4eaa79c2015-03-23 20:56:44 +00001521 if (!UseContinueLogical) {
Vincent Lejeune960a6222013-07-19 21:45:06 +00001522 int BranchOpcode =
1523 TrueBranch == ContMBB ? getBranchNzeroOpcode(OldOpcode) :
1524 getBranchZeroOpcode(OldOpcode);
1525 insertCondBranchBefore(I, BranchOpcode, DL);
1526 // insertEnd to ensure phi-moves, if exist, go before the continue-instr.
1527 insertInstrEnd(ContingMBB, AMDGPU::CONTINUE, DL);
1528 insertInstrEnd(ContingMBB, AMDGPU::ENDIF, DL);
1529 } else {
1530 int BranchOpcode =
1531 TrueBranch == ContMBB ? getContinueNzeroOpcode(OldOpcode) :
1532 getContinueZeroOpcode(OldOpcode);
1533 insertCondBranchBefore(I, BranchOpcode, DL);
Tom Stellard75aadc22012-12-11 21:25:42 +00001534 }
Vincent Lejeune960a6222013-07-19 21:45:06 +00001535
1536 MI->eraseFromParent();
1537 } else {
1538 // if we've arrived here then we've already erased the branch instruction
1539 // travel back up the basic block to see the last reference of our debug
1540 // location we've just inserted that reference here so it should be
1541 // representative insertEnd to ensure phi-moves, if exist, go before the
1542 // continue-instr.
1543 insertInstrEnd(ContingMBB, AMDGPU::CONTINUE,
1544 getLastDebugLocInBB(ContingMBB));
Tom Stellard75aadc22012-12-11 21:25:42 +00001545 }
1546}
1547
Vincent Lejeune960a6222013-07-19 21:45:06 +00001548int AMDGPUCFGStructurizer::cloneOnSideEntryTo(MachineBasicBlock *PreMBB,
1549 MachineBasicBlock *SrcMBB, MachineBasicBlock *DstMBB) {
1550 int Cloned = 0;
1551 assert(PreMBB->isSuccessor(SrcMBB));
1552 while (SrcMBB && SrcMBB != DstMBB) {
1553 assert(SrcMBB->succ_size() == 1);
1554 if (SrcMBB->pred_size() > 1) {
1555 SrcMBB = cloneBlockForPredecessor(SrcMBB, PreMBB);
1556 ++Cloned;
Tom Stellard75aadc22012-12-11 21:25:42 +00001557 }
Tom Stellard75aadc22012-12-11 21:25:42 +00001558
Vincent Lejeune960a6222013-07-19 21:45:06 +00001559 PreMBB = SrcMBB;
1560 SrcMBB = *SrcMBB->succ_begin();
Tom Stellard75aadc22012-12-11 21:25:42 +00001561 }
1562
Vincent Lejeune960a6222013-07-19 21:45:06 +00001563 return Cloned;
1564}
Tom Stellard75aadc22012-12-11 21:25:42 +00001565
Vincent Lejeune960a6222013-07-19 21:45:06 +00001566MachineBasicBlock *
1567AMDGPUCFGStructurizer::cloneBlockForPredecessor(MachineBasicBlock *MBB,
1568 MachineBasicBlock *PredMBB) {
1569 assert(PredMBB->isSuccessor(MBB) &&
Tom Stellard75aadc22012-12-11 21:25:42 +00001570 "succBlk is not a prececessor of curBlk");
1571
Vincent Lejeune960a6222013-07-19 21:45:06 +00001572 MachineBasicBlock *CloneMBB = clone(MBB); //clone instructions
1573 replaceInstrUseOfBlockWith(PredMBB, MBB, CloneMBB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001574 //srcBlk, oldBlk, newBlk
1575
Cong Houd97c1002015-12-01 05:29:22 +00001576 PredMBB->replaceSuccessor(MBB, CloneMBB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001577
1578 // add all successor to cloneBlk
Vincent Lejeune960a6222013-07-19 21:45:06 +00001579 cloneSuccessorList(CloneMBB, MBB);
Tom Stellard75aadc22012-12-11 21:25:42 +00001580
Vincent Lejeune960a6222013-07-19 21:45:06 +00001581 numClonedInstr += MBB->size();
Tom Stellard75aadc22012-12-11 21:25:42 +00001582
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001583 DEBUG(
1584 dbgs() << "Cloned block: " << "BB"
Vincent Lejeune960a6222013-07-19 21:45:06 +00001585 << MBB->getNumber() << "size " << MBB->size() << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001586 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001587
Vincent Lejeune960a6222013-07-19 21:45:06 +00001588 SHOWNEWBLK(CloneMBB, "result of Cloned block: ");
Tom Stellard75aadc22012-12-11 21:25:42 +00001589
Vincent Lejeune960a6222013-07-19 21:45:06 +00001590 return CloneMBB;
1591}
Tom Stellard75aadc22012-12-11 21:25:42 +00001592
Vincent Lejeune960a6222013-07-19 21:45:06 +00001593void AMDGPUCFGStructurizer::migrateInstruction(MachineBasicBlock *SrcMBB,
1594 MachineBasicBlock *DstMBB, MachineBasicBlock::iterator I) {
1595 MachineBasicBlock::iterator SpliceEnd;
Tom Stellard75aadc22012-12-11 21:25:42 +00001596 //look for the input branchinstr, not the AMDGPU branchinstr
Vincent Lejeune960a6222013-07-19 21:45:06 +00001597 MachineInstr *BranchMI = getNormalBlockBranchInstr(SrcMBB);
1598 if (!BranchMI) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001599 DEBUG(
1600 dbgs() << "migrateInstruction don't see branch instr\n" ;
1601 );
Vincent Lejeune960a6222013-07-19 21:45:06 +00001602 SpliceEnd = SrcMBB->end();
Tom Stellard75aadc22012-12-11 21:25:42 +00001603 } else {
Matt Arsenaulte0b44042015-09-10 21:51:19 +00001604 DEBUG(dbgs() << "migrateInstruction see branch instr: " << *BranchMI);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001605 SpliceEnd = BranchMI;
Tom Stellard75aadc22012-12-11 21:25:42 +00001606 }
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001607 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +00001608 dbgs() << "migrateInstruction before splice dstSize = " << DstMBB->size()
1609 << "srcSize = " << SrcMBB->size() << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001610 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001611
1612 //splice insert before insertPos
Vincent Lejeune960a6222013-07-19 21:45:06 +00001613 DstMBB->splice(I, SrcMBB, SrcMBB->begin(), SpliceEnd);
Tom Stellard75aadc22012-12-11 21:25:42 +00001614
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001615 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +00001616 dbgs() << "migrateInstruction after splice dstSize = " << DstMBB->size()
Matt Arsenaulte0b44042015-09-10 21:51:19 +00001617 << "srcSize = " << SrcMBB->size() << '\n';
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001618 );
Vincent Lejeune960a6222013-07-19 21:45:06 +00001619}
Tom Stellard75aadc22012-12-11 21:25:42 +00001620
Vincent Lejeune960a6222013-07-19 21:45:06 +00001621MachineBasicBlock *
1622AMDGPUCFGStructurizer::normalizeInfiniteLoopExit(MachineLoop* LoopRep) {
1623 MachineBasicBlock *LoopHeader = LoopRep->getHeader();
1624 MachineBasicBlock *LoopLatch = LoopRep->getLoopLatch();
Tom Stellard75aadc22012-12-11 21:25:42 +00001625
Vincent Lejeune960a6222013-07-19 21:45:06 +00001626 if (!LoopHeader || !LoopLatch)
Craig Topper062a2ba2014-04-25 05:30:21 +00001627 return nullptr;
Vincent Lejeune960a6222013-07-19 21:45:06 +00001628 MachineInstr *BranchMI = getLoopendBlockBranchInstr(LoopLatch);
1629 // Is LoopRep an infinite loop ?
1630 if (!BranchMI || !isUncondBranch(BranchMI))
Craig Topper062a2ba2014-04-25 05:30:21 +00001631 return nullptr;
Tom Stellard75aadc22012-12-11 21:25:42 +00001632
Vincent Lejeune960a6222013-07-19 21:45:06 +00001633 MachineBasicBlock *DummyExitBlk = FuncRep->CreateMachineBasicBlock();
1634 FuncRep->push_back(DummyExitBlk); //insert to function
1635 SHOWNEWBLK(DummyExitBlk, "DummyExitBlock to normalize infiniteLoop: ");
1636 DEBUG(dbgs() << "Old branch instr: " << *BranchMI << "\n";);
Tom Stellard1d46fb22015-07-16 15:38:29 +00001637 LLVMContext &Ctx = LoopHeader->getParent()->getFunction()->getContext();
1638 Ctx.emitError("Extra register needed to handle CFG");
1639 return nullptr;
Vincent Lejeune960a6222013-07-19 21:45:06 +00001640}
Tom Stellard75aadc22012-12-11 21:25:42 +00001641
Vincent Lejeune960a6222013-07-19 21:45:06 +00001642void AMDGPUCFGStructurizer::removeUnconditionalBranch(MachineBasicBlock *MBB) {
1643 MachineInstr *BranchMI;
Tom Stellard75aadc22012-12-11 21:25:42 +00001644
1645 // I saw two unconditional branch in one basic block in example
1646 // test_fc_do_while_or.c need to fix the upstream on this to remove the loop.
Vincent Lejeune960a6222013-07-19 21:45:06 +00001647 while ((BranchMI = getLoopendBlockBranchInstr(MBB))
1648 && isUncondBranch(BranchMI)) {
Matt Arsenaulte0b44042015-09-10 21:51:19 +00001649 DEBUG(dbgs() << "Removing uncond branch instr: " << *BranchMI);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001650 BranchMI->eraseFromParent();
Tom Stellard75aadc22012-12-11 21:25:42 +00001651 }
Vincent Lejeune960a6222013-07-19 21:45:06 +00001652}
Tom Stellard75aadc22012-12-11 21:25:42 +00001653
Vincent Lejeune960a6222013-07-19 21:45:06 +00001654void AMDGPUCFGStructurizer::removeRedundantConditionalBranch(
1655 MachineBasicBlock *MBB) {
1656 if (MBB->succ_size() != 2)
1657 return;
1658 MachineBasicBlock *MBB1 = *MBB->succ_begin();
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00001659 MachineBasicBlock *MBB2 = *std::next(MBB->succ_begin());
Vincent Lejeune960a6222013-07-19 21:45:06 +00001660 if (MBB1 != MBB2)
1661 return;
Tom Stellard75aadc22012-12-11 21:25:42 +00001662
Vincent Lejeune960a6222013-07-19 21:45:06 +00001663 MachineInstr *BranchMI = getNormalBlockBranchInstr(MBB);
1664 assert(BranchMI && isCondBranch(BranchMI));
Matt Arsenaulte0b44042015-09-10 21:51:19 +00001665 DEBUG(dbgs() << "Removing unneeded cond branch instr: " << *BranchMI);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001666 BranchMI->eraseFromParent();
1667 SHOWNEWBLK(MBB1, "Removing redundant successor");
Cong Houc1069892015-12-13 09:26:17 +00001668 MBB->removeSuccessor(MBB1, true);
Vincent Lejeune960a6222013-07-19 21:45:06 +00001669}
Tom Stellard75aadc22012-12-11 21:25:42 +00001670
Vincent Lejeune960a6222013-07-19 21:45:06 +00001671void AMDGPUCFGStructurizer::addDummyExitBlock(
1672 SmallVectorImpl<MachineBasicBlock*> &RetMBB) {
1673 MachineBasicBlock *DummyExitBlk = FuncRep->CreateMachineBasicBlock();
1674 FuncRep->push_back(DummyExitBlk); //insert to function
1675 insertInstrEnd(DummyExitBlk, AMDGPU::RETURN);
Tom Stellard75aadc22012-12-11 21:25:42 +00001676
Vincent Lejeune960a6222013-07-19 21:45:06 +00001677 for (SmallVectorImpl<MachineBasicBlock *>::iterator It = RetMBB.begin(),
1678 E = RetMBB.end(); It != E; ++It) {
1679 MachineBasicBlock *MBB = *It;
1680 MachineInstr *MI = getReturnInstr(MBB);
1681 if (MI)
1682 MI->eraseFromParent();
1683 MBB->addSuccessor(DummyExitBlk);
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001684 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +00001685 dbgs() << "Add dummyExitBlock to BB" << MBB->getNumber()
Tom Stellard75aadc22012-12-11 21:25:42 +00001686 << " successors\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001687 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001688 }
Vincent Lejeune960a6222013-07-19 21:45:06 +00001689 SHOWNEWBLK(DummyExitBlk, "DummyExitBlock: ");
Tom Stellard75aadc22012-12-11 21:25:42 +00001690}
1691
Vincent Lejeune960a6222013-07-19 21:45:06 +00001692void AMDGPUCFGStructurizer::removeSuccessor(MachineBasicBlock *MBB) {
1693 while (MBB->succ_size())
1694 MBB->removeSuccessor(*MBB->succ_begin());
Tom Stellard75aadc22012-12-11 21:25:42 +00001695}
1696
Vincent Lejeune960a6222013-07-19 21:45:06 +00001697void AMDGPUCFGStructurizer::recordSccnum(MachineBasicBlock *MBB,
1698 int SccNum) {
1699 BlockInformation *&srcBlkInfo = BlockInfoMap[MBB];
1700 if (!srcBlkInfo)
1701 srcBlkInfo = new BlockInformation();
1702 srcBlkInfo->SccNum = SccNum;
Tom Stellard75aadc22012-12-11 21:25:42 +00001703}
1704
Vincent Lejeune960a6222013-07-19 21:45:06 +00001705void AMDGPUCFGStructurizer::retireBlock(MachineBasicBlock *MBB) {
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001706 DEBUG(
Vincent Lejeune960a6222013-07-19 21:45:06 +00001707 dbgs() << "Retiring BB" << MBB->getNumber() << "\n";
Vincent Lejeunea8c38fe2013-07-19 21:44:56 +00001708 );
Tom Stellard75aadc22012-12-11 21:25:42 +00001709
Vincent Lejeune960a6222013-07-19 21:45:06 +00001710 BlockInformation *&SrcBlkInfo = BlockInfoMap[MBB];
Tom Stellard75aadc22012-12-11 21:25:42 +00001711
Vincent Lejeune960a6222013-07-19 21:45:06 +00001712 if (!SrcBlkInfo)
1713 SrcBlkInfo = new BlockInformation();
Tom Stellard75aadc22012-12-11 21:25:42 +00001714
Vincent Lejeune960a6222013-07-19 21:45:06 +00001715 SrcBlkInfo->IsRetired = true;
1716 assert(MBB->succ_size() == 0 && MBB->pred_size() == 0
Tom Stellard75aadc22012-12-11 21:25:42 +00001717 && "can't retire block yet");
1718}
1719
Tom Stellardf2ba9722013-12-11 17:51:47 +00001720INITIALIZE_PASS_BEGIN(AMDGPUCFGStructurizer, "amdgpustructurizer",
1721 "AMDGPU CFG Structurizer", false, false)
1722INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
1723INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
1724INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
1725INITIALIZE_PASS_END(AMDGPUCFGStructurizer, "amdgpustructurizer",
1726 "AMDGPU CFG Structurizer", false, false)
1727
1728FunctionPass *llvm::createAMDGPUCFGStructurizerPass() {
1729 return new AMDGPUCFGStructurizer();
Tom Stellard75aadc22012-12-11 21:25:42 +00001730}