@@ -19945,6 +19945,46 @@ static bool checkTreeSizes(ArrayRef<std::pair<unsigned, unsigned>> Sizes,
19945
19945
return Dev * 96 / (Mean * Mean) == 0;
19946
19946
}
19947
19947
19948
+ namespace {
19949
+
19950
+ /// A reference to a store instruction and the distance of its address to a base
19951
+ /// pointer.
19952
+ struct InstAndPtrDist {
19953
+ InstAndPtrDist(unsigned InstrIdx, int DistToBasePtr)
19954
+ : InstrIdx(InstrIdx), DistToBasePtr(DistToBasePtr) {}
19955
+ unsigned InstrIdx;
19956
+ int DistToBasePtr;
19957
+ };
19958
+ struct PtrDistCompare {
19959
+ bool operator()(const InstAndPtrDist &Op1, const InstAndPtrDist &Op2) const {
19960
+ return Op1.DistToBasePtr < Op2.DistToBasePtr;
19961
+ }
19962
+ };
19963
+
19964
+ /// A group of instructions that we'll try to bundle together using vector ops.
19965
+ /// They are ordered using the signed distance of their address operand to the
19966
+ /// address of this group's BaseInstr.
19967
+ struct RelatedStoreInsts {
19968
+ RelatedStoreInsts(unsigned BaseInstrIdx) { reset(BaseInstrIdx); }
19969
+ void reset(unsigned NewBaseInstr) {
19970
+ BaseInstrIdx = NewBaseInstr;
19971
+ Instrs.clear();
19972
+ Instrs.emplace(NewBaseInstr, 0);
19973
+ }
19974
+
19975
+ // Note: PtrDistCompare ensures that there a 1:1 mapping between distance and
19976
+ // instruction. This could be turned into a map to be more obvious.
19977
+ using InstSet = std::set<InstAndPtrDist, PtrDistCompare>;
19978
+
19979
+ /// The index of the Base instruction, i.e. the one with a 0 pointer distance.
19980
+ unsigned BaseInstrIdx;
19981
+
19982
+ /// Maps an instruction index to a pointer distance from \p BaseInstrIdx.
19983
+ InstSet Instrs;
19984
+ };
19985
+
19986
+ } // end anonymous namespace
19987
+
19948
19988
bool SLPVectorizerPass::vectorizeStores(
19949
19989
ArrayRef<StoreInst *> Stores, BoUpSLP &R,
19950
19990
DenseSet<std::tuple<Value *, Value *, Value *, Value *, unsigned>>
@@ -19954,31 +19994,21 @@ bool SLPVectorizerPass::vectorizeStores(
19954
19994
BoUpSLP::ValueSet VectorizedStores;
19955
19995
bool Changed = false;
19956
19996
19957
- struct StoreDistCompare {
19958
- bool operator()(const std::pair<unsigned, int> &Op1,
19959
- const std::pair<unsigned, int> &Op2) const {
19960
- return Op1.second < Op2.second;
19961
- }
19962
- };
19963
- // A set of pairs (index of store in Stores array ref, Distance of the store
19964
- // address relative to base store address in units).
19965
- using StoreIndexToDistSet =
19966
- std::set<std::pair<unsigned, int>, StoreDistCompare>;
19967
- auto TryToVectorize = [&](const StoreIndexToDistSet &Set) {
19997
+ auto TryToVectorize = [&](const RelatedStoreInsts::InstSet &StoreSeq) {
19968
19998
int PrevDist = -1;
19969
19999
BoUpSLP::ValueList Operands;
19970
20000
// Collect the chain into a list.
19971
- for (auto [Idx, Data] : enumerate(Set )) {
19972
- if (Operands.empty() || Data.second - PrevDist == 1) {
19973
- Operands.push_back(Stores[Data.first ]);
19974
- PrevDist = Data.second ;
19975
- if (Idx != Set .size() - 1)
20001
+ for (auto [Idx, Data] : enumerate(StoreSeq )) {
20002
+ if (Operands.empty() || Data.DistToBasePtr - PrevDist == 1) {
20003
+ Operands.push_back(Stores[Data.InstrIdx ]);
20004
+ PrevDist = Data.DistToBasePtr ;
20005
+ if (Idx != StoreSeq .size() - 1)
19976
20006
continue;
19977
20007
}
19978
20008
auto E = make_scope_exit([&, &DataVar = Data]() {
19979
20009
Operands.clear();
19980
- Operands.push_back(Stores[DataVar.first ]);
19981
- PrevDist = DataVar.second ;
20010
+ Operands.push_back(Stores[DataVar.InstrIdx ]);
20011
+ PrevDist = DataVar.DistToBasePtr ;
19982
20012
});
19983
20013
19984
20014
if (Operands.size() <= 1 ||
@@ -20245,7 +20275,8 @@ bool SLPVectorizerPass::vectorizeStores(
20245
20275
// Need to store the index of the very first store separately, since the set
20246
20276
// may be reordered after the insertion and the first store may be moved. This
20247
20277
// container allows to reduce number of calls of getPointersDiff() function.
20248
- SmallVector<std::pair<unsigned, StoreIndexToDistSet>> SortedStores;
20278
+ SmallVector<RelatedStoreInsts> SortedStores;
20279
+
20249
20280
// Inserts the specified store SI with the given index Idx to the set of the
20250
20281
// stores. If the store with the same distance is found already - stop
20251
20282
// insertion, try to vectorize already found stores. If some stores from this
@@ -20279,56 +20310,51 @@ bool SLPVectorizerPass::vectorizeStores(
20279
20310
// dependencies and no need to waste compile time to try to vectorize them.
20280
20311
// - Try to vectorize the sequence {1, {1, 0}, {3, 2}}.
20281
20312
auto FillStoresSet = [&](unsigned Idx, StoreInst *SI) {
20282
- for (std::pair<unsigned, StoreIndexToDistSet> &Set : SortedStores) {
20313
+ for (RelatedStoreInsts &StoreSeq : SortedStores) {
20283
20314
std::optional<int> Diff = getPointersDiff(
20284
- Stores[Set.first ]->getValueOperand()->getType(),
20285
- Stores[Set.first ]->getPointerOperand(),
20315
+ Stores[StoreSeq.BaseInstrIdx ]->getValueOperand()->getType(),
20316
+ Stores[StoreSeq.BaseInstrIdx ]->getPointerOperand(),
20286
20317
SI->getValueOperand()->getType(), SI->getPointerOperand(), *DL, *SE,
20287
20318
/*StrictCheck=*/true);
20288
20319
if (!Diff)
20289
20320
continue;
20290
- auto It = Set.second .find(std::make_pair( Idx, *Diff) );
20291
- if (It == Set.second .end()) {
20292
- Set.second .emplace(Idx, *Diff);
20321
+ auto It = StoreSeq.Instrs .find({ Idx, *Diff} );
20322
+ if (It == StoreSeq.Instrs .end()) {
20323
+ StoreSeq.Instrs .emplace(Idx, *Diff);
20293
20324
return;
20294
20325
}
20295
20326
// Try to vectorize the first found set to avoid duplicate analysis.
20296
- TryToVectorize(Set.second);
20297
- unsigned ItIdx = It->first;
20298
- int ItDist = It->second;
20299
- StoreIndexToDistSet PrevSet;
20300
- copy_if(Set.second, std::inserter(PrevSet, PrevSet.end()),
20301
- [&](const std::pair<unsigned, int> &Pair) {
20302
- return Pair.first > ItIdx;
20303
- });
20304
- Set.second.clear();
20305
- Set.first = Idx;
20306
- Set.second.emplace(Idx, 0);
20327
+ TryToVectorize(StoreSeq.Instrs);
20328
+ unsigned ItIdx = It->InstrIdx;
20329
+ int ItDist = It->DistToBasePtr;
20330
+ RelatedStoreInsts::InstSet PrevSet;
20331
+ copy_if(StoreSeq.Instrs, std::inserter(PrevSet, PrevSet.end()),
20332
+ [&](const InstAndPtrDist &I) { return I.InstrIdx > ItIdx; });
20333
+ StoreSeq.reset(Idx);
20307
20334
// Insert stores that followed previous match to try to vectorize them
20308
20335
// with this store.
20309
20336
unsigned StartIdx = ItIdx + 1;
20310
20337
SmallBitVector UsedStores(Idx - StartIdx);
20311
20338
// Distances to previously found dup store (or this store, since they
20312
20339
// store to the same addresses).
20313
20340
SmallVector<int> Dists(Idx - StartIdx, 0);
20314
- for (const std::pair<unsigned, int> &Pair : reverse(PrevSet)) {
20341
+ for (const InstAndPtrDist &Store : reverse(PrevSet)) {
20315
20342
// Do not try to vectorize sequences, we already tried.
20316
- if (VectorizedStores.contains(Stores[Pair.first ]))
20343
+ if (VectorizedStores.contains(Stores[Store.InstrIdx ]))
20317
20344
break;
20318
- unsigned BI = Pair.first - StartIdx;
20345
+ unsigned BI = Store.InstrIdx - StartIdx;
20319
20346
UsedStores.set(BI);
20320
- Dists[BI] = Pair.second - ItDist;
20347
+ Dists[BI] = Store.DistToBasePtr - ItDist;
20321
20348
}
20322
20349
for (unsigned I = StartIdx; I < Idx; ++I) {
20323
20350
unsigned BI = I - StartIdx;
20324
20351
if (UsedStores.test(BI))
20325
- Set.second .emplace(I, Dists[BI]);
20352
+ StoreSeq.Instrs .emplace(I, Dists[BI]);
20326
20353
}
20327
20354
return;
20328
20355
}
20329
- auto &Res = SortedStores.emplace_back();
20330
- Res.first = Idx;
20331
- Res.second.emplace(Idx, 0);
20356
+ // We did not find a comparable store, start a new sequence.
20357
+ SortedStores.emplace_back(Idx);
20332
20358
};
20333
20359
Type *PrevValTy = nullptr;
20334
20360
for (auto [I, SI] : enumerate(Stores)) {
@@ -20338,17 +20364,17 @@ bool SLPVectorizerPass::vectorizeStores(
20338
20364
PrevValTy = SI->getValueOperand()->getType();
20339
20365
// Check that we do not try to vectorize stores of different types.
20340
20366
if (PrevValTy != SI->getValueOperand()->getType()) {
20341
- for (auto &Set : SortedStores)
20342
- TryToVectorize(Set.second );
20367
+ for (RelatedStoreInsts &StoreSeq : SortedStores)
20368
+ TryToVectorize(StoreSeq.Instrs );
20343
20369
SortedStores.clear();
20344
20370
PrevValTy = SI->getValueOperand()->getType();
20345
20371
}
20346
20372
FillStoresSet(I, SI);
20347
20373
}
20348
20374
20349
20375
// Final vectorization attempt.
20350
- for (auto &Set : SortedStores)
20351
- TryToVectorize(Set.second );
20376
+ for (RelatedStoreInsts &StoreSeq : SortedStores)
20377
+ TryToVectorize(StoreSeq.Instrs );
20352
20378
20353
20379
return Changed;
20354
20380
}
0 commit comments