Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 8f37d00

Browse files
committed
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@346758 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 20a1e3c commit 8f37d00

File tree

6 files changed

+166
-49
lines changed

6 files changed

+166
-49
lines changed

include/llvm/Analysis/VectorUtils.h

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace llvm {
2424
template <typename T> class ArrayRef;
2525
class DemandedBits;
2626
class GetElementPtrInst;
27-
class InterleaveGroup;
27+
template <typename InstTy> class InterleaveGroup;
2828
class Loop;
2929
class ScalarEvolution;
3030
class TargetTransformInfo;
@@ -138,7 +138,7 @@ Instruction *propagateMetadata(Instruction *I, ArrayRef<Value *> VL);
138138
/// create[*]Mask() utilities which create a shuffle mask (mask that
139139
/// consists of indices).
140140
Constant *createBitMaskForGaps(IRBuilder<> &Builder, unsigned VF,
141-
const InterleaveGroup &Group);
141+
const InterleaveGroup<Instruction> &Group);
142142

143143
/// Create a mask with replicated elements.
144144
///
@@ -233,9 +233,12 @@ Value *concatenateVectors(IRBuilder<> &Builder, ArrayRef<Value *> Vecs);
233233
///
234234
/// Note: the interleaved load group could have gaps (missing members), but
235235
/// the interleaved store group doesn't allow gaps.
236-
class InterleaveGroup {
236+
template <typename InstTy> class InterleaveGroup {
237237
public:
238-
InterleaveGroup(Instruction *Instr, int Stride, unsigned Align)
238+
InterleaveGroup(unsigned Factor, bool Reverse, unsigned Align)
239+
: Factor(Factor), Reverse(Reverse), Align(Align), InsertPos(nullptr) {}
240+
241+
InterleaveGroup(InstTy *Instr, int Stride, unsigned Align)
239242
: Align(Align), InsertPos(Instr) {
240243
assert(Align && "The alignment should be non-zero");
241244

@@ -256,7 +259,7 @@ class InterleaveGroup {
256259
/// negative if it is the new leader.
257260
///
258261
/// \returns false if the instruction doesn't belong to the group.
259-
bool insertMember(Instruction *Instr, int Index, unsigned NewAlign) {
262+
bool insertMember(InstTy *Instr, int Index, unsigned NewAlign) {
260263
assert(NewAlign && "The new member's alignment should be non-zero");
261264

262265
int Key = Index + SmallestKey;
@@ -288,7 +291,7 @@ class InterleaveGroup {
288291
/// Get the member with the given index \p Index
289292
///
290293
/// \returns nullptr if contains no such member.
291-
Instruction *getMember(unsigned Index) const {
294+
InstTy *getMember(unsigned Index) const {
292295
int Key = SmallestKey + Index;
293296
auto Member = Members.find(Key);
294297
if (Member == Members.end())
@@ -299,29 +302,25 @@ class InterleaveGroup {
299302

300303
/// Get the index for the given member. Unlike the key in the member
301304
/// map, the index starts from 0.
302-
unsigned getIndex(Instruction *Instr) const {
303-
for (auto I : Members)
305+
unsigned getIndex(const InstTy *Instr) const {
306+
for (auto I : Members) {
304307
if (I.second == Instr)
305308
return I.first - SmallestKey;
309+
}
306310

307311
llvm_unreachable("InterleaveGroup contains no such member");
308312
}
309313

310-
Instruction *getInsertPos() const { return InsertPos; }
311-
void setInsertPos(Instruction *Inst) { InsertPos = Inst; }
314+
InstTy *getInsertPos() const { return InsertPos; }
315+
void setInsertPos(InstTy *Inst) { InsertPos = Inst; }
312316

313317
/// Add metadata (e.g. alias info) from the instructions in this group to \p
314318
/// NewInst.
315319
///
316320
/// FIXME: this function currently does not add noalias metadata a'la
317321
/// addNewMedata. To do that we need to compute the intersection of the
318322
/// noalias info from all members.
319-
void addMetadata(Instruction *NewInst) const {
320-
SmallVector<Value *, 4> VL;
321-
std::transform(Members.begin(), Members.end(), std::back_inserter(VL),
322-
[](std::pair<int, Instruction *> p) { return p.second; });
323-
propagateMetadata(NewInst, VL);
324-
}
323+
void addMetadata(InstTy *NewInst) const;
325324

326325
/// Returns true if this Group requires a scalar iteration to handle gaps.
327326
bool requiresScalarEpilogue() const {
@@ -344,7 +343,7 @@ class InterleaveGroup {
344343
unsigned Factor; // Interleave Factor.
345344
bool Reverse;
346345
unsigned Align;
347-
DenseMap<int, Instruction *> Members;
346+
DenseMap<int, InstTy *> Members;
348347
int SmallestKey = 0;
349348
int LargestKey = 0;
350349

@@ -359,7 +358,7 @@ class InterleaveGroup {
359358
// store i32 %even
360359
// %odd = add i32 // Def of %odd
361360
// store i32 %odd // Insert Position
362-
Instruction *InsertPos;
361+
InstTy *InsertPos;
363362
};
364363

365364
/// Drive the analysis of interleaved memory accesses in the loop.
@@ -390,7 +389,7 @@ class InterleavedAccessInfo {
390389
/// formation for predicated accesses, we may be able to relax this limitation
391390
/// in the future once we handle more complicated blocks.
392391
void reset() {
393-
SmallPtrSet<InterleaveGroup *, 4> DelSet;
392+
SmallPtrSet<InterleaveGroup<Instruction> *, 4> DelSet;
394393
// Avoid releasing a pointer twice.
395394
for (auto &I : InterleaveGroupMap)
396395
DelSet.insert(I.second);
@@ -409,11 +408,16 @@ class InterleavedAccessInfo {
409408
/// Get the interleave group that \p Instr belongs to.
410409
///
411410
/// \returns nullptr if doesn't have such group.
412-
InterleaveGroup *getInterleaveGroup(Instruction *Instr) const {
413-
auto Group = InterleaveGroupMap.find(Instr);
414-
if (Group == InterleaveGroupMap.end())
415-
return nullptr;
416-
return Group->second;
411+
InterleaveGroup<Instruction> *
412+
getInterleaveGroup(const Instruction *Instr) const {
413+
if (InterleaveGroupMap.count(Instr))
414+
return InterleaveGroupMap.find(Instr)->second;
415+
return nullptr;
416+
}
417+
418+
iterator_range<SmallPtrSetIterator<llvm::InterleaveGroup<Instruction> *>>
419+
getInterleaveGroups() {
420+
return make_range(InterleaveGroups.begin(), InterleaveGroups.end());
417421
}
418422

419423
/// Returns true if an interleaved group that may access memory
@@ -443,7 +447,9 @@ class InterleavedAccessInfo {
443447
bool RequiresScalarEpilogue = false;
444448

445449
/// Holds the relationships between the members and the interleave group.
446-
DenseMap<Instruction *, InterleaveGroup *> InterleaveGroupMap;
450+
DenseMap<Instruction *, InterleaveGroup<Instruction> *> InterleaveGroupMap;
451+
452+
SmallPtrSet<InterleaveGroup<Instruction> *, 4> InterleaveGroups;
447453

448454
/// Holds dependences among the memory accesses in the loop. It maps a source
449455
/// access to a set of dependent sink accesses.
@@ -476,19 +482,23 @@ class InterleavedAccessInfo {
476482
/// stride \p Stride and alignment \p Align.
477483
///
478484
/// \returns the newly created interleave group.
479-
InterleaveGroup *createInterleaveGroup(Instruction *Instr, int Stride,
480-
unsigned Align) {
481-
assert(!isInterleaved(Instr) && "Already in an interleaved access group");
482-
InterleaveGroupMap[Instr] = new InterleaveGroup(Instr, Stride, Align);
485+
InterleaveGroup<Instruction> *
486+
createInterleaveGroup(Instruction *Instr, int Stride, unsigned Align) {
487+
assert(!InterleaveGroupMap.count(Instr) &&
488+
"Already in an interleaved access group");
489+
InterleaveGroupMap[Instr] =
490+
new InterleaveGroup<Instruction>(Instr, Stride, Align);
491+
InterleaveGroups.insert(InterleaveGroupMap[Instr]);
483492
return InterleaveGroupMap[Instr];
484493
}
485494

486495
/// Release the group and remove all the relationships.
487-
void releaseGroup(InterleaveGroup *Group) {
496+
void releaseGroup(InterleaveGroup<Instruction> *Group) {
488497
for (unsigned i = 0; i < Group->getFactor(); i++)
489498
if (Instruction *Member = Group->getMember(i))
490499
InterleaveGroupMap.erase(Member);
491500

501+
InterleaveGroups.erase(Group);
492502
delete Group;
493503
}
494504

lib/Analysis/VectorUtils.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -505,8 +505,9 @@ Instruction *llvm::propagateMetadata(Instruction *Inst, ArrayRef<Value *> VL) {
505505
return Inst;
506506
}
507507

508-
Constant *llvm::createBitMaskForGaps(IRBuilder<> &Builder, unsigned VF,
509-
const InterleaveGroup &Group) {
508+
Constant *
509+
llvm::createBitMaskForGaps(IRBuilder<> &Builder, unsigned VF,
510+
const InterleaveGroup<Instruction> &Group) {
510511
// All 1's means mask is not needed.
511512
if (Group.getNumMembers() == Group.getFactor())
512513
return nullptr;
@@ -720,9 +721,9 @@ void InterleavedAccessInfo::analyzeInterleaving(
720721
collectDependences();
721722

722723
// Holds all interleaved store groups temporarily.
723-
SmallSetVector<InterleaveGroup *, 4> StoreGroups;
724+
SmallSetVector<InterleaveGroup<Instruction> *, 4> StoreGroups;
724725
// Holds all interleaved load groups temporarily.
725-
SmallSetVector<InterleaveGroup *, 4> LoadGroups;
726+
SmallSetVector<InterleaveGroup<Instruction> *, 4> LoadGroups;
726727

727728
// Search in bottom-up program order for pairs of accesses (A and B) that can
728729
// form interleaved load or store groups. In the algorithm below, access A
@@ -744,7 +745,7 @@ void InterleavedAccessInfo::analyzeInterleaving(
744745
// Initialize a group for B if it has an allowable stride. Even if we don't
745746
// create a group for B, we continue with the bottom-up algorithm to ensure
746747
// we don't break any of B's dependences.
747-
InterleaveGroup *Group = nullptr;
748+
InterleaveGroup<Instruction> *Group = nullptr;
748749
if (isStrided(DesB.Stride) &&
749750
(!isPredicated(B->getParent()) || EnablePredicatedInterleavedMemAccesses)) {
750751
Group = getInterleaveGroup(B);
@@ -789,7 +790,7 @@ void InterleavedAccessInfo::analyzeInterleaving(
789790
// illegal code motion. A will then be free to form another group with
790791
// instructions that precede it.
791792
if (isInterleaved(A)) {
792-
InterleaveGroup *StoreGroup = getInterleaveGroup(A);
793+
InterleaveGroup<Instruction> *StoreGroup = getInterleaveGroup(A);
793794
StoreGroups.remove(StoreGroup);
794795
releaseGroup(StoreGroup);
795796
}
@@ -868,7 +869,7 @@ void InterleavedAccessInfo::analyzeInterleaving(
868869
} // Iteration over B accesses.
869870

870871
// Remove interleaved store groups with gaps.
871-
for (InterleaveGroup *Group : StoreGroups)
872+
for (auto *Group : StoreGroups)
872873
if (Group->getNumMembers() != Group->getFactor()) {
873874
LLVM_DEBUG(
874875
dbgs() << "LV: Invalidate candidate interleaved store group due "
@@ -889,7 +890,7 @@ void InterleavedAccessInfo::analyzeInterleaving(
889890
// This means that we can forcefully peel the loop in order to only have to
890891
// check the first pointer for no-wrap. When we'll change to use Assume=true
891892
// we'll only need at most one runtime check per interleaved group.
892-
for (InterleaveGroup *Group : LoadGroups) {
893+
for (auto *Group : LoadGroups) {
893894
// Case 1: A full group. Can Skip the checks; For full groups, if the wide
894895
// load would wrap around the address space we would do a memory access at
895896
// nullptr even without the transformation.
@@ -947,9 +948,9 @@ void InterleavedAccessInfo::invalidateGroupsRequiringScalarEpilogue() {
947948
return;
948949

949950
// Avoid releasing a Group twice.
950-
SmallPtrSet<InterleaveGroup *, 4> DelSet;
951+
SmallPtrSet<InterleaveGroup<Instruction> *, 4> DelSet;
951952
for (auto &I : InterleaveGroupMap) {
952-
InterleaveGroup *Group = I.second;
953+
InterleaveGroup<Instruction> *Group = I.second;
953954
if (Group->requiresScalarEpilogue())
954955
DelSet.insert(Group);
955956
}
@@ -964,3 +965,16 @@ void InterleavedAccessInfo::invalidateGroupsRequiringScalarEpilogue() {
964965

965966
RequiresScalarEpilogue = false;
966967
}
968+
969+
template <>
970+
void InterleaveGroup<Instruction>::addMetadata(Instruction *NewInst) const {
971+
SmallVector<Value *, 4> VL;
972+
std::transform(Members.begin(), Members.end(), std::back_inserter(VL),
973+
[](std::pair<int, Instruction *> p) { return p.second; });
974+
propagateMetadata(NewInst, VL);
975+
}
976+
977+
template <typename InstT>
978+
void InterleaveGroup<InstT>::addMetadata(InstT *NewInst) const {
979+
llvm_unreachable("addMetadata can only be used for Instruction");
980+
}

lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,7 @@ class LoopVectorizationCostModel {
976976

977977
/// Save vectorization decision \p W and \p Cost taken by the cost model for
978978
/// interleaving group \p Grp and vector width \p VF.
979-
void setWideningDecision(const InterleaveGroup *Grp, unsigned VF,
979+
void setWideningDecision(const InterleaveGroup<Instruction> *Grp, unsigned VF,
980980
InstWidening W, unsigned Cost) {
981981
assert(VF >= 2 && "Expected VF >=2");
982982
/// Broadcast this decicion to all instructions inside the group.
@@ -1131,7 +1131,8 @@ class LoopVectorizationCostModel {
11311131
}
11321132

11331133
/// Get the interleaved access group that \p Instr belongs to.
1134-
const InterleaveGroup *getInterleavedAccessGroup(Instruction *Instr) {
1134+
const InterleaveGroup<Instruction> *
1135+
getInterleavedAccessGroup(Instruction *Instr) {
11351136
return InterleaveInfo.getInterleaveGroup(Instr);
11361137
}
11371138

@@ -1994,7 +1995,8 @@ static bool useMaskedInterleavedAccesses(const TargetTransformInfo &TTI) {
19941995
// store <12 x i32> %interleaved.vec ; Write 4 tuples of R,G,B
19951996
void InnerLoopVectorizer::vectorizeInterleaveGroup(Instruction *Instr,
19961997
VectorParts *BlockInMask) {
1997-
const InterleaveGroup *Group = Cost->getInterleavedAccessGroup(Instr);
1998+
const InterleaveGroup<Instruction> *Group =
1999+
Cost->getInterleavedAccessGroup(Instr);
19982000
assert(Group && "Fail to get an interleaved access group.");
19992001

20002002
// Skip if current instruction is not the insert position.
@@ -6377,7 +6379,7 @@ VPValue *VPRecipeBuilder::createBlockInMask(BasicBlock *BB, VPlanPtr &Plan) {
63776379
VPInterleaveRecipe *VPRecipeBuilder::tryToInterleaveMemory(Instruction *I,
63786380
VFRange &Range,
63796381
VPlanPtr &Plan) {
6380-
const InterleaveGroup *IG = CM.getInterleavedAccessGroup(I);
6382+
const InterleaveGroup<Instruction> *IG = CM.getInterleavedAccessGroup(I);
63816383
if (!IG)
63826384
return nullptr;
63836385

@@ -6793,7 +6795,8 @@ LoopVectorizationPlanner::buildVPlanWithVPRecipes(
67936795

67946796
// I is a member of an InterleaveGroup for Range.Start. If it's an adjunct
67956797
// member of the IG, do not construct any Recipe for it.
6796-
const InterleaveGroup *IG = CM.getInterleavedAccessGroup(Instr);
6798+
const InterleaveGroup<Instruction> *IG =
6799+
CM.getInterleavedAccessGroup(Instr);
67976800
if (IG && Instr != IG->getInsertPos() &&
67986801
Range.Start >= 2 && // Query is illegal for VF == 1
67996802
CM.getWideningDecision(Instr, Range.Start) ==

lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,3 +680,48 @@ void VPWidenMemoryInstructionRecipe::print(raw_ostream &O,
680680
}
681681

682682
template void DomTreeBuilder::Calculate<VPDominatorTree>(VPDominatorTree &DT);
683+
684+
void VPInterleavedAccessInfo::visitRegion(VPRegionBlock *Region,
685+
Old2NewTy &Old2New,
686+
InterleavedAccessInfo &IAI) {
687+
ReversePostOrderTraversal<VPBlockBase *> RPOT(Region->getEntry());
688+
for (VPBlockBase *Base : RPOT) {
689+
visitBlock(Base, Old2New, IAI);
690+
}
691+
}
692+
693+
void VPInterleavedAccessInfo::visitBlock(VPBlockBase *Block, Old2NewTy &Old2New,
694+
InterleavedAccessInfo &IAI) {
695+
if (VPBasicBlock *VPBB = dyn_cast<VPBasicBlock>(Block)) {
696+
for (VPRecipeBase &VPI : *VPBB) {
697+
assert(isa<VPInstruction>(&VPI) && "Can only handle VPInstructions");
698+
auto *VPInst = cast<VPInstruction>(&VPI);
699+
auto *Inst = cast<Instruction>(VPInst->getUnderlyingValue());
700+
auto *IG = IAI.getInterleaveGroup(Inst);
701+
if (!IG)
702+
continue;
703+
704+
auto NewIGIter = Old2New.find(IG);
705+
if (NewIGIter == Old2New.end())
706+
Old2New[IG] = new InterleaveGroup<VPInstruction>(
707+
IG->getFactor(), IG->isReverse(), IG->getAlignment());
708+
709+
if (Inst == IG->getInsertPos())
710+
Old2New[IG]->setInsertPos(VPInst);
711+
712+
InterleaveGroupMap[VPInst] = Old2New[IG];
713+
InterleaveGroupMap[VPInst]->insertMember(
714+
VPInst, IG->getIndex(Inst),
715+
IG->isReverse() ? (-1) * int(IG->getFactor()) : IG->getFactor());
716+
}
717+
} else if (VPRegionBlock *Region = dyn_cast<VPRegionBlock>(Block))
718+
visitRegion(Region, Old2New, IAI);
719+
else
720+
llvm_unreachable("Unsupported kind of VPBlock.");
721+
}
722+
723+
VPInterleavedAccessInfo::VPInterleavedAccessInfo(VPlan &Plan,
724+
InterleavedAccessInfo &IAI) {
725+
Old2NewTy Old2New;
726+
visitRegion(cast<VPRegionBlock>(Plan.getEntry()), Old2New, IAI);
727+
}

0 commit comments

Comments
 (0)