@@ -361,12 +361,14 @@ static bool isCommutative(Instruction *I) {
361
361
return I->isCommutative();
362
362
}
363
363
364
- /// \returns inserting index of InsertElement or InsertValue instruction,
365
- /// using Offset as base offset for index.
366
- static std::optional<unsigned> getInsertIndex(const Value *InsertInst,
367
- unsigned Offset = 0) {
364
+ template <typename T>
365
+ static std::optional<unsigned> getInsertExtractIndex(const Value *Inst,
366
+ unsigned Offset) {
367
+ static_assert(std::is_same_v<T, InsertElementInst> ||
368
+ std::is_same_v<T, ExtractElementInst>,
369
+ "unsupported T");
368
370
int Index = Offset;
369
- if (const auto *IE = dyn_cast<InsertElementInst>(InsertInst )) {
371
+ if (const auto *IE = dyn_cast<T>(Inst )) {
370
372
const auto *VT = dyn_cast<FixedVectorType>(IE->getType());
371
373
if (!VT)
372
374
return std::nullopt;
@@ -379,8 +381,25 @@ static std::optional<unsigned> getInsertIndex(const Value *InsertInst,
379
381
Index += CI->getZExtValue();
380
382
return Index;
381
383
}
384
+ return std::nullopt;
385
+ }
386
+
387
+ /// \returns inserting or extracting index of InsertElement, ExtractElement or
388
+ /// InsertValue instruction, using Offset as base offset for index.
389
+ /// \returns std::nullopt if the index is not an immediate.
390
+ static std::optional<unsigned> getElementIndex(const Value *Inst,
391
+ unsigned Offset = 0) {
392
+ if (auto Index = getInsertExtractIndex<InsertElementInst>(Inst, Offset))
393
+ return Index;
394
+ if (auto Index = getInsertExtractIndex<ExtractElementInst>(Inst, Offset))
395
+ return Index;
396
+
397
+ int Index = Offset;
398
+
399
+ const auto *IV = dyn_cast<InsertValueInst>(Inst);
400
+ if (!IV)
401
+ return std::nullopt;
382
402
383
- const auto *IV = cast<InsertValueInst>(InsertInst);
384
403
Type *CurrentType = IV->getType();
385
404
for (unsigned I : IV->indices()) {
386
405
if (const auto *ST = dyn_cast<StructType>(CurrentType)) {
@@ -454,7 +473,7 @@ static SmallBitVector isUndefVector(const Value *V,
454
473
Base = II->getOperand(0);
455
474
if (isa<T>(II->getOperand(1)))
456
475
continue;
457
- std::optional<unsigned> Idx = getInsertIndex (II);
476
+ std::optional<unsigned> Idx = getElementIndex (II);
458
477
if (!Idx) {
459
478
Res.reset();
460
479
return Res;
@@ -4707,8 +4726,8 @@ static bool areTwoInsertFromSameBuildVector(
4707
4726
return false;
4708
4727
auto *IE1 = VU;
4709
4728
auto *IE2 = V;
4710
- std::optional<unsigned> Idx1 = getInsertIndex (IE1);
4711
- std::optional<unsigned> Idx2 = getInsertIndex (IE2);
4729
+ std::optional<unsigned> Idx1 = getElementIndex (IE1);
4730
+ std::optional<unsigned> Idx2 = getElementIndex (IE2);
4712
4731
if (Idx1 == std::nullopt || Idx2 == std::nullopt)
4713
4732
return false;
4714
4733
// Go through the vector operand of insertelement instructions trying to find
@@ -4723,7 +4742,7 @@ static bool areTwoInsertFromSameBuildVector(
4723
4742
if (IE1 == V && !IE2)
4724
4743
return V->hasOneUse();
4725
4744
if (IE1 && IE1 != V) {
4726
- unsigned Idx1 = getInsertIndex (IE1).value_or(*Idx2);
4745
+ unsigned Idx1 = getElementIndex (IE1).value_or(*Idx2);
4727
4746
IsReusedIdx |= ReusedIdx.test(Idx1);
4728
4747
ReusedIdx.set(Idx1);
4729
4748
if ((IE1 != VU && !IE1->hasOneUse()) || IsReusedIdx)
@@ -4732,7 +4751,7 @@ static bool areTwoInsertFromSameBuildVector(
4732
4751
IE1 = dyn_cast_or_null<InsertElementInst>(GetBaseOperand(IE1));
4733
4752
}
4734
4753
if (IE2 && IE2 != VU) {
4735
- unsigned Idx2 = getInsertIndex (IE2).value_or(*Idx1);
4754
+ unsigned Idx2 = getElementIndex (IE2).value_or(*Idx1);
4736
4755
IsReusedIdx |= ReusedIdx.test(Idx2);
4737
4756
ReusedIdx.set(Idx2);
4738
4757
if ((IE2 != V && !IE2->hasOneUse()) || IsReusedIdx)
@@ -4891,13 +4910,13 @@ BoUpSLP::getReorderingData(const TreeEntry &TE, bool TopToBottom) {
4891
4910
IE1, IE2,
4892
4911
[](InsertElementInst *II) { return II->getOperand(0); }))
4893
4912
return I1 < I2;
4894
- return getInsertIndex (IE1) < getInsertIndex (IE2);
4913
+ return getElementIndex (IE1) < getElementIndex (IE2);
4895
4914
}
4896
4915
if (auto *EE1 = dyn_cast<ExtractElementInst>(FirstUserOfPhi1))
4897
4916
if (auto *EE2 = dyn_cast<ExtractElementInst>(FirstUserOfPhi2)) {
4898
4917
if (EE1->getOperand(0) != EE2->getOperand(0))
4899
4918
return I1 < I2;
4900
- return getInsertIndex (EE1) < getInsertIndex (EE2);
4919
+ return getElementIndex (EE1) < getElementIndex (EE2);
4901
4920
}
4902
4921
return I1 < I2;
4903
4922
};
@@ -6159,7 +6178,7 @@ BoUpSLP::TreeEntry::EntryState BoUpSLP::getScalarsVectorizationState(
6159
6178
ValueSet SourceVectors;
6160
6179
for (Value *V : VL) {
6161
6180
SourceVectors.insert(cast<Instruction>(V)->getOperand(0));
6162
- assert(getInsertIndex (V) != std::nullopt &&
6181
+ assert(getElementIndex (V) != std::nullopt &&
6163
6182
"Non-constant or undef index?");
6164
6183
}
6165
6184
@@ -6926,7 +6945,7 @@ void BoUpSLP::buildTree_rec(ArrayRef<Value *> VL, unsigned Depth,
6926
6945
decltype(OrdCompare)>
6927
6946
Indices(OrdCompare);
6928
6947
for (int I = 0, E = VL.size(); I < E; ++I) {
6929
- unsigned Idx = *getInsertIndex (VL[I]);
6948
+ unsigned Idx = *getElementIndex (VL[I]);
6930
6949
Indices.emplace(Idx, I);
6931
6950
}
6932
6951
OrdersType CurrentOrder(VL.size(), VL.size());
@@ -9271,11 +9290,11 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals,
9271
9290
unsigned NumOfParts = TTI->getNumberOfParts(SrcVecTy);
9272
9291
9273
9292
SmallVector<int> InsertMask(NumElts, PoisonMaskElem);
9274
- unsigned OffsetBeg = *getInsertIndex (VL.front());
9293
+ unsigned OffsetBeg = *getElementIndex (VL.front());
9275
9294
unsigned OffsetEnd = OffsetBeg;
9276
9295
InsertMask[OffsetBeg] = 0;
9277
9296
for (auto [I, V] : enumerate(VL.drop_front())) {
9278
- unsigned Idx = *getInsertIndex (V);
9297
+ unsigned Idx = *getElementIndex (V);
9279
9298
if (OffsetBeg > Idx)
9280
9299
OffsetBeg = Idx;
9281
9300
else if (OffsetEnd < Idx)
@@ -9316,7 +9335,7 @@ BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals,
9316
9335
SmallVector<int> PrevMask(InsertVecSz, PoisonMaskElem);
9317
9336
Mask.swap(PrevMask);
9318
9337
for (unsigned I = 0; I < NumScalars; ++I) {
9319
- unsigned InsertIdx = *getInsertIndex (VL[PrevMask[I]]);
9338
+ unsigned InsertIdx = *getElementIndex (VL[PrevMask[I]]);
9320
9339
DemandedElts.setBit(InsertIdx);
9321
9340
IsIdentity &= InsertIdx - OffsetBeg == I;
9322
9341
Mask[InsertIdx - OffsetBeg] = I;
@@ -10070,8 +10089,8 @@ static bool isFirstInsertElement(const InsertElementInst *IE1,
10070
10089
const auto *I2 = IE2;
10071
10090
const InsertElementInst *PrevI1;
10072
10091
const InsertElementInst *PrevI2;
10073
- unsigned Idx1 = *getInsertIndex (IE1);
10074
- unsigned Idx2 = *getInsertIndex (IE2);
10092
+ unsigned Idx1 = *getElementIndex (IE1);
10093
+ unsigned Idx2 = *getElementIndex (IE2);
10075
10094
do {
10076
10095
if (I2 == IE1)
10077
10096
return true;
@@ -10080,10 +10099,10 @@ static bool isFirstInsertElement(const InsertElementInst *IE1,
10080
10099
PrevI1 = I1;
10081
10100
PrevI2 = I2;
10082
10101
if (I1 && (I1 == IE1 || I1->hasOneUse()) &&
10083
- getInsertIndex (I1).value_or(Idx2) != Idx2)
10102
+ getElementIndex (I1).value_or(Idx2) != Idx2)
10084
10103
I1 = dyn_cast<InsertElementInst>(I1->getOperand(0));
10085
10104
if (I2 && ((I2 == IE2 || I2->hasOneUse())) &&
10086
- getInsertIndex (I2).value_or(Idx1) != Idx1)
10105
+ getElementIndex (I2).value_or(Idx1) != Idx1)
10087
10106
I2 = dyn_cast<InsertElementInst>(I2->getOperand(0));
10088
10107
} while ((I1 && PrevI1 != I1) || (I2 && PrevI2 != I2));
10089
10108
llvm_unreachable("Two different buildvectors not expected.");
@@ -10274,7 +10293,7 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals) {
10274
10293
if (auto *FTy = dyn_cast<FixedVectorType>(VU->getType())) {
10275
10294
if (!UsedInserts.insert(VU).second)
10276
10295
continue;
10277
- std::optional<unsigned> InsertIdx = getInsertIndex (VU);
10296
+ std::optional<unsigned> InsertIdx = getElementIndex (VU);
10278
10297
if (InsertIdx) {
10279
10298
const TreeEntry *ScalarTE = getTreeEntry(EU.Scalar);
10280
10299
auto *It = find_if(
@@ -10300,14 +10319,14 @@ InstructionCost BoUpSLP::getTreeCost(ArrayRef<Value *> VectorizedVals) {
10300
10319
while (auto *IEBase = dyn_cast<InsertElementInst>(Base)) {
10301
10320
if (IEBase != EU.User &&
10302
10321
(!IEBase->hasOneUse() ||
10303
- getInsertIndex (IEBase).value_or(*InsertIdx) == *InsertIdx))
10322
+ getElementIndex (IEBase).value_or(*InsertIdx) == *InsertIdx))
10304
10323
break;
10305
10324
// Build the mask for the vectorized insertelement instructions.
10306
10325
if (const TreeEntry *E = getTreeEntry(IEBase)) {
10307
10326
VU = IEBase;
10308
10327
do {
10309
10328
IEBase = cast<InsertElementInst>(Base);
10310
- int Idx = *getInsertIndex (IEBase);
10329
+ int Idx = *getElementIndex (IEBase);
10311
10330
assert(Mask[Idx] == PoisonMaskElem &&
10312
10331
"InsertElementInstruction used already.");
10313
10332
Mask[Idx] = Idx;
@@ -12721,7 +12740,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
12721
12740
cast<FixedVectorType>(FirstInsert->getType())->getNumElements();
12722
12741
const unsigned NumScalars = E->Scalars.size();
12723
12742
12724
- unsigned Offset = *getInsertIndex (VL0);
12743
+ unsigned Offset = *getElementIndex (VL0);
12725
12744
assert(Offset < NumElts && "Failed to find vector index offset");
12726
12745
12727
12746
// Create shuffle to resize vector
@@ -12739,7 +12758,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
12739
12758
Mask.swap(PrevMask);
12740
12759
for (unsigned I = 0; I < NumScalars; ++I) {
12741
12760
Value *Scalar = E->Scalars[PrevMask[I]];
12742
- unsigned InsertIdx = *getInsertIndex (Scalar);
12761
+ unsigned InsertIdx = *getElementIndex (Scalar);
12743
12762
IsIdentity &= InsertIdx - Offset == I;
12744
12763
Mask[InsertIdx - Offset] = I;
12745
12764
}
@@ -12752,7 +12771,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
12752
12771
// sequence.
12753
12772
InsertElementInst *Ins = cast<InsertElementInst>(VL0);
12754
12773
do {
12755
- std::optional<unsigned> InsertIdx = getInsertIndex (Ins);
12774
+ std::optional<unsigned> InsertIdx = getElementIndex (Ins);
12756
12775
if (!InsertIdx)
12757
12776
break;
12758
12777
if (InsertMask[*InsertIdx] == PoisonMaskElem)
@@ -13800,7 +13819,7 @@ Value *BoUpSLP::vectorizeTree(
13800
13819
}
13801
13820
}
13802
13821
13803
- std::optional<unsigned> InsertIdx = getInsertIndex (VU);
13822
+ std::optional<unsigned> InsertIdx = getElementIndex (VU);
13804
13823
if (InsertIdx) {
13805
13824
auto *It =
13806
13825
find_if(ShuffledInserts, [VU](const ShuffledInsertData &Data) {
@@ -13823,13 +13842,13 @@ Value *BoUpSLP::vectorizeTree(
13823
13842
while (auto *IEBase = dyn_cast<InsertElementInst>(Base)) {
13824
13843
if (IEBase != User &&
13825
13844
(!IEBase->hasOneUse() ||
13826
- getInsertIndex (IEBase).value_or(Idx) == Idx))
13845
+ getElementIndex (IEBase).value_or(Idx) == Idx))
13827
13846
break;
13828
13847
// Build the mask for the vectorized insertelement instructions.
13829
13848
if (const TreeEntry *E = getTreeEntry(IEBase)) {
13830
13849
do {
13831
13850
IEBase = cast<InsertElementInst>(Base);
13832
- int IEIdx = *getInsertIndex (IEBase);
13851
+ int IEIdx = *getElementIndex (IEBase);
13833
13852
assert(Mask[IEIdx] == PoisonMaskElem &&
13834
13853
"InsertElementInstruction used already.");
13835
13854
Mask[IEIdx] = IEIdx;
@@ -17781,7 +17800,7 @@ static void findBuildAggregate_rec(Instruction *LastInsertInst,
17781
17800
do {
17782
17801
Value *InsertedOperand = LastInsertInst->getOperand(1);
17783
17802
std::optional<unsigned> OperandIndex =
17784
- getInsertIndex (LastInsertInst, OperandOffset);
17803
+ getElementIndex (LastInsertInst, OperandOffset);
17785
17804
if (!OperandIndex)
17786
17805
return;
17787
17806
if (isa<InsertElementInst, InsertValueInst>(InsertedOperand)) {
0 commit comments