LLVM: lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
27
28#define DEBUG_TYPE "loop-vectorize"
29
30using namespace llvm;
31
32namespace {
33
34class PlainCFGBuilder {
35private:
36
37 Loop *TheLoop;
38
39
41
42
44
45
47
48
49
50
51
53
55
56
58
59
61
62
65 void fixPhiNodes();
67#ifndef NDEBUG
68 bool isExternalDef(Value *Val);
69#endif
72
73public:
75 : TheLoop(Lp), LI(LI), Plan(P) {}
76
77
78 void buildPlainCFG();
79};
80}
81
82
83
87 Loop *LoopForBB = LI->getLoopFor(BB);
88 if (!SinglePred || LI->getLoopFor(SinglePred) == LoopForBB)
89 return nullptr;
90
91
92 assert(SinglePred == LI->getLoopFor(SinglePred)->getLoopLatch() &&
93 "SinglePred must be the only loop latch");
94 return SinglePred;
95 };
96 if (auto *LatchBB = GetLatchOfExit(BB)) {
97 auto *PredRegion = getOrCreateVPBB(LatchBB)->getParent();
98 assert(VPBB == cast(PredRegion->getSingleSuccessor()) &&
99 "successor must already be set for PredRegion; it must have VPBB "
100 "as single successor");
102 return;
103 }
104
107 VPBBPreds.push_back(getOrCreateVPBB(Pred));
109}
110
112 return L && BB == L->getHeader();
113}
114
117
118 Loop *LoopOfBB = LI->getLoopFor(BB);
120}
121
122
123void PlainCFGBuilder::fixPhiNodes() {
124 for (auto *Phi : PhisToFix) {
125 assert(IRDef2VPValue.count(Phi) && "Missing VPInstruction for PHINode.");
127 assert(isa(VPVal) &&
128 "Expected WidenPHIRecipe for phi node.");
129 auto *VPPhi = cast(VPVal);
130 assert(VPPhi->getNumOperands() == 0 &&
131 "Expected VPInstruction with no operands.");
132
133 Loop *L = LI->getLoopFor(Phi->getParent());
135
136
137 assert(Phi->getNumOperands() == 2);
138 BasicBlock *LoopPred = L->getLoopPredecessor();
139 VPPhi->addIncoming(
140 getOrCreateVPOperand(Phi->getIncomingValueForBlock(LoopPred)),
141 BB2VPBB[LoopPred]);
142 BasicBlock *LoopLatch = L->getLoopLatch();
143 VPPhi->addIncoming(
144 getOrCreateVPOperand(Phi->getIncomingValueForBlock(LoopLatch)),
145 BB2VPBB[LoopLatch]);
146 continue;
147 }
148
149 for (unsigned I = 0; I != Phi->getNumOperands(); ++I)
150 VPPhi->addIncoming(getOrCreateVPOperand(Phi->getIncomingValue(I)),
151 BB2VPBB[Phi->getIncomingBlock(I)]);
152 }
153}
154
157}
158
159
161 if (L->getLoopDepth() < OuterLoop->getLoopDepth())
162 return false;
164 while (P) {
165 if (P == OuterLoop)
166 return true;
168 }
169 return false;
170}
171
172
173
174
175
177 if (auto *VPBB = BB2VPBB.lookup(BB)) {
178
179 return VPBB;
180 }
181
182
186 BB2VPBB[BB] = VPBB;
187
188
189 Loop *LoopOfBB = LI->getLoopFor(BB);
191 return VPBB;
192
193 auto *RegionOfVPBB = Loop2Region.lookup(LoopOfBB);
195 assert(RegionOfVPBB &&
196 "Region should have been created by visiting header earlier");
198 return VPBB;
199 }
200
201 assert(!RegionOfVPBB &&
202 "First visit of a header basic block expects to register its region.");
203
204 if (LoopOfBB == TheLoop) {
205 RegionOfVPBB = Plan.getVectorLoopRegion();
206 } else {
207 RegionOfVPBB = Plan.createVPRegionBlock(Name.str(), false );
208 RegionOfVPBB->setParent(Loop2Region[LoopOfBB->getParentLoop()]);
209 }
210 RegionOfVPBB->setEntry(VPBB);
211 Loop2Region[LoopOfBB] = RegionOfVPBB;
212 return VPBB;
213}
214
215#ifndef NDEBUG
216
217
218
219
220
221
222bool PlainCFGBuilder::isExternalDef(Value *Val) {
223
224
225 Instruction *Inst = dyn_cast(Val);
226 if (!Inst)
227 return true;
228
230 assert(InstParent && "Expected instruction parent.");
231
232
233 BasicBlock *PH = TheLoop->getLoopPreheader();
234 assert(PH && "Expected loop pre-header.");
235
236 if (InstParent == PH)
237
238 return false;
239
240
242 assert(Exit && "Expected loop with single exit.");
243 if (InstParent == Exit) {
244
245 return false;
246 }
247
248
249 return !TheLoop->contains(Inst);
250}
251#endif
252
253
254
255
256
257VPValue *PlainCFGBuilder::getOrCreateVPOperand(Value *IRVal) {
258 auto VPValIt = IRDef2VPValue.find(IRVal);
259 if (VPValIt != IRDef2VPValue.end())
260
261
262 return VPValIt->second;
263
264
265
266
267
268
269
270
271 assert(isExternalDef(IRVal) && "Expected external definition as operand.");
272
273
274
275 VPValue *NewVPVal = Plan.getOrAddLiveIn(IRVal);
276 IRDef2VPValue[IRVal] = NewVPVal;
277 return NewVPVal;
278}
279
280
281
282
283void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
285 VPIRBuilder.setInsertPoint(VPBB);
288
289
290
291 assert(!IRDef2VPValue.count(Inst) &&
292 "Instruction shouldn't have been visited.");
293
294 if (auto *Br = dyn_cast(Inst)) {
295
296
297 if (Br->isConditional()) {
298 VPValue *Cond = getOrCreateVPOperand(Br->getCondition());
300 }
301
302
303 continue;
304 }
305
307 if (auto *Phi = dyn_cast(Inst)) {
308
309
310
312 VPBB->appendRecipe(cast(NewVPV));
313 PhisToFix.push_back(Phi);
314 } else {
315
316
319 VPOperands.push_back(getOrCreateVPOperand(Op));
320
321
322
323 NewVPV = cast(
324 VPIRBuilder.createNaryOp(Inst->getOpcode(), VPOperands, Inst));
325 }
326
327 IRDef2VPValue[Inst] = NewVPV;
328 }
329}
330
331
332void PlainCFGBuilder::buildPlainCFG() {
333
334
335
336
337 VPRegionBlock *TheRegion = Plan.getVectorLoopRegion();
338 BasicBlock *ThePreheaderBB = TheLoop->getLoopPreheader();
340 "Unexpected loop preheader");
341 auto *VectorPreheaderVPBB =
343
344
345
346
347 BB2VPBB[ThePreheaderBB] = VectorPreheaderVPBB;
348 BasicBlock *LoopExitBB = TheLoop->getUniqueExitBlock();
349 Loop2Region[LI->getLoopFor(TheLoop->getHeader())] = TheRegion;
350 assert(LoopExitBB && "Loops with multiple exits are not supported.");
351 BB2VPBB[LoopExitBB] = cast(TheRegion->getSingleSuccessor());
352
353
354
357 BB2VPBB[TheLoop->getHeader()] = VectorHeaderVPBB;
360 if (TheLoop->getHeader() != TheLoop->getLoopLatch())
361 BB2VPBB[TheLoop->getLoopLatch()] = VectorLatchVPBB;
362 else
363 TheRegion->setExiting(VectorHeaderVPBB);
364
365
366
367
368
369
370
371
372
373
374 for (auto &I : *ThePreheaderBB) {
375 if (I.getType()->isVoidTy())
376 continue;
377 IRDef2VPValue[&I] = Plan.getOrAddLiveIn(&I);
378 }
379
381 RPO.perform(LI);
382
384
385
388 createVPInstructionsForVPBB(VPBB, BB);
389 Loop *LoopForBB = LI->getLoopFor(BB);
390
392 setVPBBPredsFromBB(VPBB, BB);
393 } else {
394
395
396 assert(isHeaderVPBB(VPBB) && "isHeaderBB and isHeaderVPBB disagree");
397 if (TheRegion != Region)
398 setRegionPredsFromBB(Region, BB);
399 }
400
401
402
403
404 auto *BI = cast(BB->getTerminator());
405 unsigned NumSuccs = succ_size(BB);
406 if (NumSuccs == 1) {
411 continue;
412 }
413 assert(BI->isConditional() && NumSuccs == 2 && BI->isConditional() &&
414 "block must have conditional branch with 2 successors");
415
416
417 assert(IRDef2VPValue.contains(BI->getCondition()) &&
418 "Missing condition bit in IRDef2VPValue!");
419 VPBasicBlock *Successor0 = getOrCreateVPBB(BI->getSuccessor(0));
420 VPBasicBlock *Successor1 = getOrCreateVPBB(BI->getSuccessor(1));
421 if (!LoopForBB || BB != LoopForBB->getLoopLatch()) {
423 continue;
424 }
425
426
427
428
429 if (TheRegion != Region) {
431 : Successor0);
432 Region->setExiting(VPBB);
433 }
434 }
435
436
437
438
439 fixPhiNodes();
440}
441
442void VPlanHCFGBuilder::buildPlainCFG() {
443 PlainCFGBuilder PCFGBuilder(TheLoop, LI, Plan);
444 PCFGBuilder.buildPlainCFG();
445}
446
447
449
450 buildPlainCFG();
452
453
455 LLVM_DEBUG(dbgs() << "Dominator Tree after building the plain CFG.\n";
457}
This file provides a LoopVectorizationPlanner class.
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isHeaderBB(BasicBlock *BB, Loop *L)
static bool doesContainLoop(const Loop *L, const Loop *OuterLoop)
Return true of L loop is contained within OuterLoop.
static bool isHeaderVPBB(VPBasicBlock *VPBB)
This file defines the VPlanHCFGBuilder class which contains the public interface (buildHierarchicalCF...
LLVM Basic Block Representation.
iterator_range< filter_iterator< BasicBlock::const_iterator, std::function< bool(const Instruction &)> > > instructionsWithoutDebug(bool SkipPseudoOp=true) const
Return a const iterator range over the instructions in the block, skipping any debug instructions.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
This class represents an Operation in the Expression.
void print(raw_ostream &O) const
print - Convert to human readable form
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
BlockT * getLoopLatch() const
If there is a single latch block for this loop, return it.
unsigned getLoopDepth() const
Return the nesting level of this loop.
BlockT * getLoopPredecessor() const
If the given loop's header has exactly one unique predecessor outside the loop, return it.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
Wrapper class to LoopBlocksDFS that provides a standard begin()/end() interface for the DFS reverse p...
Represents a single loop in the control flow graph.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
void appendRecipe(VPRecipeBase *Recipe)
Augment the existing recipes of a VPBasicBlock with an additional Recipe as the last recipe.
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
VPRegionBlock * getParent()
const VPBasicBlock * getExitingBasicBlock() const
void setPredecessors(ArrayRef< VPBlockBase * > NewPreds)
Set each VPBasicBlock in NewPreds as predecessor of this VPBlockBase.
void clearSuccessors()
Remove all the successors of this block.
void setTwoSuccessors(VPBlockBase *IfTrue, VPBlockBase *IfFalse)
Set two given VPBlockBases IfTrue and IfFalse to be the two successors of this VPBlockBase.
VPBlockBase * getSinglePredecessor() const
void clearPredecessors()
Remove all the predecessor of this block.
const VPBasicBlock * getEntryBasicBlock() const
void setOneSuccessor(VPBlockBase *Successor)
Set a given VPBlockBase Successor as the single successor of this VPBlockBase.
void setParent(VPRegionBlock *P)
VPBlockBase * getSingleSuccessor() const
VPlan-based builder utility analogous to IRBuilder.
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
const VPBlockBase * getEntry() const
void setExiting(VPBlockBase *ExitingBlock)
Set ExitingBlock as the exiting VPBlockBase of this VPRegionBlock.
A recipe for handling phis that are widened in the vector loop.
void buildHierarchicalCFG()
Build H-CFG for TheLoop and update Plan accordingly.
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
void setName(const Twine &newName)
LLVM Value Representation.
StringRef getName() const
Return a constant reference to the value's name.
const ParentTy * getParent() const
NodeAddr< PhiNode * > Phi
This is an optimization pass for GlobalISel generic memory operations.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto succ_size(const MachineBasicBlock *BB)
auto predecessors(const MachineBasicBlock *BB)