1 //===- VPlan.cpp - Vectorizer Plan ----------------------------------------===//
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 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This is the LLVM vectorization plan. It represents a candidate for
12 /// vectorization, allowing to plan and optimize how to vectorize a given loop
13 /// before generating LLVM-IR.
14 /// The vectorizer uses vectorization plans to estimate the costs of potential
15 /// candidates and if profitable to execute the desired plan, generating vector
16 /// LLVM-IR code.
17 ///
18 //===----------------------------------------------------------------------===//
19
20 #include "VPlan.h"
21 #include "VPlanDominatorTree.h"
22 #include "llvm/ADT/DepthFirstIterator.h"
23 #include "llvm/ADT/PostOrderIterator.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/ADT/Twine.h"
26 #include "llvm/Analysis/LoopInfo.h"
27 #include "llvm/IR/BasicBlock.h"
28 #include "llvm/IR/CFG.h"
29 #include "llvm/IR/InstrTypes.h"
30 #include "llvm/IR/Instruction.h"
31 #include "llvm/IR/Instructions.h"
32 #include "llvm/IR/Type.h"
33 #include "llvm/IR/Value.h"
34 #include "llvm/Support/Casting.h"
35 #include "llvm/Support/Debug.h"
36 #include "llvm/Support/ErrorHandling.h"
37 #include "llvm/Support/GenericDomTreeConstruction.h"
38 #include "llvm/Support/GraphWriter.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
41 #include <cassert>
42 #include <iterator>
43 #include <string>
44 #include <vector>
45
46 using namespace llvm;
47
48 #define DEBUG_TYPE "vplan"
49
operator <<(raw_ostream & OS,const VPValue & V)50 raw_ostream &llvm::operator<<(raw_ostream &OS, const VPValue &V) {
51 if (const VPInstruction *Instr = dyn_cast<VPInstruction>(&V))
52 Instr->print(OS);
53 else
54 V.printAsOperand(OS);
55 return OS;
56 }
57
58 /// \return the VPBasicBlock that is the entry of Block, possibly indirectly.
getEntryBasicBlock() const59 const VPBasicBlock *VPBlockBase::getEntryBasicBlock() const {
60 const VPBlockBase *Block = this;
61 while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
62 Block = Region->getEntry();
63 return cast<VPBasicBlock>(Block);
64 }
65
getEntryBasicBlock()66 VPBasicBlock *VPBlockBase::getEntryBasicBlock() {
67 VPBlockBase *Block = this;
68 while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
69 Block = Region->getEntry();
70 return cast<VPBasicBlock>(Block);
71 }
72
73 /// \return the VPBasicBlock that is the exit of Block, possibly indirectly.
getExitBasicBlock() const74 const VPBasicBlock *VPBlockBase::getExitBasicBlock() const {
75 const VPBlockBase *Block = this;
76 while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
77 Block = Region->getExit();
78 return cast<VPBasicBlock>(Block);
79 }
80
getExitBasicBlock()81 VPBasicBlock *VPBlockBase::getExitBasicBlock() {
82 VPBlockBase *Block = this;
83 while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
84 Block = Region->getExit();
85 return cast<VPBasicBlock>(Block);
86 }
87
getEnclosingBlockWithSuccessors()88 VPBlockBase *VPBlockBase::getEnclosingBlockWithSuccessors() {
89 if (!Successors.empty() || !Parent)
90 return this;
91 assert(Parent->getExit() == this &&
92 "Block w/o successors not the exit of its parent.");
93 return Parent->getEnclosingBlockWithSuccessors();
94 }
95
getEnclosingBlockWithPredecessors()96 VPBlockBase *VPBlockBase::getEnclosingBlockWithPredecessors() {
97 if (!Predecessors.empty() || !Parent)
98 return this;
99 assert(Parent->getEntry() == this &&
100 "Block w/o predecessors not the entry of its parent.");
101 return Parent->getEnclosingBlockWithPredecessors();
102 }
103
deleteCFG(VPBlockBase * Entry)104 void VPBlockBase::deleteCFG(VPBlockBase *Entry) {
105 SmallVector<VPBlockBase *, 8> Blocks;
106 for (VPBlockBase *Block : depth_first(Entry))
107 Blocks.push_back(Block);
108
109 for (VPBlockBase *Block : Blocks)
110 delete Block;
111 }
112
113 BasicBlock *
createEmptyBasicBlock(VPTransformState::CFGState & CFG)114 VPBasicBlock::createEmptyBasicBlock(VPTransformState::CFGState &CFG) {
115 // BB stands for IR BasicBlocks. VPBB stands for VPlan VPBasicBlocks.
116 // Pred stands for Predessor. Prev stands for Previous - last visited/created.
117 BasicBlock *PrevBB = CFG.PrevBB;
118 BasicBlock *NewBB = BasicBlock::Create(PrevBB->getContext(), getName(),
119 PrevBB->getParent(), CFG.LastBB);
120 LLVM_DEBUG(dbgs() << "LV: created " << NewBB->getName() << '\n');
121
122 // Hook up the new basic block to its predecessors.
123 for (VPBlockBase *PredVPBlock : getHierarchicalPredecessors()) {
124 VPBasicBlock *PredVPBB = PredVPBlock->getExitBasicBlock();
125 auto &PredVPSuccessors = PredVPBB->getSuccessors();
126 BasicBlock *PredBB = CFG.VPBB2IRBB[PredVPBB];
127 assert(PredBB && "Predecessor basic-block not found building successor.");
128 auto *PredBBTerminator = PredBB->getTerminator();
129 LLVM_DEBUG(dbgs() << "LV: draw edge from" << PredBB->getName() << '\n');
130 if (isa<UnreachableInst>(PredBBTerminator)) {
131 assert(PredVPSuccessors.size() == 1 &&
132 "Predecessor ending w/o branch must have single successor.");
133 PredBBTerminator->eraseFromParent();
134 BranchInst::Create(NewBB, PredBB);
135 } else {
136 assert(PredVPSuccessors.size() == 2 &&
137 "Predecessor ending with branch must have two successors.");
138 unsigned idx = PredVPSuccessors.front() == this ? 0 : 1;
139 assert(!PredBBTerminator->getSuccessor(idx) &&
140 "Trying to reset an existing successor block.");
141 PredBBTerminator->setSuccessor(idx, NewBB);
142 }
143 }
144 return NewBB;
145 }
146
execute(VPTransformState * State)147 void VPBasicBlock::execute(VPTransformState *State) {
148 bool Replica = State->Instance &&
149 !(State->Instance->Part == 0 && State->Instance->Lane == 0);
150 VPBasicBlock *PrevVPBB = State->CFG.PrevVPBB;
151 VPBlockBase *SingleHPred = nullptr;
152 BasicBlock *NewBB = State->CFG.PrevBB; // Reuse it if possible.
153
154 // 1. Create an IR basic block, or reuse the last one if possible.
155 // The last IR basic block is reused, as an optimization, in three cases:
156 // A. the first VPBB reuses the loop header BB - when PrevVPBB is null;
157 // B. when the current VPBB has a single (hierarchical) predecessor which
158 // is PrevVPBB and the latter has a single (hierarchical) successor; and
159 // C. when the current VPBB is an entry of a region replica - where PrevVPBB
160 // is the exit of this region from a previous instance, or the predecessor
161 // of this region.
162 if (PrevVPBB && /* A */
163 !((SingleHPred = getSingleHierarchicalPredecessor()) &&
164 SingleHPred->getExitBasicBlock() == PrevVPBB &&
165 PrevVPBB->getSingleHierarchicalSuccessor()) && /* B */
166 !(Replica && getPredecessors().empty())) { /* C */
167 NewBB = createEmptyBasicBlock(State->CFG);
168 State->Builder.SetInsertPoint(NewBB);
169 // Temporarily terminate with unreachable until CFG is rewired.
170 UnreachableInst *Terminator = State->Builder.CreateUnreachable();
171 State->Builder.SetInsertPoint(Terminator);
172 // Register NewBB in its loop. In innermost loops its the same for all BB's.
173 Loop *L = State->LI->getLoopFor(State->CFG.LastBB);
174 L->addBasicBlockToLoop(NewBB, *State->LI);
175 State->CFG.PrevBB = NewBB;
176 }
177
178 // 2. Fill the IR basic block with IR instructions.
179 LLVM_DEBUG(dbgs() << "LV: vectorizing VPBB:" << getName()
180 << " in BB:" << NewBB->getName() << '\n');
181
182 State->CFG.VPBB2IRBB[this] = NewBB;
183 State->CFG.PrevVPBB = this;
184
185 for (VPRecipeBase &Recipe : Recipes)
186 Recipe.execute(*State);
187
188 LLVM_DEBUG(dbgs() << "LV: filled BB:" << *NewBB);
189 }
190
execute(VPTransformState * State)191 void VPRegionBlock::execute(VPTransformState *State) {
192 ReversePostOrderTraversal<VPBlockBase *> RPOT(Entry);
193
194 if (!isReplicator()) {
195 // Visit the VPBlocks connected to "this", starting from it.
196 for (VPBlockBase *Block : RPOT) {
197 LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n');
198 Block->execute(State);
199 }
200 return;
201 }
202
203 assert(!State->Instance && "Replicating a Region with non-null instance.");
204
205 // Enter replicating mode.
206 State->Instance = {0, 0};
207
208 for (unsigned Part = 0, UF = State->UF; Part < UF; ++Part) {
209 State->Instance->Part = Part;
210 for (unsigned Lane = 0, VF = State->VF; Lane < VF; ++Lane) {
211 State->Instance->Lane = Lane;
212 // Visit the VPBlocks connected to \p this, starting from it.
213 for (VPBlockBase *Block : RPOT) {
214 LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n');
215 Block->execute(State);
216 }
217 }
218 }
219
220 // Exit replicating mode.
221 State->Instance.reset();
222 }
223
insertBefore(VPRecipeBase * InsertPos)224 void VPRecipeBase::insertBefore(VPRecipeBase *InsertPos) {
225 Parent = InsertPos->getParent();
226 Parent->getRecipeList().insert(InsertPos->getIterator(), this);
227 }
228
eraseFromParent()229 iplist<VPRecipeBase>::iterator VPRecipeBase::eraseFromParent() {
230 return getParent()->getRecipeList().erase(getIterator());
231 }
232
generateInstruction(VPTransformState & State,unsigned Part)233 void VPInstruction::generateInstruction(VPTransformState &State,
234 unsigned Part) {
235 IRBuilder<> &Builder = State.Builder;
236
237 if (Instruction::isBinaryOp(getOpcode())) {
238 Value *A = State.get(getOperand(0), Part);
239 Value *B = State.get(getOperand(1), Part);
240 Value *V = Builder.CreateBinOp((Instruction::BinaryOps)getOpcode(), A, B);
241 State.set(this, V, Part);
242 return;
243 }
244
245 switch (getOpcode()) {
246 case VPInstruction::Not: {
247 Value *A = State.get(getOperand(0), Part);
248 Value *V = Builder.CreateNot(A);
249 State.set(this, V, Part);
250 break;
251 }
252 default:
253 llvm_unreachable("Unsupported opcode for instruction");
254 }
255 }
256
execute(VPTransformState & State)257 void VPInstruction::execute(VPTransformState &State) {
258 assert(!State.Instance && "VPInstruction executing an Instance");
259 for (unsigned Part = 0; Part < State.UF; ++Part)
260 generateInstruction(State, Part);
261 }
262
print(raw_ostream & O,const Twine & Indent) const263 void VPInstruction::print(raw_ostream &O, const Twine &Indent) const {
264 O << " +\n" << Indent << "\"EMIT ";
265 print(O);
266 O << "\\l\"";
267 }
268
print(raw_ostream & O) const269 void VPInstruction::print(raw_ostream &O) const {
270 printAsOperand(O);
271 O << " = ";
272
273 switch (getOpcode()) {
274 case VPInstruction::Not:
275 O << "not";
276 break;
277 default:
278 O << Instruction::getOpcodeName(getOpcode());
279 }
280
281 for (const VPValue *Operand : operands()) {
282 O << " ";
283 Operand->printAsOperand(O);
284 }
285 }
286
287 /// Generate the code inside the body of the vectorized loop. Assumes a single
288 /// LoopVectorBody basic-block was created for this. Introduce additional
289 /// basic-blocks as needed, and fill them all.
execute(VPTransformState * State)290 void VPlan::execute(VPTransformState *State) {
291 // 0. Set the reverse mapping from VPValues to Values for code generation.
292 for (auto &Entry : Value2VPValue)
293 State->VPValue2Value[Entry.second] = Entry.first;
294
295 BasicBlock *VectorPreHeaderBB = State->CFG.PrevBB;
296 BasicBlock *VectorHeaderBB = VectorPreHeaderBB->getSingleSuccessor();
297 assert(VectorHeaderBB && "Loop preheader does not have a single successor.");
298 BasicBlock *VectorLatchBB = VectorHeaderBB;
299
300 // 1. Make room to generate basic-blocks inside loop body if needed.
301 VectorLatchBB = VectorHeaderBB->splitBasicBlock(
302 VectorHeaderBB->getFirstInsertionPt(), "vector.body.latch");
303 Loop *L = State->LI->getLoopFor(VectorHeaderBB);
304 L->addBasicBlockToLoop(VectorLatchBB, *State->LI);
305 // Remove the edge between Header and Latch to allow other connections.
306 // Temporarily terminate with unreachable until CFG is rewired.
307 // Note: this asserts the generated code's assumption that
308 // getFirstInsertionPt() can be dereferenced into an Instruction.
309 VectorHeaderBB->getTerminator()->eraseFromParent();
310 State->Builder.SetInsertPoint(VectorHeaderBB);
311 UnreachableInst *Terminator = State->Builder.CreateUnreachable();
312 State->Builder.SetInsertPoint(Terminator);
313
314 // 2. Generate code in loop body.
315 State->CFG.PrevVPBB = nullptr;
316 State->CFG.PrevBB = VectorHeaderBB;
317 State->CFG.LastBB = VectorLatchBB;
318
319 for (VPBlockBase *Block : depth_first(Entry))
320 Block->execute(State);
321
322 // 3. Merge the temporary latch created with the last basic-block filled.
323 BasicBlock *LastBB = State->CFG.PrevBB;
324 // Connect LastBB to VectorLatchBB to facilitate their merge.
325 assert(isa<UnreachableInst>(LastBB->getTerminator()) &&
326 "Expected VPlan CFG to terminate with unreachable");
327 LastBB->getTerminator()->eraseFromParent();
328 BranchInst::Create(VectorLatchBB, LastBB);
329
330 // Merge LastBB with Latch.
331 bool Merged = MergeBlockIntoPredecessor(VectorLatchBB, nullptr, State->LI);
332 (void)Merged;
333 assert(Merged && "Could not merge last basic block with latch.");
334 VectorLatchBB = LastBB;
335
336 updateDominatorTree(State->DT, VectorPreHeaderBB, VectorLatchBB);
337 }
338
updateDominatorTree(DominatorTree * DT,BasicBlock * LoopPreHeaderBB,BasicBlock * LoopLatchBB)339 void VPlan::updateDominatorTree(DominatorTree *DT, BasicBlock *LoopPreHeaderBB,
340 BasicBlock *LoopLatchBB) {
341 BasicBlock *LoopHeaderBB = LoopPreHeaderBB->getSingleSuccessor();
342 assert(LoopHeaderBB && "Loop preheader does not have a single successor.");
343 DT->addNewBlock(LoopHeaderBB, LoopPreHeaderBB);
344 // The vector body may be more than a single basic-block by this point.
345 // Update the dominator tree information inside the vector body by propagating
346 // it from header to latch, expecting only triangular control-flow, if any.
347 BasicBlock *PostDomSucc = nullptr;
348 for (auto *BB = LoopHeaderBB; BB != LoopLatchBB; BB = PostDomSucc) {
349 // Get the list of successors of this block.
350 std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB));
351 assert(Succs.size() <= 2 &&
352 "Basic block in vector loop has more than 2 successors.");
353 PostDomSucc = Succs[0];
354 if (Succs.size() == 1) {
355 assert(PostDomSucc->getSinglePredecessor() &&
356 "PostDom successor has more than one predecessor.");
357 DT->addNewBlock(PostDomSucc, BB);
358 continue;
359 }
360 BasicBlock *InterimSucc = Succs[1];
361 if (PostDomSucc->getSingleSuccessor() == InterimSucc) {
362 PostDomSucc = Succs[1];
363 InterimSucc = Succs[0];
364 }
365 assert(InterimSucc->getSingleSuccessor() == PostDomSucc &&
366 "One successor of a basic block does not lead to the other.");
367 assert(InterimSucc->getSinglePredecessor() &&
368 "Interim successor has more than one predecessor.");
369 assert(pred_size(PostDomSucc) == 2 &&
370 "PostDom successor has more than two predecessors.");
371 DT->addNewBlock(InterimSucc, BB);
372 DT->addNewBlock(PostDomSucc, BB);
373 }
374 }
375
getUID(const VPBlockBase * Block)376 const Twine VPlanPrinter::getUID(const VPBlockBase *Block) {
377 return (isa<VPRegionBlock>(Block) ? "cluster_N" : "N") +
378 Twine(getOrCreateBID(Block));
379 }
380
getOrCreateName(const VPBlockBase * Block)381 const Twine VPlanPrinter::getOrCreateName(const VPBlockBase *Block) {
382 const std::string &Name = Block->getName();
383 if (!Name.empty())
384 return Name;
385 return "VPB" + Twine(getOrCreateBID(Block));
386 }
387
dump()388 void VPlanPrinter::dump() {
389 Depth = 1;
390 bumpIndent(0);
391 OS << "digraph VPlan {\n";
392 OS << "graph [labelloc=t, fontsize=30; label=\"Vectorization Plan";
393 if (!Plan.getName().empty())
394 OS << "\\n" << DOT::EscapeString(Plan.getName());
395 if (!Plan.Value2VPValue.empty()) {
396 OS << ", where:";
397 for (auto Entry : Plan.Value2VPValue) {
398 OS << "\\n" << *Entry.second;
399 OS << DOT::EscapeString(" := ");
400 Entry.first->printAsOperand(OS, false);
401 }
402 }
403 OS << "\"]\n";
404 OS << "node [shape=rect, fontname=Courier, fontsize=30]\n";
405 OS << "edge [fontname=Courier, fontsize=30]\n";
406 OS << "compound=true\n";
407
408 for (VPBlockBase *Block : depth_first(Plan.getEntry()))
409 dumpBlock(Block);
410
411 OS << "}\n";
412 }
413
dumpBlock(const VPBlockBase * Block)414 void VPlanPrinter::dumpBlock(const VPBlockBase *Block) {
415 if (const VPBasicBlock *BasicBlock = dyn_cast<VPBasicBlock>(Block))
416 dumpBasicBlock(BasicBlock);
417 else if (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
418 dumpRegion(Region);
419 else
420 llvm_unreachable("Unsupported kind of VPBlock.");
421 }
422
drawEdge(const VPBlockBase * From,const VPBlockBase * To,bool Hidden,const Twine & Label)423 void VPlanPrinter::drawEdge(const VPBlockBase *From, const VPBlockBase *To,
424 bool Hidden, const Twine &Label) {
425 // Due to "dot" we print an edge between two regions as an edge between the
426 // exit basic block and the entry basic of the respective regions.
427 const VPBlockBase *Tail = From->getExitBasicBlock();
428 const VPBlockBase *Head = To->getEntryBasicBlock();
429 OS << Indent << getUID(Tail) << " -> " << getUID(Head);
430 OS << " [ label=\"" << Label << '\"';
431 if (Tail != From)
432 OS << " ltail=" << getUID(From);
433 if (Head != To)
434 OS << " lhead=" << getUID(To);
435 if (Hidden)
436 OS << "; splines=none";
437 OS << "]\n";
438 }
439
dumpEdges(const VPBlockBase * Block)440 void VPlanPrinter::dumpEdges(const VPBlockBase *Block) {
441 auto &Successors = Block->getSuccessors();
442 if (Successors.size() == 1)
443 drawEdge(Block, Successors.front(), false, "");
444 else if (Successors.size() == 2) {
445 drawEdge(Block, Successors.front(), false, "T");
446 drawEdge(Block, Successors.back(), false, "F");
447 } else {
448 unsigned SuccessorNumber = 0;
449 for (auto *Successor : Successors)
450 drawEdge(Block, Successor, false, Twine(SuccessorNumber++));
451 }
452 }
453
dumpBasicBlock(const VPBasicBlock * BasicBlock)454 void VPlanPrinter::dumpBasicBlock(const VPBasicBlock *BasicBlock) {
455 OS << Indent << getUID(BasicBlock) << " [label =\n";
456 bumpIndent(1);
457 OS << Indent << "\"" << DOT::EscapeString(BasicBlock->getName()) << ":\\n\"";
458 bumpIndent(1);
459 for (const VPRecipeBase &Recipe : *BasicBlock)
460 Recipe.print(OS, Indent);
461
462 // Dump the condition bit.
463 const VPValue *CBV = BasicBlock->getCondBit();
464 if (CBV) {
465 OS << " +\n" << Indent << " \"CondBit: ";
466 if (const VPInstruction *CBI = dyn_cast<VPInstruction>(CBV)) {
467 CBI->printAsOperand(OS);
468 OS << " (" << DOT::EscapeString(CBI->getParent()->getName()) << ")\\l\"";
469 } else
470 CBV->printAsOperand(OS);
471 }
472
473 bumpIndent(-2);
474 OS << "\n" << Indent << "]\n";
475 dumpEdges(BasicBlock);
476 }
477
dumpRegion(const VPRegionBlock * Region)478 void VPlanPrinter::dumpRegion(const VPRegionBlock *Region) {
479 OS << Indent << "subgraph " << getUID(Region) << " {\n";
480 bumpIndent(1);
481 OS << Indent << "fontname=Courier\n"
482 << Indent << "label=\""
483 << DOT::EscapeString(Region->isReplicator() ? "<xVFxUF> " : "<x1> ")
484 << DOT::EscapeString(Region->getName()) << "\"\n";
485 // Dump the blocks of the region.
486 assert(Region->getEntry() && "Region contains no inner blocks.");
487 for (const VPBlockBase *Block : depth_first(Region->getEntry()))
488 dumpBlock(Block);
489 bumpIndent(-1);
490 OS << Indent << "}\n";
491 dumpEdges(Region);
492 }
493
printAsIngredient(raw_ostream & O,Value * V)494 void VPlanPrinter::printAsIngredient(raw_ostream &O, Value *V) {
495 std::string IngredientString;
496 raw_string_ostream RSO(IngredientString);
497 if (auto *Inst = dyn_cast<Instruction>(V)) {
498 if (!Inst->getType()->isVoidTy()) {
499 Inst->printAsOperand(RSO, false);
500 RSO << " = ";
501 }
502 RSO << Inst->getOpcodeName() << " ";
503 unsigned E = Inst->getNumOperands();
504 if (E > 0) {
505 Inst->getOperand(0)->printAsOperand(RSO, false);
506 for (unsigned I = 1; I < E; ++I)
507 Inst->getOperand(I)->printAsOperand(RSO << ", ", false);
508 }
509 } else // !Inst
510 V->printAsOperand(RSO, false);
511 RSO.flush();
512 O << DOT::EscapeString(IngredientString);
513 }
514
print(raw_ostream & O,const Twine & Indent) const515 void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent) const {
516 O << " +\n" << Indent << "\"WIDEN\\l\"";
517 for (auto &Instr : make_range(Begin, End))
518 O << " +\n" << Indent << "\" " << VPlanIngredient(&Instr) << "\\l\"";
519 }
520
print(raw_ostream & O,const Twine & Indent) const521 void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O,
522 const Twine &Indent) const {
523 O << " +\n" << Indent << "\"WIDEN-INDUCTION";
524 if (Trunc) {
525 O << "\\l\"";
526 O << " +\n" << Indent << "\" " << VPlanIngredient(IV) << "\\l\"";
527 O << " +\n" << Indent << "\" " << VPlanIngredient(Trunc) << "\\l\"";
528 } else
529 O << " " << VPlanIngredient(IV) << "\\l\"";
530 }
531
print(raw_ostream & O,const Twine & Indent) const532 void VPWidenPHIRecipe::print(raw_ostream &O, const Twine &Indent) const {
533 O << " +\n" << Indent << "\"WIDEN-PHI " << VPlanIngredient(Phi) << "\\l\"";
534 }
535
print(raw_ostream & O,const Twine & Indent) const536 void VPBlendRecipe::print(raw_ostream &O, const Twine &Indent) const {
537 O << " +\n" << Indent << "\"BLEND ";
538 Phi->printAsOperand(O, false);
539 O << " =";
540 if (!User) {
541 // Not a User of any mask: not really blending, this is a
542 // single-predecessor phi.
543 O << " ";
544 Phi->getIncomingValue(0)->printAsOperand(O, false);
545 } else {
546 for (unsigned I = 0, E = User->getNumOperands(); I < E; ++I) {
547 O << " ";
548 Phi->getIncomingValue(I)->printAsOperand(O, false);
549 O << "/";
550 User->getOperand(I)->printAsOperand(O);
551 }
552 }
553 O << "\\l\"";
554 }
555
print(raw_ostream & O,const Twine & Indent) const556 void VPReplicateRecipe::print(raw_ostream &O, const Twine &Indent) const {
557 O << " +\n"
558 << Indent << "\"" << (IsUniform ? "CLONE " : "REPLICATE ")
559 << VPlanIngredient(Ingredient);
560 if (AlsoPack)
561 O << " (S->V)";
562 O << "\\l\"";
563 }
564
print(raw_ostream & O,const Twine & Indent) const565 void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent) const {
566 O << " +\n"
567 << Indent << "\"PHI-PREDICATED-INSTRUCTION " << VPlanIngredient(PredInst)
568 << "\\l\"";
569 }
570
print(raw_ostream & O,const Twine & Indent) const571 void VPWidenMemoryInstructionRecipe::print(raw_ostream &O,
572 const Twine &Indent) const {
573 O << " +\n" << Indent << "\"WIDEN " << VPlanIngredient(&Instr);
574 if (User) {
575 O << ", ";
576 User->getOperand(0)->printAsOperand(O);
577 }
578 O << "\\l\"";
579 }
580
581 template void DomTreeBuilder::Calculate<VPDominatorTree>(VPDominatorTree &DT);
582