[llvm] a1bdb01 - [VectorCombine] Change shuffleToIdentity to use Use. NFC
David Green via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 17 07:25:39 PDT 2024
Author: David Green
Date: 2024-06-17T15:25:33+01:00
New Revision: a1bdb016564d3c0867e83f3bb7494bfe8128f4b6
URL: https://github.com/llvm/llvm-project/commit/a1bdb016564d3c0867e83f3bb7494bfe8128f4b6
DIFF: https://github.com/llvm/llvm-project/commit/a1bdb016564d3c0867e83f3bb7494bfe8128f4b6.diff
LOG: [VectorCombine] Change shuffleToIdentity to use Use. NFC
When looking up through shuffles, a Value can be multiple different leaf types
(for example an identity from one position, a splat from another). We currently
detect this by recalculating which type of leaf it is when generating, but as
more types of leafs are added (#94954) this doesn't scale very well.
This patch switches it to use Use, not Value, to more accurately detect which
type of leaf each Use should have.
Added:
Modified:
llvm/lib/Transforms/Vectorize/VectorCombine.cpp
llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index e608c7fb60468..5b9fe1c9c9854 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -1669,33 +1669,34 @@ bool VectorCombine::foldShuffleOfShuffles(Instruction &I) {
return true;
}
-using InstLane = std::pair<Value *, int>;
+using InstLane = std::pair<Use *, int>;
-static InstLane lookThroughShuffles(Value *V, int Lane) {
- while (auto *SV = dyn_cast<ShuffleVectorInst>(V)) {
+static InstLane lookThroughShuffles(Use *U, int Lane) {
+ while (auto *SV = dyn_cast<ShuffleVectorInst>(U->get())) {
unsigned NumElts =
cast<FixedVectorType>(SV->getOperand(0)->getType())->getNumElements();
int M = SV->getMaskValue(Lane);
if (M < 0)
return {nullptr, PoisonMaskElem};
if (static_cast<unsigned>(M) < NumElts) {
- V = SV->getOperand(0);
+ U = &SV->getOperandUse(0);
Lane = M;
} else {
- V = SV->getOperand(1);
+ U = &SV->getOperandUse(1);
Lane = M - NumElts;
}
}
- return InstLane{V, Lane};
+ return InstLane{U, Lane};
}
static SmallVector<InstLane>
generateInstLaneVectorFromOperand(ArrayRef<InstLane> Item, int Op) {
SmallVector<InstLane> NItem;
for (InstLane IL : Item) {
- auto [V, Lane] = IL;
+ auto [U, Lane] = IL;
InstLane OpLane =
- V ? lookThroughShuffles(cast<Instruction>(V)->getOperand(Op), Lane)
+ U ? lookThroughShuffles(&cast<Instruction>(U->get())->getOperandUse(Op),
+ Lane)
: InstLane{nullptr, PoisonMaskElem};
NItem.emplace_back(OpLane);
}
@@ -1703,29 +1704,24 @@ generateInstLaneVectorFromOperand(ArrayRef<InstLane> Item, int Op) {
}
static Value *generateNewInstTree(ArrayRef<InstLane> Item, FixedVectorType *Ty,
- const SmallPtrSet<Value *, 4> &IdentityLeafs,
- const SmallPtrSet<Value *, 4> &SplatLeafs,
+ const SmallPtrSet<Use *, 4> &IdentityLeafs,
+ const SmallPtrSet<Use *, 4> &SplatLeafs,
IRBuilder<> &Builder) {
- auto [FrontV, FrontLane] = Item.front();
-
- if (IdentityLeafs.contains(FrontV) &&
- all_of(drop_begin(enumerate(Item)), [Item](const auto &E) {
- Value *FrontV = Item.front().first;
- auto [V, Lane] = E.value();
- return !V || (V == FrontV && Lane == (int)E.index());
- })) {
- return FrontV;
+ auto [FrontU, FrontLane] = Item.front();
+
+ if (IdentityLeafs.contains(FrontU)) {
+ return FrontU->get();
}
- if (SplatLeafs.contains(FrontV)) {
- if (auto *ILI = dyn_cast<Instruction>(FrontV))
+ if (SplatLeafs.contains(FrontU)) {
+ if (auto *ILI = dyn_cast<Instruction>(FrontU))
Builder.SetInsertPoint(*ILI->getInsertionPointAfterDef());
- else if (auto *Arg = dyn_cast<Argument>(FrontV))
+ else if (auto *Arg = dyn_cast<Argument>(FrontU))
Builder.SetInsertPointPastAllocas(Arg->getParent());
SmallVector<int, 16> Mask(Ty->getNumElements(), FrontLane);
- return Builder.CreateShuffleVector(FrontV, Mask);
+ return Builder.CreateShuffleVector(FrontU->get(), Mask);
}
- auto *I = cast<Instruction>(FrontV);
+ auto *I = cast<Instruction>(FrontU->get());
auto *II = dyn_cast<IntrinsicInst>(I);
unsigned NumOps = I->getNumOperands() - (II ? 1 : 0);
SmallVector<Value *> Ops(NumOps);
@@ -1741,7 +1737,7 @@ static Value *generateNewInstTree(ArrayRef<InstLane> Item, FixedVectorType *Ty,
SmallVector<Value *, 8> ValueList;
for (const auto &Lane : Item)
if (Lane.first)
- ValueList.push_back(Lane.first);
+ ValueList.push_back(Lane.first->get());
Builder.SetInsertPoint(I);
Type *DstTy =
@@ -1785,16 +1781,16 @@ static Value *generateNewInstTree(ArrayRef<InstLane> Item, FixedVectorType *Ty,
// do so.
bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
auto *Ty = dyn_cast<FixedVectorType>(I.getType());
- if (!Ty)
+ if (!Ty || I.use_empty())
return false;
SmallVector<InstLane> Start(Ty->getNumElements());
for (unsigned M = 0, E = Ty->getNumElements(); M < E; ++M)
- Start[M] = lookThroughShuffles(&I, M);
+ Start[M] = lookThroughShuffles(&*I.use_begin(), M);
SmallVector<SmallVector<InstLane>> Worklist;
Worklist.push_back(Start);
- SmallPtrSet<Value *, 4> IdentityLeafs, SplatLeafs;
+ SmallPtrSet<Use *, 4> IdentityLeafs, SplatLeafs;
unsigned NumVisited = 0;
while (!Worklist.empty()) {
@@ -1802,52 +1798,52 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
return false;
SmallVector<InstLane> Item = Worklist.pop_back_val();
- auto [FrontV, FrontLane] = Item.front();
+ auto [FrontU, FrontLane] = Item.front();
// If we found an undef first lane then bail out to keep things simple.
- if (!FrontV)
+ if (!FrontU)
return false;
// Look for an identity value.
- if (!FrontLane &&
- cast<FixedVectorType>(FrontV->getType())->getNumElements() ==
+ if (FrontLane == 0 &&
+ cast<FixedVectorType>(FrontU->get()->getType())->getNumElements() ==
Ty->getNumElements() &&
all_of(drop_begin(enumerate(Item)), [Item](const auto &E) {
- Value *FrontV = Item.front().first;
- return !E.value().first || (E.value().first == FrontV &&
+ Value *FrontV = Item.front().first->get();
+ return !E.value().first || (E.value().first->get() == FrontV &&
E.value().second == (int)E.index());
})) {
- IdentityLeafs.insert(FrontV);
+ IdentityLeafs.insert(FrontU);
continue;
}
// Look for constants, for the moment only supporting constant splats.
- if (auto *C = dyn_cast<Constant>(FrontV);
+ if (auto *C = dyn_cast<Constant>(FrontU);
C && C->getSplatValue() &&
all_of(drop_begin(Item), [Item](InstLane &IL) {
- Value *FrontV = Item.front().first;
- Value *V = IL.first;
- return !V || V == FrontV;
+ Value *FrontV = Item.front().first->get();
+ Use *U = IL.first;
+ return !U || U->get() == FrontV;
})) {
- SplatLeafs.insert(FrontV);
+ SplatLeafs.insert(FrontU);
continue;
}
// Look for a splat value.
if (all_of(drop_begin(Item), [Item](InstLane &IL) {
- auto [FrontV, FrontLane] = Item.front();
- auto [V, Lane] = IL;
- return !V || (V == FrontV && Lane == FrontLane);
+ auto [FrontU, FrontLane] = Item.front();
+ auto [U, Lane] = IL;
+ return !U || (U->get() == FrontU->get() && Lane == FrontLane);
})) {
- SplatLeafs.insert(FrontV);
+ SplatLeafs.insert(FrontU);
continue;
}
// We need each element to be the same type of value, and check that each
// element has a single use.
if (!all_of(drop_begin(Item), [Item](InstLane IL) {
- Value *FrontV = Item.front().first;
- Value *V = IL.first;
- if (!V)
+ Value *FrontV = Item.front().first->get();
+ if (!IL.first)
return true;
+ Value *V = IL.first->get();
if (auto *I = dyn_cast<Instruction>(V); I && !I->hasOneUse())
return false;
if (V->getValueID() != FrontV->getValueID())
@@ -1869,25 +1865,25 @@ bool VectorCombine::foldShuffleToIdentity(Instruction &I) {
// Check the operator is one that we support. We exclude div/rem in case
// they hit UB from poison lanes.
- if ((isa<BinaryOperator>(FrontV) &&
- !cast<BinaryOperator>(FrontV)->isIntDivRem()) ||
- isa<CmpInst>(FrontV)) {
+ if ((isa<BinaryOperator>(FrontU) &&
+ !cast<BinaryOperator>(FrontU)->isIntDivRem()) ||
+ isa<CmpInst>(FrontU)) {
Worklist.push_back(generateInstLaneVectorFromOperand(Item, 0));
Worklist.push_back(generateInstLaneVectorFromOperand(Item, 1));
- } else if (isa<UnaryOperator, TruncInst, ZExtInst, SExtInst>(FrontV)) {
+ } else if (isa<UnaryOperator, TruncInst, ZExtInst, SExtInst>(FrontU)) {
Worklist.push_back(generateInstLaneVectorFromOperand(Item, 0));
- } else if (isa<SelectInst>(FrontV)) {
+ } else if (isa<SelectInst>(FrontU)) {
Worklist.push_back(generateInstLaneVectorFromOperand(Item, 0));
Worklist.push_back(generateInstLaneVectorFromOperand(Item, 1));
Worklist.push_back(generateInstLaneVectorFromOperand(Item, 2));
- } else if (auto *II = dyn_cast<IntrinsicInst>(FrontV);
+ } else if (auto *II = dyn_cast<IntrinsicInst>(FrontU);
II && isTriviallyVectorizable(II->getIntrinsicID())) {
for (unsigned Op = 0, E = II->getNumOperands() - 1; Op < E; Op++) {
if (isVectorIntrinsicWithScalarOpAtArg(II->getIntrinsicID(), Op)) {
if (!all_of(drop_begin(Item), [Item, Op](InstLane &IL) {
- Value *FrontV = Item.front().first;
- Value *V = IL.first;
- return !V || (cast<Instruction>(V)->getOperand(Op) ==
+ Value *FrontV = Item.front().first->get();
+ Use *U = IL.first;
+ return !U || (cast<Instruction>(U->get())->getOperand(Op) ==
cast<Instruction>(FrontV)->getOperand(Op));
}))
return false;
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
index c020aeb6483f5..9ad042c112b4c 100644
--- a/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
+++ b/llvm/test/Transforms/VectorCombine/AArch64/shuffletoidentity.ll
@@ -202,6 +202,19 @@ define <8 x i8> @abs_
diff erent(<8 x i8> %a) {
ret <8 x i8> %r
}
+define <4 x i32> @poison_intrinsic(<2 x i16> %l256) {
+; CHECK-LABEL: @poison_intrinsic(
+; CHECK-NEXT: [[L266:%.*]] = call <2 x i16> @llvm.abs.v2i16(<2 x i16> [[L256:%.*]], i1 false)
+; CHECK-NEXT: [[L267:%.*]] = zext <2 x i16> [[L266]] to <2 x i32>
+; CHECK-NEXT: [[L271:%.*]] = shufflevector <2 x i32> [[L267]], <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+; CHECK-NEXT: ret <4 x i32> [[L271]]
+;
+ %l266 = call <2 x i16> @llvm.abs.v2i16(<2 x i16> %l256, i1 false)
+ %l267 = zext <2 x i16> %l266 to <2 x i32>
+ %l271 = shufflevector <2 x i32> %l267, <2 x i32> poison, <4 x i32> <i32 0, i32 1, i32 poison, i32 poison>
+ ret <4 x i32> %l271
+}
+
define <8 x half> @splat0(<8 x half> %a, <8 x half> %b) {
; CHECK-LABEL: @splat0(
; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <8 x half> [[B:%.*]], <8 x half> poison, <8 x i32> zeroinitializer
More information about the llvm-commits
mailing list