From 2d0d65b3babecbd339b01fdf7da29b8dfd69f889 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 28 Jan 2024 21:05:16 +0000 Subject: [PATCH] [VPlan] Create edge masks all cases up front needed.(NFC) Similarly to how block masks are created up front and later only retrieved also make sure masks are created in cases where edge masks are needed, i.e. blend recipes. Creating block-in masks for all blocks in the loop also ensures edge masks for all relevant edges have been created. Later, the new getEdgeMask can be used to look up cached edge masks. This makes sure edge masks are available in all cases for https://github.com/llvm/llvm-project/pull/76090. --- .../Transforms/Vectorize/LoopVectorize.cpp | 24 +++++++++++++++---- .../Transforms/Vectorize/VPRecipeBuilder.h | 4 ++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index fbc82fb9696e..3aff0a02e059 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -8038,6 +8038,17 @@ VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst, return EdgeMaskCache[Edge] = EdgeMask; } +VPValue *VPRecipeBuilder::getEdgeMask(BasicBlock *Src, BasicBlock *Dst) const { + assert(is_contained(predecessors(Dst), Src) && "Invalid edge"); + + // Look for cached value. + std::pair Edge(Src, Dst); + EdgeMaskCacheTy::const_iterator ECEntryIt = EdgeMaskCache.find(Edge); + assert(ECEntryIt != EdgeMaskCache.end() && + "looking up mask for edge which has not been created"); + return ECEntryIt->second; +} + void VPRecipeBuilder::createHeaderMask(VPlan &Plan) { BasicBlock *Header = OrigLoop->getHeader(); @@ -8728,10 +8739,13 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { DFS.perform(LI); VPBasicBlock *VPBB = HeaderVPBB; - bool NeedsMasks = CM.foldTailByMasking() || - any_of(OrigLoop->blocks(), [this](BasicBlock *BB) { - return Legal->blockNeedsPredication(BB); - }); + BasicBlock *HeaderBB = OrigLoop->getHeader(); + bool NeedsMasks = + CM.foldTailByMasking() || + any_of(OrigLoop->blocks(), [this, HeaderBB](BasicBlock *BB) { + bool NeedsBlends = BB != HeaderBB && !BB->phis().empty(); + return Legal->blockNeedsPredication(BB) || NeedsBlends; + }); for (BasicBlock *BB : make_range(DFS.beginRPO(), DFS.endRPO())) { // Relevant instructions from basic block BB will be grouped into VPRecipe // ingredients and fill a new VPBasicBlock. @@ -8750,7 +8764,7 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) { Instruction *Instr = &I; SmallVector Operands; auto *Phi = dyn_cast(Instr); - if (Phi && Phi->getParent() == OrigLoop->getHeader()) { + if (Phi && Phi->getParent() == HeaderBB) { Operands.push_back(Plan->getVPValueOrAddLiveIn( Phi->getIncomingValueForBlock(OrigLoop->getLoopPreheader()))); } else { diff --git a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h index 4b3143aead46..5645cfa1473a 100644 --- a/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h +++ b/llvm/lib/Transforms/Vectorize/VPRecipeBuilder.h @@ -148,6 +148,10 @@ public: /// and DST. VPValue *createEdgeMask(BasicBlock *Src, BasicBlock *Dst, VPlan &Plan); + /// A helper that returns the previously computed predicate of the edge + /// between SRC and DST. + VPValue *getEdgeMask(BasicBlock *Src, BasicBlock *Dst) const; + /// Mark given ingredient for recording its recipe once one is created for /// it. void recordRecipeOf(Instruction *I) {