diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h index 98140f6fddc01..bae53c600c18c 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -252,8 +252,7 @@ class VPBuilder { VPInstruction *createScalarPhi(ArrayRef IncomingValues, DebugLoc DL, const Twine &Name = "") { - return tryInsertInstruction( - new VPInstruction(Instruction::PHI, IncomingValues, DL, Name)); + return tryInsertInstruction(new VPPhi(IncomingValues, DL, Name)); } /// Convert the input value \p Current to the corresponding value of an diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 136ee36636565..2a726e058166d 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1143,6 +1143,21 @@ class VPPhiAccessors { #endif }; +struct VPPhi : public VPInstruction, public VPPhiAccessors { + VPPhi(ArrayRef Operands, DebugLoc DL, const Twine &Name = "") + : VPInstruction(Instruction::PHI, Operands, DL, Name) {} + + static inline bool classof(const VPRecipeBase *U) { + auto *R = dyn_cast(U); + return R && R->getOpcode() == Instruction::PHI; + } + + void execute(VPTransformState &State) override; + +protected: + const VPRecipeBase *getAsRecipe() const override { return this; } +}; + /// A recipe to wrap on original IR instruction not to be modified during /// execution, except for PHIs. PHIs are modeled via the VPIRPhi subclass. /// Expect PHIs, VPIRInstructions cannot have any operands. diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index 056a9aa0565d3..b2b2faafb6c26 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -492,16 +492,7 @@ Value *VPInstruction::generate(VPTransformState &State) { return Builder.CreateCmp(getPredicate(), A, B, Name); } case Instruction::PHI: { - assert(getParent() == - getParent()->getPlan()->getVectorLoopRegion()->getEntry() && - "VPInstructions with PHI opcodes must be used for header phis only " - "at the moment"); - BasicBlock *VectorPH = - State.CFG.VPBB2IRBB.at(getParent()->getCFGPredecessor(0)); - Value *Start = State.get(getOperand(0), VPLane(0)); - PHINode *Phi = State.Builder.CreatePHI(Start->getType(), 2, Name); - Phi->addIncoming(Start, VectorPH); - return Phi; + llvm_unreachable("should be handled by VPPhi::execute"); } case Instruction::Select: { bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this); @@ -1131,6 +1122,19 @@ void VPInstructionWithType::print(raw_ostream &O, const Twine &Indent, } #endif +void VPPhi::execute(VPTransformState &State) { + State.setDebugLocFrom(getDebugLoc()); + assert(getParent() == + getParent()->getPlan()->getVectorLoopRegion()->getEntry() && + "VPInstructions with PHI opcodes must be used for header phis only " + "at the moment"); + BasicBlock *VectorPH = State.CFG.VPBB2IRBB.at(getIncomingBlock(0)); + Value *Start = State.get(getIncomingValue(0), VPLane(0)); + PHINode *Phi = State.Builder.CreatePHI(Start->getType(), 2, getName()); + Phi->addIncoming(Start, VectorPH); + State.set(this, Phi, VPLane(0)); +} + VPIRInstruction *VPIRInstruction ::create(Instruction &I) { if (auto *Phi = dyn_cast(&I)) return new VPIRPhi(*Phi);