12cab237bSDimitry Andric //===- VPlan.cpp - Vectorizer Plan ----------------------------------------===//
22cab237bSDimitry Andric //
32cab237bSDimitry Andric // The LLVM Compiler Infrastructure
42cab237bSDimitry Andric //
52cab237bSDimitry Andric // This file is distributed under the University of Illinois Open Source
62cab237bSDimitry Andric // License. See LICENSE.TXT for details.
72cab237bSDimitry Andric //
82cab237bSDimitry Andric //===----------------------------------------------------------------------===//
92cab237bSDimitry Andric ///
102cab237bSDimitry Andric /// \file
112cab237bSDimitry Andric /// This is the LLVM vectorization plan. It represents a candidate for
122cab237bSDimitry Andric /// vectorization, allowing to plan and optimize how to vectorize a given loop
132cab237bSDimitry Andric /// before generating LLVM-IR.
142cab237bSDimitry Andric /// The vectorizer uses vectorization plans to estimate the costs of potential
152cab237bSDimitry Andric /// candidates and if profitable to execute the desired plan, generating vector
162cab237bSDimitry Andric /// LLVM-IR code.
172cab237bSDimitry Andric ///
182cab237bSDimitry Andric //===----------------------------------------------------------------------===//
192cab237bSDimitry Andric
202cab237bSDimitry Andric #include "VPlan.h"
214ba319b5SDimitry Andric #include "VPlanDominatorTree.h"
222cab237bSDimitry Andric #include "llvm/ADT/DepthFirstIterator.h"
232cab237bSDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
242cab237bSDimitry Andric #include "llvm/ADT/SmallVector.h"
252cab237bSDimitry Andric #include "llvm/ADT/Twine.h"
262cab237bSDimitry Andric #include "llvm/Analysis/LoopInfo.h"
272cab237bSDimitry Andric #include "llvm/IR/BasicBlock.h"
282cab237bSDimitry Andric #include "llvm/IR/CFG.h"
292cab237bSDimitry Andric #include "llvm/IR/InstrTypes.h"
302cab237bSDimitry Andric #include "llvm/IR/Instruction.h"
312cab237bSDimitry Andric #include "llvm/IR/Instructions.h"
322cab237bSDimitry Andric #include "llvm/IR/Type.h"
332cab237bSDimitry Andric #include "llvm/IR/Value.h"
342cab237bSDimitry Andric #include "llvm/Support/Casting.h"
352cab237bSDimitry Andric #include "llvm/Support/Debug.h"
362cab237bSDimitry Andric #include "llvm/Support/ErrorHandling.h"
374ba319b5SDimitry Andric #include "llvm/Support/GenericDomTreeConstruction.h"
382cab237bSDimitry Andric #include "llvm/Support/GraphWriter.h"
392cab237bSDimitry Andric #include "llvm/Support/raw_ostream.h"
402cab237bSDimitry Andric #include "llvm/Transforms/Utils/BasicBlockUtils.h"
412cab237bSDimitry Andric #include <cassert>
422cab237bSDimitry Andric #include <iterator>
432cab237bSDimitry Andric #include <string>
442cab237bSDimitry Andric #include <vector>
452cab237bSDimitry Andric
462cab237bSDimitry Andric using namespace llvm;
47*b5893f02SDimitry Andric extern cl::opt<bool> EnableVPlanNativePath;
482cab237bSDimitry Andric
492cab237bSDimitry Andric #define DEBUG_TYPE "vplan"
502cab237bSDimitry Andric
operator <<(raw_ostream & OS,const VPValue & V)512cab237bSDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const VPValue &V) {
522cab237bSDimitry Andric if (const VPInstruction *Instr = dyn_cast<VPInstruction>(&V))
532cab237bSDimitry Andric Instr->print(OS);
542cab237bSDimitry Andric else
552cab237bSDimitry Andric V.printAsOperand(OS);
562cab237bSDimitry Andric return OS;
572cab237bSDimitry Andric }
582cab237bSDimitry Andric
592cab237bSDimitry Andric /// \return the VPBasicBlock that is the entry of Block, possibly indirectly.
getEntryBasicBlock() const602cab237bSDimitry Andric const VPBasicBlock *VPBlockBase::getEntryBasicBlock() const {
612cab237bSDimitry Andric const VPBlockBase *Block = this;
622cab237bSDimitry Andric while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
632cab237bSDimitry Andric Block = Region->getEntry();
642cab237bSDimitry Andric return cast<VPBasicBlock>(Block);
652cab237bSDimitry Andric }
662cab237bSDimitry Andric
getEntryBasicBlock()672cab237bSDimitry Andric VPBasicBlock *VPBlockBase::getEntryBasicBlock() {
682cab237bSDimitry Andric VPBlockBase *Block = this;
692cab237bSDimitry Andric while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
702cab237bSDimitry Andric Block = Region->getEntry();
712cab237bSDimitry Andric return cast<VPBasicBlock>(Block);
722cab237bSDimitry Andric }
732cab237bSDimitry Andric
742cab237bSDimitry Andric /// \return the VPBasicBlock that is the exit of Block, possibly indirectly.
getExitBasicBlock() const752cab237bSDimitry Andric const VPBasicBlock *VPBlockBase::getExitBasicBlock() const {
762cab237bSDimitry Andric const VPBlockBase *Block = this;
772cab237bSDimitry Andric while (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
782cab237bSDimitry Andric Block = Region->getExit();
792cab237bSDimitry Andric return cast<VPBasicBlock>(Block);
802cab237bSDimitry Andric }
812cab237bSDimitry Andric
getExitBasicBlock()822cab237bSDimitry Andric VPBasicBlock *VPBlockBase::getExitBasicBlock() {
832cab237bSDimitry Andric VPBlockBase *Block = this;
842cab237bSDimitry Andric while (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
852cab237bSDimitry Andric Block = Region->getExit();
862cab237bSDimitry Andric return cast<VPBasicBlock>(Block);
872cab237bSDimitry Andric }
882cab237bSDimitry Andric
getEnclosingBlockWithSuccessors()892cab237bSDimitry Andric VPBlockBase *VPBlockBase::getEnclosingBlockWithSuccessors() {
902cab237bSDimitry Andric if (!Successors.empty() || !Parent)
912cab237bSDimitry Andric return this;
922cab237bSDimitry Andric assert(Parent->getExit() == this &&
932cab237bSDimitry Andric "Block w/o successors not the exit of its parent.");
942cab237bSDimitry Andric return Parent->getEnclosingBlockWithSuccessors();
952cab237bSDimitry Andric }
962cab237bSDimitry Andric
getEnclosingBlockWithPredecessors()972cab237bSDimitry Andric VPBlockBase *VPBlockBase::getEnclosingBlockWithPredecessors() {
982cab237bSDimitry Andric if (!Predecessors.empty() || !Parent)
992cab237bSDimitry Andric return this;
1002cab237bSDimitry Andric assert(Parent->getEntry() == this &&
1012cab237bSDimitry Andric "Block w/o predecessors not the entry of its parent.");
1022cab237bSDimitry Andric return Parent->getEnclosingBlockWithPredecessors();
1032cab237bSDimitry Andric }
1042cab237bSDimitry Andric
deleteCFG(VPBlockBase * Entry)1052cab237bSDimitry Andric void VPBlockBase::deleteCFG(VPBlockBase *Entry) {
1062cab237bSDimitry Andric SmallVector<VPBlockBase *, 8> Blocks;
1072cab237bSDimitry Andric for (VPBlockBase *Block : depth_first(Entry))
1082cab237bSDimitry Andric Blocks.push_back(Block);
1092cab237bSDimitry Andric
1102cab237bSDimitry Andric for (VPBlockBase *Block : Blocks)
1112cab237bSDimitry Andric delete Block;
1122cab237bSDimitry Andric }
1132cab237bSDimitry Andric
1142cab237bSDimitry Andric BasicBlock *
createEmptyBasicBlock(VPTransformState::CFGState & CFG)1152cab237bSDimitry Andric VPBasicBlock::createEmptyBasicBlock(VPTransformState::CFGState &CFG) {
1162cab237bSDimitry Andric // BB stands for IR BasicBlocks. VPBB stands for VPlan VPBasicBlocks.
1172cab237bSDimitry Andric // Pred stands for Predessor. Prev stands for Previous - last visited/created.
1182cab237bSDimitry Andric BasicBlock *PrevBB = CFG.PrevBB;
1192cab237bSDimitry Andric BasicBlock *NewBB = BasicBlock::Create(PrevBB->getContext(), getName(),
1202cab237bSDimitry Andric PrevBB->getParent(), CFG.LastBB);
1214ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: created " << NewBB->getName() << '\n');
1222cab237bSDimitry Andric
1232cab237bSDimitry Andric // Hook up the new basic block to its predecessors.
1242cab237bSDimitry Andric for (VPBlockBase *PredVPBlock : getHierarchicalPredecessors()) {
1252cab237bSDimitry Andric VPBasicBlock *PredVPBB = PredVPBlock->getExitBasicBlock();
1262cab237bSDimitry Andric auto &PredVPSuccessors = PredVPBB->getSuccessors();
1272cab237bSDimitry Andric BasicBlock *PredBB = CFG.VPBB2IRBB[PredVPBB];
128*b5893f02SDimitry Andric
129*b5893f02SDimitry Andric // In outer loop vectorization scenario, the predecessor BBlock may not yet
130*b5893f02SDimitry Andric // be visited(backedge). Mark the VPBasicBlock for fixup at the end of
131*b5893f02SDimitry Andric // vectorization. We do not encounter this case in inner loop vectorization
132*b5893f02SDimitry Andric // as we start out by building a loop skeleton with the vector loop header
133*b5893f02SDimitry Andric // and latch blocks. As a result, we never enter this function for the
134*b5893f02SDimitry Andric // header block in the non VPlan-native path.
135*b5893f02SDimitry Andric if (!PredBB) {
136*b5893f02SDimitry Andric assert(EnableVPlanNativePath &&
137*b5893f02SDimitry Andric "Unexpected null predecessor in non VPlan-native path");
138*b5893f02SDimitry Andric CFG.VPBBsToFix.push_back(PredVPBB);
139*b5893f02SDimitry Andric continue;
140*b5893f02SDimitry Andric }
141*b5893f02SDimitry Andric
1422cab237bSDimitry Andric assert(PredBB && "Predecessor basic-block not found building successor.");
1432cab237bSDimitry Andric auto *PredBBTerminator = PredBB->getTerminator();
1444ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: draw edge from" << PredBB->getName() << '\n');
1452cab237bSDimitry Andric if (isa<UnreachableInst>(PredBBTerminator)) {
1462cab237bSDimitry Andric assert(PredVPSuccessors.size() == 1 &&
1472cab237bSDimitry Andric "Predecessor ending w/o branch must have single successor.");
1482cab237bSDimitry Andric PredBBTerminator->eraseFromParent();
1492cab237bSDimitry Andric BranchInst::Create(NewBB, PredBB);
1502cab237bSDimitry Andric } else {
1512cab237bSDimitry Andric assert(PredVPSuccessors.size() == 2 &&
1522cab237bSDimitry Andric "Predecessor ending with branch must have two successors.");
1532cab237bSDimitry Andric unsigned idx = PredVPSuccessors.front() == this ? 0 : 1;
1542cab237bSDimitry Andric assert(!PredBBTerminator->getSuccessor(idx) &&
1552cab237bSDimitry Andric "Trying to reset an existing successor block.");
1562cab237bSDimitry Andric PredBBTerminator->setSuccessor(idx, NewBB);
1572cab237bSDimitry Andric }
1582cab237bSDimitry Andric }
1592cab237bSDimitry Andric return NewBB;
1602cab237bSDimitry Andric }
1612cab237bSDimitry Andric
execute(VPTransformState * State)1622cab237bSDimitry Andric void VPBasicBlock::execute(VPTransformState *State) {
1632cab237bSDimitry Andric bool Replica = State->Instance &&
1642cab237bSDimitry Andric !(State->Instance->Part == 0 && State->Instance->Lane == 0);
1652cab237bSDimitry Andric VPBasicBlock *PrevVPBB = State->CFG.PrevVPBB;
1662cab237bSDimitry Andric VPBlockBase *SingleHPred = nullptr;
1672cab237bSDimitry Andric BasicBlock *NewBB = State->CFG.PrevBB; // Reuse it if possible.
1682cab237bSDimitry Andric
1692cab237bSDimitry Andric // 1. Create an IR basic block, or reuse the last one if possible.
1702cab237bSDimitry Andric // The last IR basic block is reused, as an optimization, in three cases:
1712cab237bSDimitry Andric // A. the first VPBB reuses the loop header BB - when PrevVPBB is null;
1722cab237bSDimitry Andric // B. when the current VPBB has a single (hierarchical) predecessor which
1732cab237bSDimitry Andric // is PrevVPBB and the latter has a single (hierarchical) successor; and
1742cab237bSDimitry Andric // C. when the current VPBB is an entry of a region replica - where PrevVPBB
1752cab237bSDimitry Andric // is the exit of this region from a previous instance, or the predecessor
1762cab237bSDimitry Andric // of this region.
1772cab237bSDimitry Andric if (PrevVPBB && /* A */
1782cab237bSDimitry Andric !((SingleHPred = getSingleHierarchicalPredecessor()) &&
1792cab237bSDimitry Andric SingleHPred->getExitBasicBlock() == PrevVPBB &&
1802cab237bSDimitry Andric PrevVPBB->getSingleHierarchicalSuccessor()) && /* B */
1812cab237bSDimitry Andric !(Replica && getPredecessors().empty())) { /* C */
1822cab237bSDimitry Andric NewBB = createEmptyBasicBlock(State->CFG);
1832cab237bSDimitry Andric State->Builder.SetInsertPoint(NewBB);
1842cab237bSDimitry Andric // Temporarily terminate with unreachable until CFG is rewired.
1852cab237bSDimitry Andric UnreachableInst *Terminator = State->Builder.CreateUnreachable();
1862cab237bSDimitry Andric State->Builder.SetInsertPoint(Terminator);
1872cab237bSDimitry Andric // Register NewBB in its loop. In innermost loops its the same for all BB's.
1882cab237bSDimitry Andric Loop *L = State->LI->getLoopFor(State->CFG.LastBB);
1892cab237bSDimitry Andric L->addBasicBlockToLoop(NewBB, *State->LI);
1902cab237bSDimitry Andric State->CFG.PrevBB = NewBB;
1912cab237bSDimitry Andric }
1922cab237bSDimitry Andric
1932cab237bSDimitry Andric // 2. Fill the IR basic block with IR instructions.
1944ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: vectorizing VPBB:" << getName()
1952cab237bSDimitry Andric << " in BB:" << NewBB->getName() << '\n');
1962cab237bSDimitry Andric
1972cab237bSDimitry Andric State->CFG.VPBB2IRBB[this] = NewBB;
1982cab237bSDimitry Andric State->CFG.PrevVPBB = this;
1992cab237bSDimitry Andric
2002cab237bSDimitry Andric for (VPRecipeBase &Recipe : Recipes)
2012cab237bSDimitry Andric Recipe.execute(*State);
2022cab237bSDimitry Andric
203*b5893f02SDimitry Andric VPValue *CBV;
204*b5893f02SDimitry Andric if (EnableVPlanNativePath && (CBV = getCondBit())) {
205*b5893f02SDimitry Andric Value *IRCBV = CBV->getUnderlyingValue();
206*b5893f02SDimitry Andric assert(IRCBV && "Unexpected null underlying value for condition bit");
207*b5893f02SDimitry Andric
208*b5893f02SDimitry Andric // Condition bit value in a VPBasicBlock is used as the branch selector. In
209*b5893f02SDimitry Andric // the VPlan-native path case, since all branches are uniform we generate a
210*b5893f02SDimitry Andric // branch instruction using the condition value from vector lane 0 and dummy
211*b5893f02SDimitry Andric // successors. The successors are fixed later when the successor blocks are
212*b5893f02SDimitry Andric // visited.
213*b5893f02SDimitry Andric Value *NewCond = State->Callback.getOrCreateVectorValues(IRCBV, 0);
214*b5893f02SDimitry Andric NewCond = State->Builder.CreateExtractElement(NewCond,
215*b5893f02SDimitry Andric State->Builder.getInt32(0));
216*b5893f02SDimitry Andric
217*b5893f02SDimitry Andric // Replace the temporary unreachable terminator with the new conditional
218*b5893f02SDimitry Andric // branch.
219*b5893f02SDimitry Andric auto *CurrentTerminator = NewBB->getTerminator();
220*b5893f02SDimitry Andric assert(isa<UnreachableInst>(CurrentTerminator) &&
221*b5893f02SDimitry Andric "Expected to replace unreachable terminator with conditional "
222*b5893f02SDimitry Andric "branch.");
223*b5893f02SDimitry Andric auto *CondBr = BranchInst::Create(NewBB, nullptr, NewCond);
224*b5893f02SDimitry Andric CondBr->setSuccessor(0, nullptr);
225*b5893f02SDimitry Andric ReplaceInstWithInst(CurrentTerminator, CondBr);
226*b5893f02SDimitry Andric }
227*b5893f02SDimitry Andric
2284ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: filled BB:" << *NewBB);
2292cab237bSDimitry Andric }
2302cab237bSDimitry Andric
execute(VPTransformState * State)2312cab237bSDimitry Andric void VPRegionBlock::execute(VPTransformState *State) {
2322cab237bSDimitry Andric ReversePostOrderTraversal<VPBlockBase *> RPOT(Entry);
2332cab237bSDimitry Andric
2342cab237bSDimitry Andric if (!isReplicator()) {
2352cab237bSDimitry Andric // Visit the VPBlocks connected to "this", starting from it.
2362cab237bSDimitry Andric for (VPBlockBase *Block : RPOT) {
237*b5893f02SDimitry Andric if (EnableVPlanNativePath) {
238*b5893f02SDimitry Andric // The inner loop vectorization path does not represent loop preheader
239*b5893f02SDimitry Andric // and exit blocks as part of the VPlan. In the VPlan-native path, skip
240*b5893f02SDimitry Andric // vectorizing loop preheader block. In future, we may replace this
241*b5893f02SDimitry Andric // check with the check for loop preheader.
242*b5893f02SDimitry Andric if (Block->getNumPredecessors() == 0)
243*b5893f02SDimitry Andric continue;
244*b5893f02SDimitry Andric
245*b5893f02SDimitry Andric // Skip vectorizing loop exit block. In future, we may replace this
246*b5893f02SDimitry Andric // check with the check for loop exit.
247*b5893f02SDimitry Andric if (Block->getNumSuccessors() == 0)
248*b5893f02SDimitry Andric continue;
249*b5893f02SDimitry Andric }
250*b5893f02SDimitry Andric
2514ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n');
2522cab237bSDimitry Andric Block->execute(State);
2532cab237bSDimitry Andric }
2542cab237bSDimitry Andric return;
2552cab237bSDimitry Andric }
2562cab237bSDimitry Andric
2572cab237bSDimitry Andric assert(!State->Instance && "Replicating a Region with non-null instance.");
2582cab237bSDimitry Andric
2592cab237bSDimitry Andric // Enter replicating mode.
2602cab237bSDimitry Andric State->Instance = {0, 0};
2612cab237bSDimitry Andric
2622cab237bSDimitry Andric for (unsigned Part = 0, UF = State->UF; Part < UF; ++Part) {
2632cab237bSDimitry Andric State->Instance->Part = Part;
2642cab237bSDimitry Andric for (unsigned Lane = 0, VF = State->VF; Lane < VF; ++Lane) {
2652cab237bSDimitry Andric State->Instance->Lane = Lane;
2662cab237bSDimitry Andric // Visit the VPBlocks connected to \p this, starting from it.
2672cab237bSDimitry Andric for (VPBlockBase *Block : RPOT) {
2684ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "LV: VPBlock in RPO " << Block->getName() << '\n');
2692cab237bSDimitry Andric Block->execute(State);
2702cab237bSDimitry Andric }
2712cab237bSDimitry Andric }
2722cab237bSDimitry Andric }
2732cab237bSDimitry Andric
2742cab237bSDimitry Andric // Exit replicating mode.
2752cab237bSDimitry Andric State->Instance.reset();
2762cab237bSDimitry Andric }
2772cab237bSDimitry Andric
insertBefore(VPRecipeBase * InsertPos)2784ba319b5SDimitry Andric void VPRecipeBase::insertBefore(VPRecipeBase *InsertPos) {
2794ba319b5SDimitry Andric Parent = InsertPos->getParent();
2804ba319b5SDimitry Andric Parent->getRecipeList().insert(InsertPos->getIterator(), this);
2814ba319b5SDimitry Andric }
2824ba319b5SDimitry Andric
eraseFromParent()2834ba319b5SDimitry Andric iplist<VPRecipeBase>::iterator VPRecipeBase::eraseFromParent() {
2844ba319b5SDimitry Andric return getParent()->getRecipeList().erase(getIterator());
2854ba319b5SDimitry Andric }
2864ba319b5SDimitry Andric
generateInstruction(VPTransformState & State,unsigned Part)2872cab237bSDimitry Andric void VPInstruction::generateInstruction(VPTransformState &State,
2882cab237bSDimitry Andric unsigned Part) {
2892cab237bSDimitry Andric IRBuilder<> &Builder = State.Builder;
2902cab237bSDimitry Andric
2912cab237bSDimitry Andric if (Instruction::isBinaryOp(getOpcode())) {
2922cab237bSDimitry Andric Value *A = State.get(getOperand(0), Part);
2932cab237bSDimitry Andric Value *B = State.get(getOperand(1), Part);
2942cab237bSDimitry Andric Value *V = Builder.CreateBinOp((Instruction::BinaryOps)getOpcode(), A, B);
2952cab237bSDimitry Andric State.set(this, V, Part);
2962cab237bSDimitry Andric return;
2972cab237bSDimitry Andric }
2982cab237bSDimitry Andric
2992cab237bSDimitry Andric switch (getOpcode()) {
3002cab237bSDimitry Andric case VPInstruction::Not: {
3012cab237bSDimitry Andric Value *A = State.get(getOperand(0), Part);
3022cab237bSDimitry Andric Value *V = Builder.CreateNot(A);
3032cab237bSDimitry Andric State.set(this, V, Part);
3042cab237bSDimitry Andric break;
3052cab237bSDimitry Andric }
306*b5893f02SDimitry Andric case VPInstruction::ICmpULE: {
307*b5893f02SDimitry Andric Value *IV = State.get(getOperand(0), Part);
308*b5893f02SDimitry Andric Value *TC = State.get(getOperand(1), Part);
309*b5893f02SDimitry Andric Value *V = Builder.CreateICmpULE(IV, TC);
310*b5893f02SDimitry Andric State.set(this, V, Part);
311*b5893f02SDimitry Andric break;
312*b5893f02SDimitry Andric }
3132cab237bSDimitry Andric default:
3142cab237bSDimitry Andric llvm_unreachable("Unsupported opcode for instruction");
3152cab237bSDimitry Andric }
3162cab237bSDimitry Andric }
3172cab237bSDimitry Andric
execute(VPTransformState & State)3182cab237bSDimitry Andric void VPInstruction::execute(VPTransformState &State) {
3192cab237bSDimitry Andric assert(!State.Instance && "VPInstruction executing an Instance");
3202cab237bSDimitry Andric for (unsigned Part = 0; Part < State.UF; ++Part)
3212cab237bSDimitry Andric generateInstruction(State, Part);
3222cab237bSDimitry Andric }
3232cab237bSDimitry Andric
print(raw_ostream & O,const Twine & Indent) const3242cab237bSDimitry Andric void VPInstruction::print(raw_ostream &O, const Twine &Indent) const {
3252cab237bSDimitry Andric O << " +\n" << Indent << "\"EMIT ";
3262cab237bSDimitry Andric print(O);
3272cab237bSDimitry Andric O << "\\l\"";
3282cab237bSDimitry Andric }
3292cab237bSDimitry Andric
print(raw_ostream & O) const3302cab237bSDimitry Andric void VPInstruction::print(raw_ostream &O) const {
3312cab237bSDimitry Andric printAsOperand(O);
3322cab237bSDimitry Andric O << " = ";
3332cab237bSDimitry Andric
3342cab237bSDimitry Andric switch (getOpcode()) {
3352cab237bSDimitry Andric case VPInstruction::Not:
3362cab237bSDimitry Andric O << "not";
3372cab237bSDimitry Andric break;
338*b5893f02SDimitry Andric case VPInstruction::ICmpULE:
339*b5893f02SDimitry Andric O << "icmp ule";
340*b5893f02SDimitry Andric break;
341*b5893f02SDimitry Andric case VPInstruction::SLPLoad:
342*b5893f02SDimitry Andric O << "combined load";
343*b5893f02SDimitry Andric break;
344*b5893f02SDimitry Andric case VPInstruction::SLPStore:
345*b5893f02SDimitry Andric O << "combined store";
346*b5893f02SDimitry Andric break;
3472cab237bSDimitry Andric default:
3482cab237bSDimitry Andric O << Instruction::getOpcodeName(getOpcode());
3492cab237bSDimitry Andric }
3502cab237bSDimitry Andric
3512cab237bSDimitry Andric for (const VPValue *Operand : operands()) {
3522cab237bSDimitry Andric O << " ";
3532cab237bSDimitry Andric Operand->printAsOperand(O);
3542cab237bSDimitry Andric }
3552cab237bSDimitry Andric }
3562cab237bSDimitry Andric
3572cab237bSDimitry Andric /// Generate the code inside the body of the vectorized loop. Assumes a single
3582cab237bSDimitry Andric /// LoopVectorBody basic-block was created for this. Introduce additional
3592cab237bSDimitry Andric /// basic-blocks as needed, and fill them all.
execute(VPTransformState * State)3602cab237bSDimitry Andric void VPlan::execute(VPTransformState *State) {
361*b5893f02SDimitry Andric // -1. Check if the backedge taken count is needed, and if so build it.
362*b5893f02SDimitry Andric if (BackedgeTakenCount && BackedgeTakenCount->getNumUsers()) {
363*b5893f02SDimitry Andric Value *TC = State->TripCount;
364*b5893f02SDimitry Andric IRBuilder<> Builder(State->CFG.PrevBB->getTerminator());
365*b5893f02SDimitry Andric auto *TCMO = Builder.CreateSub(TC, ConstantInt::get(TC->getType(), 1),
366*b5893f02SDimitry Andric "trip.count.minus.1");
367*b5893f02SDimitry Andric Value2VPValue[TCMO] = BackedgeTakenCount;
368*b5893f02SDimitry Andric }
369*b5893f02SDimitry Andric
3702cab237bSDimitry Andric // 0. Set the reverse mapping from VPValues to Values for code generation.
3712cab237bSDimitry Andric for (auto &Entry : Value2VPValue)
3722cab237bSDimitry Andric State->VPValue2Value[Entry.second] = Entry.first;
3732cab237bSDimitry Andric
3742cab237bSDimitry Andric BasicBlock *VectorPreHeaderBB = State->CFG.PrevBB;
3752cab237bSDimitry Andric BasicBlock *VectorHeaderBB = VectorPreHeaderBB->getSingleSuccessor();
3762cab237bSDimitry Andric assert(VectorHeaderBB && "Loop preheader does not have a single successor.");
3772cab237bSDimitry Andric BasicBlock *VectorLatchBB = VectorHeaderBB;
3782cab237bSDimitry Andric
3792cab237bSDimitry Andric // 1. Make room to generate basic-blocks inside loop body if needed.
3802cab237bSDimitry Andric VectorLatchBB = VectorHeaderBB->splitBasicBlock(
3812cab237bSDimitry Andric VectorHeaderBB->getFirstInsertionPt(), "vector.body.latch");
3822cab237bSDimitry Andric Loop *L = State->LI->getLoopFor(VectorHeaderBB);
3832cab237bSDimitry Andric L->addBasicBlockToLoop(VectorLatchBB, *State->LI);
3842cab237bSDimitry Andric // Remove the edge between Header and Latch to allow other connections.
3852cab237bSDimitry Andric // Temporarily terminate with unreachable until CFG is rewired.
3862cab237bSDimitry Andric // Note: this asserts the generated code's assumption that
3872cab237bSDimitry Andric // getFirstInsertionPt() can be dereferenced into an Instruction.
3882cab237bSDimitry Andric VectorHeaderBB->getTerminator()->eraseFromParent();
3892cab237bSDimitry Andric State->Builder.SetInsertPoint(VectorHeaderBB);
3902cab237bSDimitry Andric UnreachableInst *Terminator = State->Builder.CreateUnreachable();
3912cab237bSDimitry Andric State->Builder.SetInsertPoint(Terminator);
3922cab237bSDimitry Andric
3932cab237bSDimitry Andric // 2. Generate code in loop body.
3942cab237bSDimitry Andric State->CFG.PrevVPBB = nullptr;
3952cab237bSDimitry Andric State->CFG.PrevBB = VectorHeaderBB;
3962cab237bSDimitry Andric State->CFG.LastBB = VectorLatchBB;
3972cab237bSDimitry Andric
3982cab237bSDimitry Andric for (VPBlockBase *Block : depth_first(Entry))
3992cab237bSDimitry Andric Block->execute(State);
4002cab237bSDimitry Andric
401*b5893f02SDimitry Andric // Setup branch terminator successors for VPBBs in VPBBsToFix based on
402*b5893f02SDimitry Andric // VPBB's successors.
403*b5893f02SDimitry Andric for (auto VPBB : State->CFG.VPBBsToFix) {
404*b5893f02SDimitry Andric assert(EnableVPlanNativePath &&
405*b5893f02SDimitry Andric "Unexpected VPBBsToFix in non VPlan-native path");
406*b5893f02SDimitry Andric BasicBlock *BB = State->CFG.VPBB2IRBB[VPBB];
407*b5893f02SDimitry Andric assert(BB && "Unexpected null basic block for VPBB");
408*b5893f02SDimitry Andric
409*b5893f02SDimitry Andric unsigned Idx = 0;
410*b5893f02SDimitry Andric auto *BBTerminator = BB->getTerminator();
411*b5893f02SDimitry Andric
412*b5893f02SDimitry Andric for (VPBlockBase *SuccVPBlock : VPBB->getHierarchicalSuccessors()) {
413*b5893f02SDimitry Andric VPBasicBlock *SuccVPBB = SuccVPBlock->getEntryBasicBlock();
414*b5893f02SDimitry Andric BBTerminator->setSuccessor(Idx, State->CFG.VPBB2IRBB[SuccVPBB]);
415*b5893f02SDimitry Andric ++Idx;
416*b5893f02SDimitry Andric }
417*b5893f02SDimitry Andric }
418*b5893f02SDimitry Andric
4192cab237bSDimitry Andric // 3. Merge the temporary latch created with the last basic-block filled.
4202cab237bSDimitry Andric BasicBlock *LastBB = State->CFG.PrevBB;
4212cab237bSDimitry Andric // Connect LastBB to VectorLatchBB to facilitate their merge.
422*b5893f02SDimitry Andric assert((EnableVPlanNativePath ||
423*b5893f02SDimitry Andric isa<UnreachableInst>(LastBB->getTerminator())) &&
424*b5893f02SDimitry Andric "Expected InnerLoop VPlan CFG to terminate with unreachable");
425*b5893f02SDimitry Andric assert((!EnableVPlanNativePath || isa<BranchInst>(LastBB->getTerminator())) &&
426*b5893f02SDimitry Andric "Expected VPlan CFG to terminate with branch in NativePath");
4272cab237bSDimitry Andric LastBB->getTerminator()->eraseFromParent();
4282cab237bSDimitry Andric BranchInst::Create(VectorLatchBB, LastBB);
4292cab237bSDimitry Andric
4302cab237bSDimitry Andric // Merge LastBB with Latch.
4312cab237bSDimitry Andric bool Merged = MergeBlockIntoPredecessor(VectorLatchBB, nullptr, State->LI);
4322cab237bSDimitry Andric (void)Merged;
4332cab237bSDimitry Andric assert(Merged && "Could not merge last basic block with latch.");
4342cab237bSDimitry Andric VectorLatchBB = LastBB;
4352cab237bSDimitry Andric
436*b5893f02SDimitry Andric // We do not attempt to preserve DT for outer loop vectorization currently.
437*b5893f02SDimitry Andric if (!EnableVPlanNativePath)
4382cab237bSDimitry Andric updateDominatorTree(State->DT, VectorPreHeaderBB, VectorLatchBB);
4392cab237bSDimitry Andric }
4402cab237bSDimitry Andric
updateDominatorTree(DominatorTree * DT,BasicBlock * LoopPreHeaderBB,BasicBlock * LoopLatchBB)4412cab237bSDimitry Andric void VPlan::updateDominatorTree(DominatorTree *DT, BasicBlock *LoopPreHeaderBB,
4422cab237bSDimitry Andric BasicBlock *LoopLatchBB) {
4432cab237bSDimitry Andric BasicBlock *LoopHeaderBB = LoopPreHeaderBB->getSingleSuccessor();
4442cab237bSDimitry Andric assert(LoopHeaderBB && "Loop preheader does not have a single successor.");
4452cab237bSDimitry Andric DT->addNewBlock(LoopHeaderBB, LoopPreHeaderBB);
4462cab237bSDimitry Andric // The vector body may be more than a single basic-block by this point.
4472cab237bSDimitry Andric // Update the dominator tree information inside the vector body by propagating
4482cab237bSDimitry Andric // it from header to latch, expecting only triangular control-flow, if any.
4492cab237bSDimitry Andric BasicBlock *PostDomSucc = nullptr;
4502cab237bSDimitry Andric for (auto *BB = LoopHeaderBB; BB != LoopLatchBB; BB = PostDomSucc) {
4512cab237bSDimitry Andric // Get the list of successors of this block.
4522cab237bSDimitry Andric std::vector<BasicBlock *> Succs(succ_begin(BB), succ_end(BB));
4532cab237bSDimitry Andric assert(Succs.size() <= 2 &&
4542cab237bSDimitry Andric "Basic block in vector loop has more than 2 successors.");
4552cab237bSDimitry Andric PostDomSucc = Succs[0];
4562cab237bSDimitry Andric if (Succs.size() == 1) {
4572cab237bSDimitry Andric assert(PostDomSucc->getSinglePredecessor() &&
4582cab237bSDimitry Andric "PostDom successor has more than one predecessor.");
4592cab237bSDimitry Andric DT->addNewBlock(PostDomSucc, BB);
4602cab237bSDimitry Andric continue;
4612cab237bSDimitry Andric }
4622cab237bSDimitry Andric BasicBlock *InterimSucc = Succs[1];
4632cab237bSDimitry Andric if (PostDomSucc->getSingleSuccessor() == InterimSucc) {
4642cab237bSDimitry Andric PostDomSucc = Succs[1];
4652cab237bSDimitry Andric InterimSucc = Succs[0];
4662cab237bSDimitry Andric }
4672cab237bSDimitry Andric assert(InterimSucc->getSingleSuccessor() == PostDomSucc &&
4682cab237bSDimitry Andric "One successor of a basic block does not lead to the other.");
4692cab237bSDimitry Andric assert(InterimSucc->getSinglePredecessor() &&
4702cab237bSDimitry Andric "Interim successor has more than one predecessor.");
471*b5893f02SDimitry Andric assert(PostDomSucc->hasNPredecessors(2) &&
4722cab237bSDimitry Andric "PostDom successor has more than two predecessors.");
4732cab237bSDimitry Andric DT->addNewBlock(InterimSucc, BB);
4742cab237bSDimitry Andric DT->addNewBlock(PostDomSucc, BB);
4752cab237bSDimitry Andric }
4762cab237bSDimitry Andric }
4772cab237bSDimitry Andric
getUID(const VPBlockBase * Block)4782cab237bSDimitry Andric const Twine VPlanPrinter::getUID(const VPBlockBase *Block) {
4792cab237bSDimitry Andric return (isa<VPRegionBlock>(Block) ? "cluster_N" : "N") +
4802cab237bSDimitry Andric Twine(getOrCreateBID(Block));
4812cab237bSDimitry Andric }
4822cab237bSDimitry Andric
getOrCreateName(const VPBlockBase * Block)4832cab237bSDimitry Andric const Twine VPlanPrinter::getOrCreateName(const VPBlockBase *Block) {
4842cab237bSDimitry Andric const std::string &Name = Block->getName();
4852cab237bSDimitry Andric if (!Name.empty())
4862cab237bSDimitry Andric return Name;
4872cab237bSDimitry Andric return "VPB" + Twine(getOrCreateBID(Block));
4882cab237bSDimitry Andric }
4892cab237bSDimitry Andric
dump()4902cab237bSDimitry Andric void VPlanPrinter::dump() {
4912cab237bSDimitry Andric Depth = 1;
4922cab237bSDimitry Andric bumpIndent(0);
4932cab237bSDimitry Andric OS << "digraph VPlan {\n";
4942cab237bSDimitry Andric OS << "graph [labelloc=t, fontsize=30; label=\"Vectorization Plan";
4952cab237bSDimitry Andric if (!Plan.getName().empty())
4962cab237bSDimitry Andric OS << "\\n" << DOT::EscapeString(Plan.getName());
497*b5893f02SDimitry Andric if (!Plan.Value2VPValue.empty() || Plan.BackedgeTakenCount) {
4982cab237bSDimitry Andric OS << ", where:";
499*b5893f02SDimitry Andric if (Plan.BackedgeTakenCount)
500*b5893f02SDimitry Andric OS << "\\n"
501*b5893f02SDimitry Andric << *Plan.getOrCreateBackedgeTakenCount() << " := BackedgeTakenCount";
5022cab237bSDimitry Andric for (auto Entry : Plan.Value2VPValue) {
5032cab237bSDimitry Andric OS << "\\n" << *Entry.second;
5042cab237bSDimitry Andric OS << DOT::EscapeString(" := ");
5052cab237bSDimitry Andric Entry.first->printAsOperand(OS, false);
5062cab237bSDimitry Andric }
5072cab237bSDimitry Andric }
5082cab237bSDimitry Andric OS << "\"]\n";
5092cab237bSDimitry Andric OS << "node [shape=rect, fontname=Courier, fontsize=30]\n";
5102cab237bSDimitry Andric OS << "edge [fontname=Courier, fontsize=30]\n";
5112cab237bSDimitry Andric OS << "compound=true\n";
5122cab237bSDimitry Andric
5132cab237bSDimitry Andric for (VPBlockBase *Block : depth_first(Plan.getEntry()))
5142cab237bSDimitry Andric dumpBlock(Block);
5152cab237bSDimitry Andric
5162cab237bSDimitry Andric OS << "}\n";
5172cab237bSDimitry Andric }
5182cab237bSDimitry Andric
dumpBlock(const VPBlockBase * Block)5192cab237bSDimitry Andric void VPlanPrinter::dumpBlock(const VPBlockBase *Block) {
5202cab237bSDimitry Andric if (const VPBasicBlock *BasicBlock = dyn_cast<VPBasicBlock>(Block))
5212cab237bSDimitry Andric dumpBasicBlock(BasicBlock);
5222cab237bSDimitry Andric else if (const VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
5232cab237bSDimitry Andric dumpRegion(Region);
5242cab237bSDimitry Andric else
5252cab237bSDimitry Andric llvm_unreachable("Unsupported kind of VPBlock.");
5262cab237bSDimitry Andric }
5272cab237bSDimitry Andric
drawEdge(const VPBlockBase * From,const VPBlockBase * To,bool Hidden,const Twine & Label)5282cab237bSDimitry Andric void VPlanPrinter::drawEdge(const VPBlockBase *From, const VPBlockBase *To,
5292cab237bSDimitry Andric bool Hidden, const Twine &Label) {
5302cab237bSDimitry Andric // Due to "dot" we print an edge between two regions as an edge between the
5312cab237bSDimitry Andric // exit basic block and the entry basic of the respective regions.
5322cab237bSDimitry Andric const VPBlockBase *Tail = From->getExitBasicBlock();
5332cab237bSDimitry Andric const VPBlockBase *Head = To->getEntryBasicBlock();
5342cab237bSDimitry Andric OS << Indent << getUID(Tail) << " -> " << getUID(Head);
5352cab237bSDimitry Andric OS << " [ label=\"" << Label << '\"';
5362cab237bSDimitry Andric if (Tail != From)
5372cab237bSDimitry Andric OS << " ltail=" << getUID(From);
5382cab237bSDimitry Andric if (Head != To)
5392cab237bSDimitry Andric OS << " lhead=" << getUID(To);
5402cab237bSDimitry Andric if (Hidden)
5412cab237bSDimitry Andric OS << "; splines=none";
5422cab237bSDimitry Andric OS << "]\n";
5432cab237bSDimitry Andric }
5442cab237bSDimitry Andric
dumpEdges(const VPBlockBase * Block)5452cab237bSDimitry Andric void VPlanPrinter::dumpEdges(const VPBlockBase *Block) {
5462cab237bSDimitry Andric auto &Successors = Block->getSuccessors();
5472cab237bSDimitry Andric if (Successors.size() == 1)
5482cab237bSDimitry Andric drawEdge(Block, Successors.front(), false, "");
5492cab237bSDimitry Andric else if (Successors.size() == 2) {
5502cab237bSDimitry Andric drawEdge(Block, Successors.front(), false, "T");
5512cab237bSDimitry Andric drawEdge(Block, Successors.back(), false, "F");
5522cab237bSDimitry Andric } else {
5532cab237bSDimitry Andric unsigned SuccessorNumber = 0;
5542cab237bSDimitry Andric for (auto *Successor : Successors)
5552cab237bSDimitry Andric drawEdge(Block, Successor, false, Twine(SuccessorNumber++));
5562cab237bSDimitry Andric }
5572cab237bSDimitry Andric }
5582cab237bSDimitry Andric
dumpBasicBlock(const VPBasicBlock * BasicBlock)5592cab237bSDimitry Andric void VPlanPrinter::dumpBasicBlock(const VPBasicBlock *BasicBlock) {
5602cab237bSDimitry Andric OS << Indent << getUID(BasicBlock) << " [label =\n";
5612cab237bSDimitry Andric bumpIndent(1);
5622cab237bSDimitry Andric OS << Indent << "\"" << DOT::EscapeString(BasicBlock->getName()) << ":\\n\"";
5632cab237bSDimitry Andric bumpIndent(1);
5642cab237bSDimitry Andric for (const VPRecipeBase &Recipe : *BasicBlock)
5652cab237bSDimitry Andric Recipe.print(OS, Indent);
5664ba319b5SDimitry Andric
5674ba319b5SDimitry Andric // Dump the condition bit.
5684ba319b5SDimitry Andric const VPValue *CBV = BasicBlock->getCondBit();
5694ba319b5SDimitry Andric if (CBV) {
5704ba319b5SDimitry Andric OS << " +\n" << Indent << " \"CondBit: ";
5714ba319b5SDimitry Andric if (const VPInstruction *CBI = dyn_cast<VPInstruction>(CBV)) {
5724ba319b5SDimitry Andric CBI->printAsOperand(OS);
5734ba319b5SDimitry Andric OS << " (" << DOT::EscapeString(CBI->getParent()->getName()) << ")\\l\"";
574*b5893f02SDimitry Andric } else {
5754ba319b5SDimitry Andric CBV->printAsOperand(OS);
576*b5893f02SDimitry Andric OS << "\"";
577*b5893f02SDimitry Andric }
5784ba319b5SDimitry Andric }
5794ba319b5SDimitry Andric
5802cab237bSDimitry Andric bumpIndent(-2);
5812cab237bSDimitry Andric OS << "\n" << Indent << "]\n";
5822cab237bSDimitry Andric dumpEdges(BasicBlock);
5832cab237bSDimitry Andric }
5842cab237bSDimitry Andric
dumpRegion(const VPRegionBlock * Region)5852cab237bSDimitry Andric void VPlanPrinter::dumpRegion(const VPRegionBlock *Region) {
5862cab237bSDimitry Andric OS << Indent << "subgraph " << getUID(Region) << " {\n";
5872cab237bSDimitry Andric bumpIndent(1);
5882cab237bSDimitry Andric OS << Indent << "fontname=Courier\n"
5892cab237bSDimitry Andric << Indent << "label=\""
5902cab237bSDimitry Andric << DOT::EscapeString(Region->isReplicator() ? "<xVFxUF> " : "<x1> ")
5912cab237bSDimitry Andric << DOT::EscapeString(Region->getName()) << "\"\n";
5922cab237bSDimitry Andric // Dump the blocks of the region.
5932cab237bSDimitry Andric assert(Region->getEntry() && "Region contains no inner blocks.");
5942cab237bSDimitry Andric for (const VPBlockBase *Block : depth_first(Region->getEntry()))
5952cab237bSDimitry Andric dumpBlock(Block);
5962cab237bSDimitry Andric bumpIndent(-1);
5972cab237bSDimitry Andric OS << Indent << "}\n";
5982cab237bSDimitry Andric dumpEdges(Region);
5992cab237bSDimitry Andric }
6002cab237bSDimitry Andric
printAsIngredient(raw_ostream & O,Value * V)6012cab237bSDimitry Andric void VPlanPrinter::printAsIngredient(raw_ostream &O, Value *V) {
6022cab237bSDimitry Andric std::string IngredientString;
6032cab237bSDimitry Andric raw_string_ostream RSO(IngredientString);
6042cab237bSDimitry Andric if (auto *Inst = dyn_cast<Instruction>(V)) {
6052cab237bSDimitry Andric if (!Inst->getType()->isVoidTy()) {
6062cab237bSDimitry Andric Inst->printAsOperand(RSO, false);
6072cab237bSDimitry Andric RSO << " = ";
6082cab237bSDimitry Andric }
6092cab237bSDimitry Andric RSO << Inst->getOpcodeName() << " ";
6102cab237bSDimitry Andric unsigned E = Inst->getNumOperands();
6112cab237bSDimitry Andric if (E > 0) {
6122cab237bSDimitry Andric Inst->getOperand(0)->printAsOperand(RSO, false);
6132cab237bSDimitry Andric for (unsigned I = 1; I < E; ++I)
6142cab237bSDimitry Andric Inst->getOperand(I)->printAsOperand(RSO << ", ", false);
6152cab237bSDimitry Andric }
6162cab237bSDimitry Andric } else // !Inst
6172cab237bSDimitry Andric V->printAsOperand(RSO, false);
6182cab237bSDimitry Andric RSO.flush();
6192cab237bSDimitry Andric O << DOT::EscapeString(IngredientString);
6202cab237bSDimitry Andric }
6212cab237bSDimitry Andric
print(raw_ostream & O,const Twine & Indent) const6222cab237bSDimitry Andric void VPWidenRecipe::print(raw_ostream &O, const Twine &Indent) const {
6232cab237bSDimitry Andric O << " +\n" << Indent << "\"WIDEN\\l\"";
6242cab237bSDimitry Andric for (auto &Instr : make_range(Begin, End))
6252cab237bSDimitry Andric O << " +\n" << Indent << "\" " << VPlanIngredient(&Instr) << "\\l\"";
6262cab237bSDimitry Andric }
6272cab237bSDimitry Andric
print(raw_ostream & O,const Twine & Indent) const6282cab237bSDimitry Andric void VPWidenIntOrFpInductionRecipe::print(raw_ostream &O,
6292cab237bSDimitry Andric const Twine &Indent) const {
6302cab237bSDimitry Andric O << " +\n" << Indent << "\"WIDEN-INDUCTION";
6312cab237bSDimitry Andric if (Trunc) {
6322cab237bSDimitry Andric O << "\\l\"";
6332cab237bSDimitry Andric O << " +\n" << Indent << "\" " << VPlanIngredient(IV) << "\\l\"";
6342cab237bSDimitry Andric O << " +\n" << Indent << "\" " << VPlanIngredient(Trunc) << "\\l\"";
6352cab237bSDimitry Andric } else
6362cab237bSDimitry Andric O << " " << VPlanIngredient(IV) << "\\l\"";
6372cab237bSDimitry Andric }
6382cab237bSDimitry Andric
print(raw_ostream & O,const Twine & Indent) const6392cab237bSDimitry Andric void VPWidenPHIRecipe::print(raw_ostream &O, const Twine &Indent) const {
6402cab237bSDimitry Andric O << " +\n" << Indent << "\"WIDEN-PHI " << VPlanIngredient(Phi) << "\\l\"";
6412cab237bSDimitry Andric }
6422cab237bSDimitry Andric
print(raw_ostream & O,const Twine & Indent) const6432cab237bSDimitry Andric void VPBlendRecipe::print(raw_ostream &O, const Twine &Indent) const {
6442cab237bSDimitry Andric O << " +\n" << Indent << "\"BLEND ";
6452cab237bSDimitry Andric Phi->printAsOperand(O, false);
6462cab237bSDimitry Andric O << " =";
6472cab237bSDimitry Andric if (!User) {
6482cab237bSDimitry Andric // Not a User of any mask: not really blending, this is a
6492cab237bSDimitry Andric // single-predecessor phi.
6502cab237bSDimitry Andric O << " ";
6512cab237bSDimitry Andric Phi->getIncomingValue(0)->printAsOperand(O, false);
6522cab237bSDimitry Andric } else {
6532cab237bSDimitry Andric for (unsigned I = 0, E = User->getNumOperands(); I < E; ++I) {
6542cab237bSDimitry Andric O << " ";
6552cab237bSDimitry Andric Phi->getIncomingValue(I)->printAsOperand(O, false);
6562cab237bSDimitry Andric O << "/";
6572cab237bSDimitry Andric User->getOperand(I)->printAsOperand(O);
6582cab237bSDimitry Andric }
6592cab237bSDimitry Andric }
6602cab237bSDimitry Andric O << "\\l\"";
6612cab237bSDimitry Andric }
6622cab237bSDimitry Andric
print(raw_ostream & O,const Twine & Indent) const6632cab237bSDimitry Andric void VPReplicateRecipe::print(raw_ostream &O, const Twine &Indent) const {
6642cab237bSDimitry Andric O << " +\n"
6652cab237bSDimitry Andric << Indent << "\"" << (IsUniform ? "CLONE " : "REPLICATE ")
6662cab237bSDimitry Andric << VPlanIngredient(Ingredient);
6672cab237bSDimitry Andric if (AlsoPack)
6682cab237bSDimitry Andric O << " (S->V)";
6692cab237bSDimitry Andric O << "\\l\"";
6702cab237bSDimitry Andric }
6712cab237bSDimitry Andric
print(raw_ostream & O,const Twine & Indent) const6722cab237bSDimitry Andric void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent) const {
6732cab237bSDimitry Andric O << " +\n"
6742cab237bSDimitry Andric << Indent << "\"PHI-PREDICATED-INSTRUCTION " << VPlanIngredient(PredInst)
6752cab237bSDimitry Andric << "\\l\"";
6762cab237bSDimitry Andric }
6772cab237bSDimitry Andric
print(raw_ostream & O,const Twine & Indent) const6782cab237bSDimitry Andric void VPWidenMemoryInstructionRecipe::print(raw_ostream &O,
6792cab237bSDimitry Andric const Twine &Indent) const {
6802cab237bSDimitry Andric O << " +\n" << Indent << "\"WIDEN " << VPlanIngredient(&Instr);
6812cab237bSDimitry Andric if (User) {
6822cab237bSDimitry Andric O << ", ";
6832cab237bSDimitry Andric User->getOperand(0)->printAsOperand(O);
6842cab237bSDimitry Andric }
6852cab237bSDimitry Andric O << "\\l\"";
6862cab237bSDimitry Andric }
6874ba319b5SDimitry Andric
6884ba319b5SDimitry Andric template void DomTreeBuilder::Calculate<VPDominatorTree>(VPDominatorTree &DT);
689*b5893f02SDimitry Andric
replaceAllUsesWith(VPValue * New)690*b5893f02SDimitry Andric void VPValue::replaceAllUsesWith(VPValue *New) {
691*b5893f02SDimitry Andric for (VPUser *User : users())
692*b5893f02SDimitry Andric for (unsigned I = 0, E = User->getNumOperands(); I < E; ++I)
693*b5893f02SDimitry Andric if (User->getOperand(I) == this)
694*b5893f02SDimitry Andric User->setOperand(I, New);
695*b5893f02SDimitry Andric }
696*b5893f02SDimitry Andric
visitRegion(VPRegionBlock * Region,Old2NewTy & Old2New,InterleavedAccessInfo & IAI)697*b5893f02SDimitry Andric void VPInterleavedAccessInfo::visitRegion(VPRegionBlock *Region,
698*b5893f02SDimitry Andric Old2NewTy &Old2New,
699*b5893f02SDimitry Andric InterleavedAccessInfo &IAI) {
700*b5893f02SDimitry Andric ReversePostOrderTraversal<VPBlockBase *> RPOT(Region->getEntry());
701*b5893f02SDimitry Andric for (VPBlockBase *Base : RPOT) {
702*b5893f02SDimitry Andric visitBlock(Base, Old2New, IAI);
703*b5893f02SDimitry Andric }
704*b5893f02SDimitry Andric }
705*b5893f02SDimitry Andric
visitBlock(VPBlockBase * Block,Old2NewTy & Old2New,InterleavedAccessInfo & IAI)706*b5893f02SDimitry Andric void VPInterleavedAccessInfo::visitBlock(VPBlockBase *Block, Old2NewTy &Old2New,
707*b5893f02SDimitry Andric InterleavedAccessInfo &IAI) {
708*b5893f02SDimitry Andric if (VPBasicBlock *VPBB = dyn_cast<VPBasicBlock>(Block)) {
709*b5893f02SDimitry Andric for (VPRecipeBase &VPI : *VPBB) {
710*b5893f02SDimitry Andric assert(isa<VPInstruction>(&VPI) && "Can only handle VPInstructions");
711*b5893f02SDimitry Andric auto *VPInst = cast<VPInstruction>(&VPI);
712*b5893f02SDimitry Andric auto *Inst = cast<Instruction>(VPInst->getUnderlyingValue());
713*b5893f02SDimitry Andric auto *IG = IAI.getInterleaveGroup(Inst);
714*b5893f02SDimitry Andric if (!IG)
715*b5893f02SDimitry Andric continue;
716*b5893f02SDimitry Andric
717*b5893f02SDimitry Andric auto NewIGIter = Old2New.find(IG);
718*b5893f02SDimitry Andric if (NewIGIter == Old2New.end())
719*b5893f02SDimitry Andric Old2New[IG] = new InterleaveGroup<VPInstruction>(
720*b5893f02SDimitry Andric IG->getFactor(), IG->isReverse(), IG->getAlignment());
721*b5893f02SDimitry Andric
722*b5893f02SDimitry Andric if (Inst == IG->getInsertPos())
723*b5893f02SDimitry Andric Old2New[IG]->setInsertPos(VPInst);
724*b5893f02SDimitry Andric
725*b5893f02SDimitry Andric InterleaveGroupMap[VPInst] = Old2New[IG];
726*b5893f02SDimitry Andric InterleaveGroupMap[VPInst]->insertMember(
727*b5893f02SDimitry Andric VPInst, IG->getIndex(Inst),
728*b5893f02SDimitry Andric IG->isReverse() ? (-1) * int(IG->getFactor()) : IG->getFactor());
729*b5893f02SDimitry Andric }
730*b5893f02SDimitry Andric } else if (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
731*b5893f02SDimitry Andric visitRegion(Region, Old2New, IAI);
732*b5893f02SDimitry Andric else
733*b5893f02SDimitry Andric llvm_unreachable("Unsupported kind of VPBlock.");
734*b5893f02SDimitry Andric }
735*b5893f02SDimitry Andric
VPInterleavedAccessInfo(VPlan & Plan,InterleavedAccessInfo & IAI)736*b5893f02SDimitry Andric VPInterleavedAccessInfo::VPInterleavedAccessInfo(VPlan &Plan,
737*b5893f02SDimitry Andric InterleavedAccessInfo &IAI) {
738*b5893f02SDimitry Andric Old2NewTy Old2New;
739*b5893f02SDimitry Andric visitRegion(cast<VPRegionBlock>(Plan.getEntry()), Old2New, IAI);
740*b5893f02SDimitry Andric }
741