diff options
author | Florian Hahn <flo@fhahn.com> | 2025-08-06 14:43:03 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-06 14:43:03 +0100 |
commit | e80e7e717e8c2efe2c1712dc3bb4f25ba7ed11f6 (patch) | |
tree | a595d25d17ac15ab1d71f476460fa77c0a5a1544 /llvm/lib/Transforms | |
parent | fa91dcbefd7d9f16b2c6d624b14a1c023745b78a (diff) | |
download | llvm-e80e7e717e8c2efe2c1712dc3bb4f25ba7ed11f6.zip llvm-e80e7e717e8c2efe2c1712dc3bb4f25ba7ed11f6.tar.gz llvm-e80e7e717e8c2efe2c1712dc3bb4f25ba7ed11f6.tar.bz2 |
[VPlan] Use scalar VPPhi instead of VPWidenPHIRecipe in createPlainCFG. (#150847)
The initial VPlan closely reflects the original scalar loop, so unsing
VPWidenPHIRecipe here is premature. Widened phi recipes should only be
introduced together with other widened recipes.
PR: https://github.com/llvm/llvm-project/pull/150847
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlan.h | 18 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp | 23 |
5 files changed, 40 insertions, 26 deletions
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 307b5cf..9667b50 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -8301,7 +8301,7 @@ VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe(VPSingleDefRecipe *R, VPRecipeBase *Recipe; Instruction *Instr = R->getUnderlyingInstr(); SmallVector<VPValue *, 4> Operands(R->operands()); - if (auto *PhiR = dyn_cast<VPWidenPHIRecipe>(R)) { + if (auto *PhiR = dyn_cast<VPPhi>(R)) { VPBasicBlock *Parent = PhiR->getParent(); [[maybe_unused]] VPRegionBlock *LoopRegionOf = Parent->getEnclosingLoopRegion(); @@ -8339,6 +8339,7 @@ VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe(VPSingleDefRecipe *R, PhiRecipe->addOperand(Operands[1]); return PhiRecipe; } + assert(!R->isPhi() && "only VPPhi nodes expected at this point"); if (isa<TruncInst>(Instr) && (Recipe = tryToOptimizeInductionTruncate( cast<TruncInst>(Instr), Operands, Range))) diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 46dd114..c42cdd5 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -1242,12 +1242,24 @@ struct LLVM_ABI_FOR_TEST VPPhi : public VPInstruction, public VPPhiAccessors { : VPInstruction(Instruction::PHI, Operands, DL, Name) {} static inline bool classof(const VPUser *U) { - auto *R = dyn_cast<VPInstruction>(U); - return R && R->getOpcode() == Instruction::PHI; + auto *VPI = dyn_cast<VPInstruction>(U); + return VPI && VPI->getOpcode() == Instruction::PHI; + } + + static inline bool classof(const VPValue *V) { + auto *VPI = dyn_cast<VPInstruction>(V); + return VPI && VPI->getOpcode() == Instruction::PHI; + } + + static inline bool classof(const VPSingleDefRecipe *SDR) { + auto *VPI = dyn_cast<VPInstruction>(SDR); + return VPI && VPI->getOpcode() == Instruction::PHI; } VPPhi *clone() override { - return new VPPhi(operands(), getDebugLoc(), getName()); + auto *PhiR = new VPPhi(operands(), getDebugLoc(), getName()); + PhiR->setUnderlyingValue(getUnderlyingValue()); + return PhiR; } void execute(VPTransformState &State) override; diff --git a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp index 1b91901..7e8eff31 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp @@ -91,17 +91,15 @@ void PlainCFGBuilder::fixHeaderPhis() { for (auto *Phi : PhisToFix) { assert(IRDef2VPValue.count(Phi) && "Missing VPInstruction for PHINode."); VPValue *VPVal = IRDef2VPValue[Phi]; - assert(isa<VPWidenPHIRecipe>(VPVal) && - "Expected WidenPHIRecipe for phi node."); - auto *VPPhi = cast<VPWidenPHIRecipe>(VPVal); - assert(VPPhi->getNumOperands() == 0 && - "Expected VPInstruction with no operands."); + assert(isa<VPPhi>(VPVal) && "Expected VPPhi for phi node."); + auto *PhiR = cast<VPPhi>(VPVal); + assert(PhiR->getNumOperands() == 0 && "Expected VPPhi with no operands."); assert(isHeaderBB(Phi->getParent(), LI->getLoopFor(Phi->getParent())) && "Expected Phi in header block."); assert(Phi->getNumOperands() == 2 && "header phi must have exactly 2 operands"); for (BasicBlock *Pred : predecessors(Phi->getParent())) - VPPhi->addOperand( + PhiR->addOperand( getOrCreateVPOperand(Phi->getIncomingValueForBlock(Pred))); } } @@ -204,11 +202,11 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB, VPSingleDefRecipe *NewR; if (auto *Phi = dyn_cast<PHINode>(Inst)) { - // Phi node's operands may have not been visited at this point. We create + // Phi node's operands may not have been visited at this point. We create // an empty VPInstruction that we will fix once the whole plain CFG has // been built. - NewR = new VPWidenPHIRecipe(Phi, nullptr, Phi->getDebugLoc(), "vec.phi"); - VPBB->appendRecipe(NewR); + NewR = VPIRBuilder.createScalarPhi({}, Phi->getDebugLoc(), "vec.phi"); + NewR->setUnderlyingValue(Phi); if (isHeaderBB(Phi->getParent(), LI->getLoopFor(Phi->getParent()))) { // Header phis need to be fixed after the VPBB for the latch has been // created. diff --git a/llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp b/llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp index 3b3bbc3..862b930 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanPredicator.cpp @@ -227,10 +227,10 @@ void VPPredicator::createSwitchEdgeMasks(VPInstruction *SI) { } void VPPredicator::convertPhisToBlends(VPBasicBlock *VPBB) { - SmallVector<VPWidenPHIRecipe *> Phis; + SmallVector<VPPhi *> Phis; for (VPRecipeBase &R : VPBB->phis()) - Phis.push_back(cast<VPWidenPHIRecipe>(&R)); - for (VPWidenPHIRecipe *PhiR : Phis) { + Phis.push_back(cast<VPPhi>(&R)); + for (VPPhi *PhiR : Phis) { // The non-header Phi is converted into a Blend recipe below, // so we don't have to worry about the insertion order and we can just use // the builder. At this point we generate the predication tree. There may diff --git a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp index 57f8e32..1a71a75 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp @@ -63,17 +63,20 @@ bool VPlanTransforms::tryToConvertVPInstructionsToVPRecipes( Instruction *Inst = cast<Instruction>(VPV->getUnderlyingValue()); VPRecipeBase *NewRecipe = nullptr; - if (auto *VPPhi = dyn_cast<VPWidenPHIRecipe>(&Ingredient)) { - auto *Phi = cast<PHINode>(VPPhi->getUnderlyingValue()); + if (auto *PhiR = dyn_cast<VPPhi>(&Ingredient)) { + auto *Phi = cast<PHINode>(PhiR->getUnderlyingValue()); const auto *II = GetIntOrFpInductionDescriptor(Phi); - if (!II) - continue; - - VPValue *Start = Plan->getOrAddLiveIn(II->getStartValue()); - VPValue *Step = - vputils::getOrCreateVPValueForSCEVExpr(*Plan, II->getStep(), SE); - NewRecipe = new VPWidenIntOrFpInductionRecipe( - Phi, Start, Step, &Plan->getVF(), *II, Ingredient.getDebugLoc()); + if (!II) { + NewRecipe = new VPWidenPHIRecipe(Phi, nullptr, PhiR->getDebugLoc()); + for (VPValue *Op : PhiR->operands()) + NewRecipe->addOperand(Op); + } else { + VPValue *Start = Plan->getOrAddLiveIn(II->getStartValue()); + VPValue *Step = + vputils::getOrCreateVPValueForSCEVExpr(*Plan, II->getStep(), SE); + NewRecipe = new VPWidenIntOrFpInductionRecipe( + Phi, Start, Step, &Plan->getVF(), *II, Ingredient.getDebugLoc()); + } } else { assert(isa<VPInstruction>(&Ingredient) && "only VPInstructions expected here"); |