Skip to content

Commit 5cbdfe8

Browse files
committed
[IR] Add new CreateVectorInterleave interface and constant fold
This PR adds a new interface to IRBuilder called CreateVectorInterleave, which can be used to create vector.interleave intrinsics of factors 2-8. I've also added a new interface to the Folder called FoldVectorInterleave, which can spot when every operand is the same splat and instead return a new splat of the appropriate size. For convenience I have also moved getInterleaveIntrinsicID and getDeinterleaveIntrinsicID from VectorUtils.cpp to Intrinsics.cpp where it can be used by IRBuilder.
1 parent ac4c13d commit 5cbdfe8

17 files changed

+186
-113
lines changed

llvm/include/llvm/Analysis/InstSimplifyFolder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ class LLVM_ABI InstSimplifyFolder final : public IRBuilderFolder {
125125
dyn_cast_if_present<CallBase>(FMFSource));
126126
}
127127

128+
Value *FoldVectorInterleave(ArrayRef<Value *> Ops) const override {
129+
return ConstFolder.FoldVectorInterleave(Ops);
130+
}
131+
128132
//===--------------------------------------------------------------------===//
129133
// Cast/Conversion Operators
130134
//===--------------------------------------------------------------------===//

llvm/include/llvm/Analysis/TargetFolder.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,24 @@ class LLVM_ABI TargetFolder final : public IRBuilderFolder {
189189
return nullptr;
190190
}
191191

192+
Value *FoldVectorInterleave(ArrayRef<Value *> Ops) const override {
193+
// Check to see if all operands are the same.
194+
for (unsigned I = 1; I < Ops.size(); I++) {
195+
if (Ops[I] != Ops[0])
196+
return nullptr;
197+
}
198+
199+
// Is this just a large splat?
200+
if (auto *C = dyn_cast<Constant>(Ops[0])) {
201+
if (auto *V = C->getSplatValue()) {
202+
auto *SubvecTy = cast<VectorType>(Ops[0]->getType());
203+
return ConstantVector::getSplat(
204+
SubvecTy->getElementCount() * Ops.size(), V);
205+
}
206+
}
207+
return nullptr;
208+
}
209+
192210
Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
193211
Instruction *FMFSource) const override {
194212
auto *C1 = dyn_cast<Constant>(LHS);

llvm/include/llvm/Analysis/VectorUtils.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,6 @@ LLVM_ABI bool isVectorIntrinsicWithStructReturnOverloadAtField(
177177
LLVM_ABI Intrinsic::ID
178178
getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI);
179179

180-
/// Returns the corresponding llvm.vector.interleaveN intrinsic for factor N.
181-
LLVM_ABI Intrinsic::ID getInterleaveIntrinsicID(unsigned Factor);
182-
183-
/// Returns the corresponding llvm.vector.deinterleaveN intrinsic for factor N.
184-
LLVM_ABI Intrinsic::ID getDeinterleaveIntrinsicID(unsigned Factor);
185-
186180
/// Returns the corresponding factor of llvm.vector.interleaveN intrinsics.
187181
LLVM_ABI unsigned getInterleaveIntrinsicFactor(Intrinsic::ID ID);
188182

llvm/include/llvm/IR/ConstantFolder.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,24 @@ class LLVM_ABI ConstantFolder final : public IRBuilderFolder {
181181
return nullptr;
182182
}
183183

184+
Value *FoldVectorInterleave(ArrayRef<Value *> Ops) const override {
185+
// Check to see if all operands are the same.
186+
for (unsigned I = 1; I < Ops.size(); I++) {
187+
if (Ops[I] != Ops[0])
188+
return nullptr;
189+
}
190+
191+
// Is this just a large splat?
192+
if (auto *C = dyn_cast<Constant>(Ops[0])) {
193+
if (auto *V = C->getSplatValue()) {
194+
auto *SubvecTy = cast<VectorType>(Ops[0]->getType());
195+
return ConstantVector::getSplat(
196+
SubvecTy->getElementCount() * Ops.size(), V);
197+
}
198+
}
199+
return nullptr;
200+
}
201+
184202
Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
185203
Instruction *FMFSource) const override {
186204
// Use TargetFolder or InstSimplifyFolder instead.

llvm/include/llvm/IR/IRBuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2614,6 +2614,8 @@ class IRBuilderBase {
26142614
return CreateShuffleVector(V, PoisonValue::get(V->getType()), Mask, Name);
26152615
}
26162616

2617+
Value *CreateVectorInterleave(ArrayRef<Value *> Ops, const Twine &Name = "");
2618+
26172619
Value *CreateExtractValue(Value *Agg, ArrayRef<unsigned> Idxs,
26182620
const Twine &Name = "") {
26192621
if (auto *V = Folder.FoldExtractValue(Agg, Idxs))

llvm/include/llvm/IR/IRBuilderFolder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class LLVM_ABI IRBuilderFolder {
7575
virtual Value *FoldCast(Instruction::CastOps Op, Value *V,
7676
Type *DestTy) const = 0;
7777

78+
virtual Value *FoldVectorInterleave(ArrayRef<Value *> Ops) const = 0;
79+
7880
virtual Value *
7981
FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
8082
Instruction *FMFSource = nullptr) const = 0;

llvm/include/llvm/IR/Intrinsics.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,15 @@ namespace Intrinsic {
283283
// or of the wrong kind will be renamed by adding ".renamed" to the name.
284284
LLVM_ABI std::optional<Function *> remangleIntrinsicFunction(Function *F);
285285

286-
} // End Intrinsic namespace
286+
/// Returns the corresponding llvm.vector.interleaveN intrinsic for factor N.
287+
LLVM_ABI Intrinsic::ID getInterleaveIntrinsicID(unsigned Factor);
287288

288-
} // End llvm namespace
289+
/// Returns the corresponding llvm.vector.deinterleaveN intrinsic for factor
290+
/// N.
291+
LLVM_ABI Intrinsic::ID getDeinterleaveIntrinsicID(unsigned Factor);
292+
293+
} // namespace Intrinsic
294+
295+
} // namespace llvm
289296

