From b354f580cbc9b067142fbf9d08f7a2d9563ed86a Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Thu, 8 May 2025 21:28:19 +0100 Subject: [PATCH 1/3] [VPlan] Add new VPPhi subclass for VPInstruction with PHI opcodes. Similarly to VPInstructionWithType and VPIRPhi, add VPPhi as a subclass for VPInstruction. This allows implementing the VPPhiAccessors trait, making available helpers for generic printing of incoming values / blocks and accessors for incoming blocks and values. It will also allow properly verifying def-uses for values used by VPInstructions with PHI opcodes via https://github.com/llvm/llvm-project/pull/124838. --- .../Vectorize/LoopVectorizationPlanner.h | 2 +- llvm/lib/Transforms/Vectorize/VPlan.h | 22 ++++++++++++ .../lib/Transforms/Vectorize/VPlanRecipes.cpp | 35 +++++++++++++------ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h index 98140f6fddc01..5e72ce3e68c3e 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h @@ -253,7 +253,7 @@ class VPBuilder { VPInstruction *createScalarPhi(ArrayRef IncomingValues, DebugLoc DL, const Twine &Name = "") { return tryInsertInstruction( - new VPInstruction(Instruction::PHI, IncomingValues, DL, Name)); + new VPPhi(Instruction::PHI, 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..cd755dadad195 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1143,6 +1143,28 @@ class VPPhiAccessors { #endif }; +struct VPPhi : public VPInstruction, public VPPhiAccessors { + VPPhi(unsigned Opcode, ArrayRef Operands, DebugLoc DL, + const Twine &Name = "") + : VPInstruction(Opcode, 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; + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) + /// Print the recipe. + void print(raw_ostream &O, const Twine &Indent, + VPSlotTracker &SlotTracker) const override; +#endif + +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..6a4ffac200b1c 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,30 @@ 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)); +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +void VPPhi::print(raw_ostream &O, const Twine &Indent, + VPSlotTracker &SlotTracker) const { + O << Indent << "EMIT "; + printAsOperand(O, SlotTracker); + O << " = phi "; + + printPhiOperands(O, SlotTracker); +} +#endif + VPIRInstruction *VPIRInstruction ::create(Instruction &I) { if (auto *Phi = dyn_cast(&I)) return new VPIRPhi(*Phi); From 8c2bcfe7f4622a6c08d79dc083715ffdd413d692 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Fri, 9 May 2025 16:02:58 +0100 Subject: [PATCH 2/3] !fixup remove opcode argument --- llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h | 3 +-- llvm/lib/Transforms/Vectorize/VPlan.h | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h index 5e72ce3e68c3e..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 VPPhi(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 cd755dadad195..2c4cac7655ec9 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1144,9 +1144,8 @@ class VPPhiAccessors { }; struct VPPhi : public VPInstruction, public VPPhiAccessors { - VPPhi(unsigned Opcode, ArrayRef Operands, DebugLoc DL, - const Twine &Name = "") - : VPInstruction(Opcode, Operands, DL, Name) {} + 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); From 9943ab4cdc7915146b5898bf3ce7191b00d93551 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 10 May 2025 10:32:32 +0100 Subject: [PATCH 3/3] !fixup split off print changes. --- llvm/lib/Transforms/Vectorize/VPlan.h | 6 ------ llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp | 11 ----------- 2 files changed, 17 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 2c4cac7655ec9..2a726e058166d 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1154,12 +1154,6 @@ struct VPPhi : public VPInstruction, public VPPhiAccessors { void execute(VPTransformState &State) override; -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) - /// Print the recipe. - void print(raw_ostream &O, const Twine &Indent, - VPSlotTracker &SlotTracker) const override; -#endif - protected: const VPRecipeBase *getAsRecipe() const override { return this; } }; diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp index 6a4ffac200b1c..b2b2faafb6c26 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp @@ -1135,17 +1135,6 @@ void VPPhi::execute(VPTransformState &State) { State.set(this, Phi, VPLane(0)); } -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -void VPPhi::print(raw_ostream &O, const Twine &Indent, - VPSlotTracker &SlotTracker) const { - O << Indent << "EMIT "; - printAsOperand(O, SlotTracker); - O << " = phi "; - - printPhiOperands(O, SlotTracker); -} -#endif - VPIRInstruction *VPIRInstruction ::create(Instruction &I) { if (auto *Phi = dyn_cast(&I)) return new VPIRPhi(*Phi);