blob: 1f58bed5257db162bc9a7bb270d22429205dc3ee [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) {
Florian Hahn3bcff362018-06-18 13:51:28 +0000224 Parent = InsertPos->getParent();
225 Parent->getRecipeList().insert(InsertPos->getIterator(), this);
Florian Hahn7591e4e2018-06-18 11:34:17 +0000226}
227
Florian Hahn63cbcf92018-06-18 15:18:48 +0000228iplist<VPRecipeBase>::iterator VPRecipeBase::eraseFromParent() {
229 return getParent()->getRecipeList().erase(getIterator());
230}
231
Gil Rapaport8b9d1f32017-11-20 12:01:47 +0000232void VPInstruction::generateInstruction(VPTransformState &State,
233 unsigned Part) {
234 IRBuilder<> &Builder = State.Builder;
235
236 if (Instruction::isBinaryOp(getOpcode())) {
237 Value *A = State.get(getOperand(0), Part);
238 Value *B = State.get(getOperand(1), Part);
239 Value *V = Builder.CreateBinOp((Instruction::BinaryOps)getOpcode(), A, B);
240 State.set(this, V, Part);
241 return;
242 }
243
244 switch (getOpcode()) {
245 case VPInstruction::Not: {
246 Value *A = State.get(getOperand(0), Part);
247 Value *V = Builder.CreateNot(A);
248 State.set(this, V, Part);
249 break;
250 }
251 default:
252 llvm_unreachable("Unsupported opcode for instruction");
253 }
254}
255
256void VPInstruction::execute(VPTransformState &State) {
257 assert(!State.Instance && "VPInstruction executing an Instance");
258 for (unsigned Part = 0; Part < State.UF; ++Part)
259 generateInstruction(State, Part);
260}
261
262void VPInstruction::print(raw_ostream &O, const Twine &Indent) const {
263 O << " +\n" << Indent << "\"EMIT ";
264 print(O);
265 O << "\\l\"";
266}
267
268void VPInstruction::print(raw_ostream &O) const {
269 printAsOperand(O);
270 O << " = ";
271
272 switch (getOpcode()) {
273 case VPInstruction::Not:
274 O << "not";
275 break;
276 default:
277 O << Instruction::getOpcodeName(getOpcode());
278 }
279
280 for (const VPValue *Operand : operands()) {
281 O << " ";
282 Operand->printAsOperand(O);
283 }
284}
285
Ayal Zaks1f58dda2017-08-27 12:55:46 +0000286/// Generate the code inside the body of the vectorized loop. Assumes a single
287/// LoopVectorBody basic-block was created for this. Introduce additional
288/// basic-blocks as needed, and fill them all.
289void VPlan::execute(VPTransformState *State) {
Gil Rapaport8b9d1f32017-11-20 12:01:47 +0000290 // 0. Set the reverse mapping from VPValues to Values for code generation.
291 for (auto &Entry : Value2VPValue)
292 State->VPValue2Value[Entry.second] = Entry.first;
293
Ayal Zaks1f58dda2017-08-27 12:55:46 +0000294 BasicBlock *VectorPreHeaderBB = State->CFG.PrevBB;
295 BasicBlock *VectorHeaderBB = VectorPreHeaderBB->getSingleSuccessor();
296 assert(VectorHeaderBB && "Loop preheader does not have a single successor.");
297 BasicBlock *VectorLatchBB = VectorHeaderBB;
298
299 // 1. Make room to generate basic-blocks inside loop body if needed.
300 VectorLatchBB = VectorHeaderBB->splitBasicBlock(
301 VectorHeaderBB->getFirstInsertionPt(), "vector.body.latch");
302 Loop *L = State->LI->getLoopFor(VectorHeaderBB);
303 L->addBasicBlockToLoop(VectorLatchBB, *State->LI);
304 // Remove the edge between Header and Latch to allow other connections.
305 // Temporarily terminate with unreachable until CFG is rewired.
306 // Note: this asserts the generated code's assumption that
307 // getFirstInsertionPt() can be dereferenced into an Instruction.
308 VectorHeaderBB->getTerminator()->eraseFromParent();
309 State->Builder.SetInsertPoint(VectorHeaderBB);
310 UnreachableInst *Terminator = State->Builder.CreateUnreachable();
311 State->Builder.SetInsertPoint(Terminator);
312
313 // 2. Generate code in loop body.
314 State->CFG.PrevVPBB = nullptr;
315 State->CFG.PrevBB = VectorHeaderBB;
316 State->CFG.LastBB = VectorLatchBB;
317
318 for (VPBlockBase *Block : depth_first(Entry))
319 Block->execute(State);
320
321 // 3. Merge the temporary latch created with the last basic-block filled.
322 BasicBlock *LastBB = State->CFG.PrevBB;
323 // Connect LastBB to VectorLatchBB to facilitate their merge.
324 assert(isa<UnreachableInst>(LastBB->getTerminator()) &&
325 "Expected VPlan CFG to terminate with unreachable");
326 LastBB->getTerminator()->eraseFromParent();
327 BranchInst::Create(VectorLatchBB, LastBB);
328
329 // Merge LastBB with Latch.
330 bool Merged = MergeBlockIntoPredecessor(VectorLatchBB, nullptr, State->LI);
331 (void)Merged;
332 assert(Merged && "Could not merge last basic block with latch.");
333 VectorLatchBB = LastBB;
334
335 updateDominatorTree(State->DT, VectorPreHeaderBB, VectorLatchBB);
336}
337
338void VPlan::updateDominatorTree(DominatorTree *DT, BasicBlock *LoopPreHeaderBB,
339 BasicBlock *LoopLatchBB) {
340 BasicBlock *LoopHeaderBB = LoopPreHeaderBB->getSingleSuccessor();
341 assert(LoopHeaderBB && "Loop preheader does not have a single successor.");
342 DT->addNewBlock(LoopHeaderBB, LoopPreHeaderBB);
343 // The vector body may be more than a single basic-block by this point.
344 // Update the dominator tree information inside the vector body by propagating
345 // it from header to latch, expecting only triangular control-flow, if any.
346 BasicBlock *PostDomSucc = nullptr;
347 for (auto *BB = LoopHeaderBB; BB != LoopLatchBB; BB = PostDomSucc) {
348 // Get the list of successors of this block.
349 std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB));
350 assert(Succs.size() <= 2 &&
351 "Basic block in vector loop has more than 2 successors.");
352 PostDomSucc = Succs[0];
353 if (Succs.size() == 1) {
354 assert(PostDomSucc->getSinglePredecessor() &&
355 "PostDom successor has more than one predecessor.");
356 DT->addNewBlock(PostDomSucc, BB);
357 continue;
358 }
359 BasicBlock *InterimSucc = Succs[1];
360 if (PostDomSucc->getSingleSuccessor() == InterimSucc) {
361 PostDomSucc = Succs[1];
362 InterimSucc = Succs[0];
363 }
364 assert(InterimSucc->getSingleSuccessor() == PostDomSucc &&
365 "One successor of a basic block does not lead to the other.");
366 assert(InterimSucc->getSinglePredecessor() &&
367 "Interim successor has more than one predecessor.");
Vedant Kumare0b5f862018-05-10 23:01:54 +0000368 assert(pred_size(PostDomSucc) == 2 &&
Ayal Zaks1f58dda2017-08-27 12:55:46 +0000369 "PostDom successor has more than two predecessors.");
370 DT->addNewBlock(InterimSucc, BB);
371 DT->addNewBlock(PostDomSucc, BB);
372 }
373}
374
375const Twine VPlanPrinter::getUID(const VPBlockBase *Block) {
376 return (isa<VPRegionBlock>(Block) ? "cluster_N" : "N") +
377 Twine(getOrCreateBID(Block));
378}
379
380const Twine VPlanPrinter::getOrCreateName(const VPBlockBase *Block) {
381 const std::string &Name = Block->getName();
382 if (!Name.empty())
383 return Name;
384 return "VPB" + Twine(getOrCreateBID(Block));
385}
386
387void VPlanPrinter::dump() {
388 Depth = 1;
389 bumpIndent(0);
390 OS << "digraph VPlan {\n";
391 OS << "graph [labelloc=t, fontsize=30; label=\"Vectorization Plan";
392 if (!Plan.getName().empty())
393 OS << "\\n" << DOT::EscapeString(Plan.getName());
Gil Rapaport8b9d1f32017-11-20 12:01:47 +0000394 if (!Plan.Value2VPValue.empty()) {
395 OS << ", where:";
396 for (auto Entry : Plan.Value2VPValue) {
397 OS << "\\n" << *Entry.second;
398 OS << DOT::EscapeString(" := ");
399 Entry.first->printAsOperand(OS, false);
400 }
401 }
Ayal Zaks1f58dda2017-08-27 12:55:46 +0000402 OS << "\"]\n";
403 OS << "node [shape=rect, fontname=Courier, fontsize=30]\n";
404 OS << "edge [fontname=Courier, fontsize=30]\n";
405 OS << "compound=true\n";
406
407 for (VPBlockBase *Block : depth_first(Plan.getEntry()))
408 dumpBlock(Block);
409
410 OS << "}\n";
411}
412
413void VPlanPrinter::dumpBlock(const VPBlockBase *Block) {
414 if (const VPBasicBlock *BasicBlock = dyn_cast<VPBasicBlock>(Block))
415 dumpBasicBlock(BasicBlock);
416 else if (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
417 dumpRegion(Region);
418 else
419 llvm_unreachable("Unsupported kind of VPBlock.");
420}
421
422void VPlanPrinter::drawEdge(const VPBlockBase *From, const VPBlockBase *To,
423 bool Hidden, const Twine &Label) {
424 // Due to "dot" we print an edge between two regions as an edge between the
425 // exit basic block and the entry basic of the respective regions.
426 const VPBlockBase *Tail = From->getExitBasicBlock();
427 const VPBlockBase *Head = To->getEntryBasicBlock();
428 OS << Indent << getUID(Tail) << " -> " << getUID(Head);
429 OS << " [ label=\"" << Label << '\"';
430 if (Tail != From)
431 OS << " ltail=" << getUID(From);
432 if (Head != To)
433 OS << " lhead=" << getUID(To);
434 if (Hidden)
435 OS << "; splines=none";
436 OS << "]\n";
437}
438
439void VPlanPrinter::dumpEdges(const VPBlockBase *Block) {
440 auto &Successors = Block->getSuccessors();
441 if (Successors.size() == 1)
442 drawEdge(Block, Successors.front(), false, "");
443 else if (Successors.size() == 2) {
444 drawEdge(Block, Successors.front(), false, "T");
445 drawEdge(Block, Successors.back(), false, "F");
446 } else {
447 unsigned SuccessorNumber = 0;
448 for (auto *Successor : Successors)
449 drawEdge(Block, Successor, false, Twine(SuccessorNumber++));
450 }
451}
452
453void VPlanPrinter::dumpBasicBlock(const VPBasicBlock *BasicBlock) {
454 OS << Indent << getUID(BasicBlock) << " [label =\n";
455 bumpIndent(1);
456 OS << Indent << "\"" << DOT::EscapeString(BasicBlock->getName()) << ":\\n\"";
457 bumpIndent(1);
458 for (const VPRecipeBase &Recipe : *BasicBlock)
459 Recipe.print(OS, Indent);
460 bumpIndent(-2);
461 OS << "\n" << Indent << "]\n";
462 dumpEdges(BasicBlock);
463}
464
465void VPlanPrinter::dumpRegion(const VPRegionBlock *Region) {
466 OS << Indent << "subgraph " << getUID(Region) << " {\n";
467 bumpIndent(1);
468 OS << Indent << "fontname=Courier\n"
469 << Indent << "label=\""
470 << DOT::EscapeString(Region->isReplicator() ? "<xVFxUF> " : "<x1> ")
471 << DOT::EscapeString(Region->getName()) << "\"\n";
472 // Dump the blocks of the region.
473 assert(Region->getEntry() && "Region contains no inner blocks.");
474 for (const VPBlockBase *Block : depth_first(Region->getEntry()))
475 dumpBlock(Block);
476 bumpIndent(-1);
477 OS << Indent << "}\n";
478 dumpEdges(Region);
479}
480
481void VPlanPrinter::printAsIngredient(raw_ostream &O, Value *V) {
482 std::string IngredientString;
483 raw_string_ostream RSO(IngredientString);
484 if (auto *Inst = dyn_cast<Instruction>(V)) {
485 if (!Inst->getType()->isVoidTy()) {
486 Inst->printAsOperand(RSO, false);
487 RSO << " = ";
488 }
489 RSO << Inst->getOpcodeName() << " ";
490 unsigned E = Inst->getNumOperands();
491 if (E > 0) {
492 Inst->getOperand(0)->printAsOperand(RSO, false);
493 for (unsigned I = 1; I < E; ++I)
494 Inst->getOperand(I)->printAsOperand(RSO << ", ", false);
495 }
496 } else // !Inst
497 V->printAsOperand(RSO, false);
498 RSO.flush();
499 O << DOT::EscapeString(IngredientString);
500}
Hal Finkel7333aa92017-12-16 01:12:50 +0000501
502void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent) const {
503 O << " +\n" << Indent << "\"WIDEN\\l\"";
504 for (auto &Instr : make_range(Begin, End))
505 O << " +\n" << Indent << "\" " << VPlanIngredient(&Instr) << "\\l\"";
506}
507
508void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O,
509 const Twine &Indent) const {
510 O << " +\n" << Indent << "\"WIDEN-INDUCTION";
511 if (Trunc) {
512 O << "\\l\"";
513 O << " +\n" << Indent << "\" " << VPlanIngredient(IV) << "\\l\"";
514 O << " +\n" << Indent << "\" " << VPlanIngredient(Trunc) << "\\l\"";
515 } else
516 O << " " << VPlanIngredient(IV) << "\\l\"";
517}
518
519void VPWidenPHIRecipe::print(raw_ostream &O, const Twine &Indent) const {
520 O << " +\n" << Indent << "\"WIDEN-PHI " << VPlanIngredient(Phi) << "\\l\"";
521}
522
523void VPBlendRecipe::print(raw_ostream &O, const Twine &Indent) const {
524 O << " +\n" << Indent << "\"BLEND ";
525 Phi->printAsOperand(O, false);
526 O << " =";
527 if (!User) {
528 // Not a User of any mask: not really blending, this is a
529 // single-predecessor phi.
530 O << " ";
531 Phi->getIncomingValue(0)->printAsOperand(O, false);
532 } else {
533 for (unsigned I = 0, E = User->getNumOperands(); I < E; ++I) {
534 O << " ";
535 Phi->getIncomingValue(I)->printAsOperand(O, false);
536 O << "/";
537 User->getOperand(I)->printAsOperand(O);
538 }
539 }
540 O << "\\l\"";
541}
542
543void VPReplicateRecipe::print(raw_ostream &O, const Twine &Indent) const {
544 O << " +\n"
545 << Indent << "\"" << (IsUniform ? "CLONE " : "REPLICATE ")
546 << VPlanIngredient(Ingredient);
547 if (AlsoPack)
548 O << " (S->V)";
549 O << "\\l\"";
550}
551
552void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent) const {
553 O << " +\n"
554 << Indent << "\"PHI-PREDICATED-INSTRUCTION " << VPlanIngredient(PredInst)
555 << "\\l\"";
556}
557
558void VPWidenMemoryInstructionRecipe::print(raw_ostream &O,
559 const Twine &Indent) const {
560 O << " +\n" << Indent << "\"WIDEN " << VPlanIngredient(&Instr);
561 if (User) {
562 O << ", ";
563 User->getOperand(0)->printAsOperand(O);
564 }
565 O << "\\l\"";
566}