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