290297
#endif

llvm/include/llvm/IR/NoFolder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ class LLVM_ABI NoFolder final : public IRBuilderFolder {
118118
return nullptr;
119119
}
120120

121+
Value *FoldVectorInterleave(ArrayRef<Value *> Ops) const override {
122+
return nullptr;
123+
}
124+
121125
//===--------------------------------------------------------------------===//
122126
// Cast/Conversion Operators
123127
//===--------------------------------------------------------------------===//

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,7 +1641,19 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
16411641
case Intrinsic::vector_extract:
16421642
case Intrinsic::vector_insert:
16431643
case Intrinsic::vector_interleave2:
1644+
case Intrinsic::vector_interleave3:
1645+
case Intrinsic::vector_interleave4:
1646+
case Intrinsic::vector_interleave5:
1647+
case Intrinsic::vector_interleave6:
1648+
case Intrinsic::vector_interleave7:
1649+
case Intrinsic::vector_interleave8:
16441650
case Intrinsic::vector_deinterleave2:
1651+
case Intrinsic::vector_deinterleave3:
1652+
case Intrinsic::vector_deinterleave4:
1653+
case Intrinsic::vector_deinterleave5:
1654+
case Intrinsic::vector_deinterleave6:
1655+
case Intrinsic::vector_deinterleave7:
1656+
case Intrinsic::vector_deinterleave8:
16451657
// Target intrinsics
16461658
case Intrinsic::amdgcn_perm:
16471659
case Intrinsic::amdgcn_wave_reduce_umin:

llvm/lib/Analysis/VectorUtils.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -240,30 +240,6 @@ Intrinsic::ID llvm::getVectorIntrinsicIDForCall(const CallInst *CI,
240240
return Intrinsic::not_intrinsic;
241241
}
242242

243-
struct InterleaveIntrinsic {
244-
Intrinsic::ID Interleave, Deinterleave;
245-
};
246-
247-
static InterleaveIntrinsic InterleaveIntrinsics[] = {
248-
{Intrinsic::vector_interleave2, Intrinsic::vector_deinterleave2},
249-
{Intrinsic::vector_interleave3, Intrinsic::vector_deinterleave3},
250-
{Intrinsic::vector_interleave4, Intrinsic::vector_deinterleave4},
251-
{Intrinsic::vector_interleave5, Intrinsic::vector_deinterleave5},
252-
{Intrinsic::vector_interleave6, Intrinsic::vector_deinterleave6},
253-
{Intrinsic::vector_interleave7, Intrinsic::vector_deinterleave7},
254-
{Intrinsic::vector_interleave8, Intrinsic::vector_deinterleave8},
255-
};
256-
257-
Intrinsic::ID llvm::getInterleaveIntrinsicID(unsigned Factor) {
258-
assert(Factor >= 2 && Factor <= 8 && "Unexpected factor");
259-
return InterleaveIntrinsics[Factor - 2].Interleave;
260-
}
261-
262-
Intrinsic::ID llvm::getDeinterleaveIntrinsicID(unsigned Factor) {
263-
assert(Factor >= 2 && Factor <= 8 && "Unexpected factor");
264-
return InterleaveIntrinsics[Factor - 2].Deinterleave;
265-
}
266-
267243
unsigned llvm::getInterleaveIntrinsicFactor(Intrinsic::ID ID) {
268244
switch (ID) {
269245
case Intrinsic::vector_interleave2:

0 commit comments

Comments
 (0)