diff options
author | Florian Hahn <florian.hahn@arm.com> | 2018-11-13 15:58:18 +0000 |
---|---|---|
committer | Florian Hahn <florian.hahn@arm.com> | 2018-11-13 15:58:18 +0000 |
commit | a4dc7feeea371166cc24dc617da59b2302dd2410 (patch) | |
tree | 712238e4b06f2c2890aa1d49d02c0d6d0304a5d6 /llvm/lib/Transforms | |
parent | de6480a38c4e6ab1e7c0c11fc7be87a4742d2d45 (diff) | |
download | bcm5719-llvm-a4dc7feeea371166cc24dc617da59b2302dd2410.tar.gz bcm5719-llvm-a4dc7feeea371166cc24dc617da59b2302dd2410.zip |
[VPlan] VPlan version of InterleavedAccessInfo.
This patch turns InterleaveGroup into a template with the instruction type
being a template parameter. It also adds a VPInterleavedAccessInfo class, which
only contains a mapping from VPInstructions to their respective InterleaveGroup.
As we do not have access to scalar evolution in VPlan, we can re-use
convert InterleavedAccessInfo to VPInterleavedAccess info.
Reviewers: Ayal, mssimpso, hfinkel, dcaballe, rengolin, mkuper, hsaito
Reviewed By: rengolin
Differential Revision: https://reviews.llvm.org/D49489
llvm-svn: 346758
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/Vectorize/LoopVectorize.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlan.cpp | 45 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlan.h | 52 | ||||
-rw-r--r-- | llvm/lib/Transforms/Vectorize/VPlanValue.h | 1 |
4 files changed, 102 insertions, 9 deletions
diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 17191a19a3f..9c46eee9567 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -976,7 +976,7 @@ public: /// Save vectorization decision \p W and \p Cost taken by the cost model for /// interleaving group \p Grp and vector width \p VF. - void setWideningDecision(const InterleaveGroup *Grp, unsigned VF, + void setWideningDecision(const InterleaveGroup<Instruction> *Grp, unsigned VF, InstWidening W, unsigned Cost) { assert(VF >= 2 && "Expected VF >=2"); /// Broadcast this decicion to all instructions inside the group. @@ -1131,7 +1131,8 @@ public: } /// Get the interleaved access group that \p Instr belongs to. - const InterleaveGroup *getInterleavedAccessGroup(Instruction *Instr) { + const InterleaveGroup<Instruction> * + getInterleavedAccessGroup(Instruction *Instr) { return InterleaveInfo.getInterleaveGroup(Instr); } @@ -1994,7 +1995,8 @@ static bool useMaskedInterleavedAccesses(const TargetTransformInfo &TTI) { // store <12 x i32> %interleaved.vec ; Write 4 tuples of R,G,B void InnerLoopVectorizer::vectorizeInterleaveGroup(Instruction *Instr, VectorParts *BlockInMask) { - const InterleaveGroup *Group = Cost->getInterleavedAccessGroup(Instr); + const InterleaveGroup<Instruction> *Group = + Cost->getInterleavedAccessGroup(Instr); assert(Group && "Fail to get an interleaved access group."); // Skip if current instruction is not the insert position. @@ -6377,7 +6379,7 @@ VPValue *VPRecipeBuilder::createBlockInMask(BasicBlock *BB, VPlanPtr &Plan) { VPInterleaveRecipe *VPRecipeBuilder::tryToInterleaveMemory(Instruction *I, VFRange &Range, VPlanPtr &Plan) { - const InterleaveGroup *IG = CM.getInterleavedAccessGroup(I); + const InterleaveGroup<Instruction> *IG = CM.getInterleavedAccessGroup(I); if (!IG) return nullptr; @@ -6793,7 +6795,8 @@ LoopVectorizationPlanner::buildVPlanWithVPRecipes( // I is a member of an InterleaveGroup for Range.Start. If it's an adjunct // member of the IG, do not construct any Recipe for it. - const InterleaveGroup *IG = CM.getInterleavedAccessGroup(Instr); + const InterleaveGroup<Instruction> *IG = + CM.getInterleavedAccessGroup(Instr); if (IG && Instr != IG->getInsertPos() && Range.Start >= 2 && // Query is illegal for VF == 1 CM.getWideningDecision(Instr, Range.Start) == diff --git a/llvm/lib/Transforms/Vectorize/VPlan.cpp b/llvm/lib/Transforms/Vectorize/VPlan.cpp index a3c15a36b05..541378dee2a 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.cpp +++ b/llvm/lib/Transforms/Vectorize/VPlan.cpp @@ -680,3 +680,48 @@ void VPWidenMemoryInstructionRecipe::print(raw_ostream &O, } template void DomTreeBuilder::Calculate<VPDominatorTree>(VPDominatorTree &DT); + +void VPInterleavedAccessInfo::visitRegion(VPRegionBlock *Region, + Old2NewTy &Old2New, + InterleavedAccessInfo &IAI) { + ReversePostOrderTraversal<VPBlockBase *> RPOT(Region->getEntry()); + for (VPBlockBase *Base : RPOT) { + visitBlock(Base, Old2New, IAI); + } +} + +void VPInterleavedAccessInfo::visitBlock(VPBlockBase *Block, Old2NewTy &Old2New, + InterleavedAccessInfo &IAI) { + if (VPBasicBlock *VPBB = dyn_cast<VPBasicBlock>(Block)) { + for (VPRecipeBase &VPI : *VPBB) { + assert(isa<VPInstruction>(&VPI) && "Can only handle VPInstructions"); + auto *VPInst = cast<VPInstruction>(&VPI); + auto *Inst = cast<Instruction>(VPInst->getUnderlyingValue()); + auto *IG = IAI.getInterleaveGroup(Inst); + if (!IG) + continue; + + auto NewIGIter = Old2New.find(IG); + if (NewIGIter == Old2New.end()) + Old2New[IG] = new InterleaveGroup<VPInstruction>( + IG->getFactor(), IG->isReverse(), IG->getAlignment()); + + if (Inst == IG->getInsertPos()) + Old2New[IG]->setInsertPos(VPInst); + + InterleaveGroupMap[VPInst] = Old2New[IG]; + InterleaveGroupMap[VPInst]->insertMember( + VPInst, IG->getIndex(Inst), + IG->isReverse() ? (-1) * int(IG->getFactor()) : IG->getFactor()); + } + } else if (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block)) + visitRegion(Region, Old2New, IAI); + else + llvm_unreachable("Unsupported kind of VPBlock."); +} + +VPInterleavedAccessInfo::VPInterleavedAccessInfo(VPlan &Plan, + InterleavedAccessInfo &IAI) { + Old2NewTy Old2New; + visitRegion(cast<VPRegionBlock>(Plan.getEntry()), Old2New, IAI); +} diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 9daaea1acde..66333220971 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -38,6 +38,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/Analysis/VectorUtils.h" #include "llvm/IR/IRBuilder.h" #include <algorithm> #include <cassert> @@ -52,7 +53,8 @@ class LoopVectorizationCostModel; class BasicBlock; class DominatorTree; class InnerLoopVectorizer; -class InterleaveGroup; +template <class T> class InterleaveGroup; +class LoopInfo; class raw_ostream; class Value; class VPBasicBlock; @@ -771,11 +773,11 @@ public: /// or stores into one wide load/store and shuffles. class VPInterleaveRecipe : public VPRecipeBase { private: - const InterleaveGroup *IG; + const InterleaveGroup<Instruction> *IG; std::unique_ptr<VPUser> User; public: - VPInterleaveRecipe(const InterleaveGroup *IG, VPValue *Mask) + VPInterleaveRecipe(const InterleaveGroup<Instruction> *IG, VPValue *Mask) : VPRecipeBase(VPInterleaveSC), IG(IG) { if (Mask) // Create a VPInstruction to register as a user of the mask. User.reset(new VPUser({Mask})); @@ -793,7 +795,7 @@ public: /// Print the recipe. void print(raw_ostream &O, const Twine &Indent) const override; - const InterleaveGroup *getInterleaveGroup() { return IG; } + const InterleaveGroup<Instruction> *getInterleaveGroup() { return IG; } }; /// VPReplicateRecipe replicates a given instruction producing multiple scalar @@ -1464,6 +1466,48 @@ public: } }; +class VPInterleavedAccessInfo { +private: + DenseMap<VPInstruction *, InterleaveGroup<VPInstruction> *> + InterleaveGroupMap; + + /// Type for mapping of instruction based interleave groups to VPInstruction + /// interleave groups + using Old2NewTy = DenseMap<InterleaveGroup<Instruction> *, + InterleaveGroup<VPInstruction> *>; + + /// Recursively \p Region and populate VPlan based interleave groups based on + /// \p IAI. + void visitRegion(VPRegionBlock *Region, Old2NewTy &Old2New, + InterleavedAccessInfo &IAI); + /// Recursively traverse \p Block and populate VPlan based interleave groups + /// based on \p IAI. + void visitBlock(VPBlockBase *Block, Old2NewTy &Old2New, + InterleavedAccessInfo &IAI); + +public: + VPInterleavedAccessInfo(VPlan &Plan, InterleavedAccessInfo &IAI); + + ~VPInterleavedAccessInfo() { + SmallPtrSet<InterleaveGroup<VPInstruction> *, 4> DelSet; + // Avoid releasing a pointer twice. + for (auto &I : InterleaveGroupMap) + DelSet.insert(I.second); + for (auto *Ptr : DelSet) + delete Ptr; + } + + /// Get the interleave group that \p Instr belongs to. + /// + /// \returns nullptr if doesn't have such group. + InterleaveGroup<VPInstruction> * + getInterleaveGroup(VPInstruction *Instr) const { + if (InterleaveGroupMap.count(Instr)) + return InterleaveGroupMap.find(Instr)->second; + return nullptr; + } +}; + } // end namespace llvm #endif // LLVM_TRANSFORMS_VECTORIZE_VPLAN_H diff --git a/llvm/lib/Transforms/Vectorize/VPlanValue.h b/llvm/lib/Transforms/Vectorize/VPlanValue.h index a81044a5e1b..972f0fa7da6 100644 --- a/llvm/lib/Transforms/Vectorize/VPlanValue.h +++ b/llvm/lib/Transforms/Vectorize/VPlanValue.h @@ -40,6 +40,7 @@ class VPValue { friend class VPBuilder; friend class VPlanHCFGTransforms; friend class VPBasicBlock; + friend class VPInterleavedAccessInfo; private: const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast). |