Skip to content

Commit 79198b9

Browse files
committed
[InterleavedAccess] Construct interleaved access store with shuffles
- [AArch64]: Interleaved access store can handle more elements than target supported maximum interleaved factor with shuffles.
1 parent e866c44 commit 79198b9

File tree

9 files changed

+428
-18
lines changed

9 files changed

+428
-18
lines changed

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3212,6 +3212,11 @@ class LLVM_ABI TargetLoweringBase {
32123212
/// Default to be the minimum interleave factor: 2.
32133213
virtual unsigned getMaxSupportedInterleaveFactor() const { return 2; }
32143214

3215+
/// Return true if the target interleave with shuffles are cheaper
3216+
virtual bool isProfitableToInterleaveWithGatherScatter() const {
3217+
return false;
3218+
}
3219+
32153220
/// Lower an interleaved load to target specific intrinsics. Return
32163221
/// true on success.
32173222
///

llvm/lib/CodeGen/InterleavedAccessPass.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,8 @@ static bool isDeInterleaveMask(ArrayRef<int> Mask, unsigned &Factor,
239239
/// I.e. <0, LaneLen, ... , LaneLen*(Factor - 1), 1, LaneLen + 1, ...>
240240
/// E.g. For a Factor of 2 (LaneLen=4): <0, 4, 1, 5, 2, 6, 3, 7>
241241
static bool isReInterleaveMask(ShuffleVectorInst *SVI, unsigned &Factor,
242-
unsigned MaxFactor) {
242+
unsigned MaxFactor,
243+
bool InterleaveWithShuffles) {
243244
unsigned NumElts = SVI->getShuffleMask().size();
244245
if (NumElts < 4)
245246
return false;
@@ -250,6 +251,13 @@ static bool isReInterleaveMask(ShuffleVectorInst *SVI, unsigned &Factor,
250251
return true;
251252
}
252253

254+
if (InterleaveWithShuffles) {
255+
for (unsigned i = 1; MaxFactor * i <= 16; i *= 2) {
256+
Factor = i * MaxFactor;
257+
if (SVI->isInterleave(Factor))
258+
return true;
259+
}
260+
}
253261
return false;
254262
}
255263

@@ -528,7 +536,8 @@ bool InterleavedAccessImpl::lowerInterleavedStore(
528536
cast<FixedVectorType>(SVI->getType())->getNumElements();
529537
// Check if the shufflevector is RE-interleave shuffle.
530538
unsigned Factor;
531-
if (!isReInterleaveMask(SVI, Factor, MaxFactor))
539+
if (!isReInterleaveMask(SVI, Factor, MaxFactor,
540+
TLI->isProfitableToInterleaveWithGatherScatter()))
532541
return false;
533542
assert(NumStoredElements % Factor == 0 &&
534543
"number of stored element should be a multiple of Factor");

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 141 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
#include <cctype>
9797
#include <cstdint>
9898
#include <cstdlib>
99+
#include <deque>
99100
#include <iterator>
100101
#include <limits>
101102
#include <optional>
@@ -18025,11 +18026,17 @@ bool AArch64TargetLowering::lowerInterleavedStore(Instruction *Store,
1802518026
unsigned Factor,
1802618027
const APInt &GapMask) const {
1802718028

18028-
assert(Factor >= 2 && Factor <= getMaxSupportedInterleaveFactor() &&
18029-
"Invalid interleave factor");
1803018029
auto *SI = dyn_cast<StoreInst>(Store);
1803118030
if (!SI)
1803218031
return false;
18032+
18033+
if (isProfitableToInterleaveWithGatherScatter() &&
18034+
Factor > getMaxSupportedInterleaveFactor())
18035+
return lowerInterleavedStoreWithShuffle(SI, SVI, Factor);
18036+
18037+
assert(Factor >= 2 && Factor <= getMaxSupportedInterleaveFactor() &&
18038+
"Invalid interleave factor");
18039+
1803318040
assert(!LaneMask && GapMask.popcount() == Factor &&
1803418041
"Unexpected mask on store");
1803518042

@@ -18175,6 +18182,138 @@ bool AArch64TargetLowering::lowerInterleavedStore(Instruction *Store,
1817518182
return true;
1817618183
}
1817718184

18185+
/// If the interleaved vector elements are greater than supported MaxFactor,
18186+
/// interleaving the data with additional shuffles can be used to
18187+
/// achieve the same.
18188+
///
18189+
/// Consider the following data with 8 interleaves which are shuffled to store
18190+
/// stN instructions. Data needs to be stored in this order:
18191+
/// [v0, v1, v2, v3, v4, v5, v6, v7]
18192+
///
18193+
/// v0 v4 v2 v6 v1 v5 v3 v7
18194+
/// | | | | | | | |
18195+
/// \ / \ / \ / \ /
18196+
/// [zip v0,v4] [zip v2,v6] [zip v1,v5] [zip v3,v7] ==> stN = 4
18197+
/// | | | |
18198+
/// \ / \ /
18199+
/// \ / \ /
18200+
/// \ / \ /
18201+
/// [zip [v0,v2,v4,v6]] [zip [v1,v3,v5,v7]] ==> stN = 2
18202+
///
18203+
/// For stN = 4, upper half of interleaved data V0, V1, V2, V3 is stored
18204+
/// with one st4 instruction. Lower half, i.e, V4, V5, V6, V7 is stored with
18205+
/// another st4.
18206+
///
18207+
/// For stN = 2, upper half of interleaved data V0, V1 is stored
18208+
/// with one st2 instruction. Second set V2, V3 is stored with another st2.
18209+
/// Total of 4 st2's are required here.
18210+
bool AArch64TargetLowering::lowerInterleavedStoreWithShuffle(
18211+
StoreInst *SI, ShuffleVectorInst *SVI, unsigned Factor) const {
18212+
unsigned MaxSupportedFactor = getMaxSupportedInterleaveFactor();
18213+
18214+
auto *VecTy = cast<FixedVectorType>(SVI->getType());
18215+
assert(VecTy->getNumElements() % Factor == 0 && "Invalid interleaved store");
18216+
18217+
unsigned LaneLen = VecTy->getNumElements() / Factor;
18218+
Type *EltTy = VecTy->getElementType();
18219+
auto *SubVecTy = FixedVectorType::get(EltTy, Factor);
18220+
18221+
const DataLayout &DL = SI->getModule()->getDataLayout();
18222+
bool UseScalable;
18223+
18224+
// Skip if we do not have NEON and skip illegal vector types. We can
18225+
// "legalize" wide vector types into multiple interleaved accesses as long as
18226+
// the vector types are divisible by 128.
18227+
if (!Subtarget->hasNEON() ||
18228+
!isLegalInterleavedAccessType(SubVecTy, DL, UseScalable))
18229+
return false;
18230+
18231+
if (UseScalable)
18232+
return false;
18233+
18234+
std::deque<Value *> Shuffles;
18235+
Shuffles.push_back(SVI);
18236+
unsigned ConcatLevel = Factor;
18237+
while (ConcatLevel > 1) {
18238+
std::deque<Value *> ShufflesIntermediate;
18239+
ShufflesIntermediate = Shuffles;
18240+
Shuffles.clear();
18241+
while (!ShufflesIntermediate.empty()) {
18242+
ShuffleVectorInst *SFL =
18243+
dyn_cast<ShuffleVectorInst>(ShufflesIntermediate.front());
18244+
if (!SFL)
18245+
break;
18246+
ShufflesIntermediate.pop_front();
18247+
18248+
Value *Op0 = SFL->getOperand(0);
18249+
Value *Op1 = SFL->getOperand(1);
18250+
18251+
Shuffles.push_back(dyn_cast<Value>(Op0));
18252+
Shuffles.push_back(dyn_cast<Value>(Op1));
18253+
}
18254+
if (!ShufflesIntermediate.empty()) {
18255+
Shuffles = ShufflesIntermediate;
18256+
break;
18257+
}
18258+
ConcatLevel = ConcatLevel >> 1;
18259+
}
18260+
18261+
if (Shuffles.size() != Factor)
18262+
return false;
18263+
18264+
IRBuilder<> Builder(SI);
18265+
auto Mask = createInterleaveMask(LaneLen, 2);
18266+
SmallVector<int, 16> UpperHalfMask, LowerHalfMask;
18267+
for (unsigned i = 0; i < (2 * LaneLen); i++) {
18268+
if (i < LaneLen)
18269+
LowerHalfMask.push_back(Mask[i]);
18270+
else
18271+
UpperHalfMask.push_back(Mask[i]);
18272+
}
18273+
18274+
unsigned InterleaveFactor = Factor >> 1;
18275+
while (InterleaveFactor >= MaxSupportedFactor) {
18276+
std::deque<Value *> ShufflesIntermediate;
18277+
ShufflesIntermediate.resize(Factor);
18278+
for (unsigned j = 0; j < Factor; j += (InterleaveFactor * 2)) {
18279+
for (unsigned i = 0; i < InterleaveFactor; i++) {
18280+
auto *Shuffle = Builder.CreateShuffleVector(
18281+
Shuffles[i + j], Shuffles[i + j + InterleaveFactor], LowerHalfMask);
18282+
ShufflesIntermediate[i + j] = Shuffle;
18283+
Shuffle = Builder.CreateShuffleVector(
18284+
Shuffles[i + j], Shuffles[i + j + InterleaveFactor], UpperHalfMask);
18285+
ShufflesIntermediate[i + j + InterleaveFactor] = Shuffle;
18286+
}
18287+
}
18288+
18289+
Shuffles = ShufflesIntermediate;
18290+
InterleaveFactor = InterleaveFactor >> 1;
18291+
}
18292+
18293+
Type *PtrTy = SI->getPointerOperandType();
18294+
auto *STVTy = FixedVectorType::get(SubVecTy->getElementType(), LaneLen);
18295+
18296+
Value *BaseAddr = SI->getPointerOperand();
18297+
Function *StNFunc = getStructuredStoreFunction(
18298+
SI->getModule(), MaxSupportedFactor, UseScalable, STVTy, PtrTy);
18299+
for (unsigned i = 0; i < (Factor / MaxSupportedFactor); i++) {
18300+
SmallVector<Value *, 5> Ops;
18301+
for (unsigned j = 0; j < MaxSupportedFactor; j++)
18302+
Ops.push_back(Shuffles[i * MaxSupportedFactor + j]);
18303+
18304+
if (i > 0) {
18305+
// We will compute the pointer operand of each store from the original
18306+
// base address using GEPs. Cast the base address to a pointer to the
18307+
// scalar element type.
18308+
BaseAddr = Builder.CreateConstGEP1_32(
18309+
SubVecTy->getElementType(), BaseAddr, LaneLen * MaxSupportedFactor);
18310+
}
18311+
Ops.push_back(Builder.CreateBitCast(BaseAddr, PtrTy));
18312+
Builder.CreateCall(StNFunc, Ops);
18313+
}
18314+
return true;
18315+
}
18316+
1817818317
bool AArch64TargetLowering::lowerDeinterleaveIntrinsicToLoad(
1817918318
Instruction *Load, Value *Mask, IntrinsicInst *DI) const {
1818018319
const unsigned Factor = getDeinterleaveIntrinsicFactor(DI->getIntrinsicID());

llvm/lib/Target/AArch64/AArch64ISelLowering.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,10 @@ class AArch64TargetLowering : public TargetLowering {
229229

230230
bool hasPairedLoad(EVT LoadedType, Align &RequiredAlignment) const override;
231231

232+
bool isProfitableToInterleaveWithGatherScatter() const override {
233+
return true;
234+
}
235+
232236
unsigned getMaxSupportedInterleaveFactor() const override { return 4; }
233237

234238
bool lowerInterleavedLoad(Instruction *Load, Value *Mask,
@@ -239,6 +243,9 @@ class AArch64TargetLowering : public TargetLowering {
239243
ShuffleVectorInst *SVI, unsigned Factor,
240244
const APInt &GapMask) const override;
241245

246+
bool lowerInterleavedStoreWithShuffle(StoreInst *SI, ShuffleVectorInst *SVI,
247+
unsigned Factor) const;
248+
242249
bool lowerDeinterleaveIntrinsicToLoad(Instruction *Load, Value *Mask,
243250
IntrinsicInst *DI) const override;
244251

llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4837,19 +4837,47 @@ InstructionCost AArch64TTIImpl::getInterleavedMemoryOpCost(
48374837
if (!VecTy->isScalableTy() && (UseMaskForCond || UseMaskForGaps))
48384838
return InstructionCost::getInvalid();
48394839

4840-
if (!UseMaskForGaps && Factor <= TLI->getMaxSupportedInterleaveFactor()) {
4840+
unsigned NumLoadStores = 1;
4841+
InstructionCost ShuffleCost = 0;
4842+
bool isInterleaveWithShuffle = false;
4843+
unsigned MaxSupportedFactor = TLI->getMaxSupportedInterleaveFactor();
4844+
4845+
auto *SubVecTy =
4846+
VectorType::get(VecVTy->getElementType(),
4847+
VecVTy->getElementCount().divideCoefficientBy(Factor));
4848+
4849+
if (TLI->isProfitableToInterleaveWithGatherScatter() &&
4850+
Opcode == Instruction::Store && (0 == Factor % MaxSupportedFactor) &&
4851+
Factor > MaxSupportedFactor) {
4852+
isInterleaveWithShuffle = true;
4853+
SmallVector<int, 16> Mask;
4854+
// preparing interleave Mask.
4855+
for (unsigned i = 0; i < VecVTy->getElementCount().getKnownMinValue() / 2;
4856+
i++) {
4857+
for (unsigned j = 0; j < 2; j++)
4858+
Mask.push_back(j * Factor + i);
4859+
}
4860+
4861+
NumLoadStores = Factor / MaxSupportedFactor;
4862+
ShuffleCost =
4863+
(Factor * getShuffleCost(TargetTransformInfo::SK_Splice, VecVTy, VecVTy,
4864+
Mask, CostKind, 0, SubVecTy));
4865+
}
4866+
4867+
if (!UseMaskForGaps &&
4868+
(Factor <= MaxSupportedFactor || isInterleaveWithShuffle)) {
48414869
unsigned MinElts = VecVTy->getElementCount().getKnownMinValue();
4842-
auto *SubVecTy =
4843-
VectorType::get(VecVTy->getElementType(),
4844-
VecVTy->getElementCount().divideCoefficientBy(Factor));
48454870

48464871
// ldN/stN only support legal vector types of size 64 or 128 in bits.
48474872
// Accesses having vector types that are a multiple of 128 bits can be
48484873
// matched to more than one ldN/stN instruction.
48494874
bool UseScalable;
48504875
if (MinElts % Factor == 0 &&
48514876
TLI->isLegalInterleavedAccessType(SubVecTy, DL, UseScalable))
4852-
return Factor * TLI->getNumInterleavedAccesses(SubVecTy, DL, UseScalable);
4877+
return (Factor *
4878+
TLI->getNumInterleavedAccesses(SubVecTy, DL, UseScalable) *
4879+
NumLoadStores) +
4880+
ShuffleCost;
48534881
}
48544882

48554883
return BaseT::getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,

llvm/test/CodeGen/AArch64/vldn_shuffle.ll

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,111 @@ entry:
730730
ret void
731731
}
732732

733+
define void @store_factor8(ptr %ptr, <4 x i32> %a0, <4 x i32> %a1, <4 x i32> %a2, <4 x i32> %a3,
734+
<4 x i32> %a4, <4 x i32> %a5, <4 x i32> %a6, <4 x i32> %a7) {
735+
; CHECK-LABEL: store_factor8:
736+
; CHECK: .Lfunc_begin17:
737+
; CHECK-NEXT: .cfi_startproc
738+
; CHECK-NEXT: // %bb.0:
739+
; CHECK: zip1 [[V1:.*s]], [[I1:.*s]], [[I5:.*s]]
740+
; CHECK-NEXT: zip2 [[V5:.*s]], [[I1]], [[I5]]
741+
; CHECK-NEXT: zip1 [[V2:.*s]], [[I2:.*s]], [[I6:.*s]]
742+
; CHECK-NEXT: zip2 [[V6:.*s]], [[I2]], [[I6]]
743+
; CHECK-NEXT: zip1 [[V3:.*s]], [[I3:.*s]], [[I7:.*s]]
744+
; CHECK-NEXT: zip2 [[V7:.*s]], [[I3]], [[I7]]
745+
; CHECK-NEXT: zip1 [[V4:.*s]], [[I4:.*s]], [[I8:.*s]]
746+
; CHECK-NEXT: zip2 [[V8:.*s]], [[I4]], [[I8]]
747+
; CHECK-NEXT: st4 { [[V1]], [[V2]], [[V3]], [[V4]] }, [x0], #64
748+
; CHECK-NEXT: st4 { [[V5]], [[V6]], [[V7]], [[V8]] }, [x0]
749+
; CHECK-NEXT: ret
750+
751+
%v0 = shufflevector <4 x i32> %a0, <4 x i32> %a1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
752+
%v1 = shufflevector <4 x i32> %a2, <4 x i32> %a3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
753+
%v2 = shufflevector <4 x i32> %a4, <4 x i32> %a5, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
754+
%v3 = shufflevector <4 x i32> %a6, <4 x i32> %a7, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
755+
756+
%s0 = shufflevector <8 x i32> %v0, <8 x i32> %v1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
757+
%s1 = shufflevector <8 x i32> %v2, <8 x i32> %v3, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
758+
759+
%interleaved.vec = shufflevector <16 x i32> %s0, <16 x i32> %s1, <32 x i32> <i32 0, i32 4, i32 8, i32 12, i32 16, i32 20, i32 24, i32 28, i32 1, i32 5, i32 9, i32 13, i32 17, i32 21, i32 25, i32 29, i32 2, i32 6, i32 10, i32 14, i32 18, i32 22, i32 26, i32 30, i32 3, i32 7, i32 11, i32 15, i32 19, i32 23, i32 27, i32 31>
760+
store <32 x i32> %interleaved.vec, ptr %ptr, align 4
761+
ret void
762+
}
763+
764+
define void @store_factor16(ptr %ptr, <4 x i32> %a0, <4 x i32> %a1, <4 x i32> %a2, <4 x i32> %a3,
765+
<4 x i32> %a4, <4 x i32> %a5, <4 x i32> %a6, <4 x i32> %a7,
766+
<4 x i32> %a8, <4 x i32> %a9, <4 x i32> %a10, <4 x i32> %a11,
767+
<4 x i32> %a12, <4 x i32> %a13, <4 x i32> %a14, <4 x i32> %a15) {
768+
; CHECK-LABEL: store_factor16:
769+
; CHECK: .Lfunc_begin18:
770+
; CHECK-NEXT: .cfi_startproc
771+
; CHECK-NEXT: // %bb.0:
772+
; CHECK: zip1 [[V05:.*s]], [[I05:.*s]], [[I13:.*s]]
773+
; CHECK-NEXT: zip1 [[V01:.*s]], [[I01:.*s]], [[I09:.*s]]
774+
; CHECK-NEXT: zip1 [[V02:.*s]], [[I02:.*s]], [[I10:.*s]]
775+
; CHECK-NEXT: zip1 [[V06:.*s]], [[I06:.*s]], [[I14:.*s]]
776+
; CHECK-NEXT: zip1 [[V07:.*s]], [[I07:.*s]], [[I15:.*s]]
777+
; CHECK-NEXT: zip2 [[V09:.*s]], [[I01]], [[I09]]
778+
; CHECK-NEXT: zip2 [[V13:.*s]], [[I05]], [[I13]]
779+
; CHECK-NEXT: zip1 [[V03:.*s]], [[I03:.*s]], [[I11:.*s]]
780+
; CHECK-NEXT: zip1 [[V04:.*s]], [[I04:.*s]], [[I12:.*s]]
781+
; CHECK-NEXT: zip1 [[V08:.*s]], [[I08:.*s]], [[I16:.*s]]
782+
; CHECK-NEXT: zip2 [[V10:.*s]], [[I02]], [[I10]]
783+
; CHECK-NEXT: zip2 [[V14:.*s]], [[I06]], [[I14]]
784+
; CHECK-NEXT: zip2 [[V11:.*s]], [[I03]], [[I11]]
785+
; CHECK-NEXT: zip1 [[V17:.*s]], [[V01]], [[V05]]
786+
; CHECK-NEXT: zip2 [[V15:.*s]], [[I07]], [[I15]]
787+
; CHECK-NEXT: zip2 [[V21:.*s]], [[V01]], [[V05]]
788+
; CHECK-NEXT: zip1 [[V18:.*s]], [[V02]], [[V06]]
789+
; CHECK-NEXT: zip2 [[V12:.*s]], [[I04]], [[I12]]
790+
; CHECK-NEXT: zip2 [[V16:.*s]], [[I08]], [[I16]]
791+
; CHECK-NEXT: zip1 [[V19:.*s]], [[V03]], [[V07]]
792+
; CHECK-NEXT: zip2 [[V22:.*s]], [[V02]], [[V06]]
793+
; CHECK-NEXT: zip1 [[V25:.*s]], [[V09]], [[V13]]
794+
; CHECK-NEXT: zip1 [[V20:.*s]], [[V04]], [[V08]]
795+
; CHECK-NEXT: zip2 [[V23:.*s]], [[V03]], [[V07]]
796+
; CHECK-NEXT: zip1 [[V26:.*s]], [[V10]], [[V14]]
797+
; CHECK-NEXT: zip2 [[V29:.*s]], [[V09]], [[V13]]
798+
; CHECK-NEXT: zip2 [[V24:.*s]], [[V04]], [[V08]]
799+
; CHECK-NEXT: zip1 [[V27:.*s]], [[V11]], [[V15]]
800+
; CHECK-NEXT: zip2 [[V30:.*s]], [[V10]], [[V14]]
801+
; CHECK-NEXT: zip1 [[V28:.*s]], [[V12]], [[V16]]
802+
; CHECK-NEXT: zip2 [[V31:.*s]], [[V11]], [[V15]]
803+
; CHECK-NEXT: zip2 [[V32:.*s]], [[V12]], [[V16]]
804+
; CHECK-NEXT: st4 { [[V17]], [[V18]], [[V19]], [[V20]] }, [x8], #64
805+
; CHECK-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload
806+
; CHECK-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload
807+
; CHECK-NEXT: st4 { [[V21]], [[V22]], [[V23]], [[V24]] }, [x8]
808+
; CHECK-NEXT: add x8, x0, #128
809+
; CHECK-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload
810+
; CHECK-NEXT: st4 { [[V25]], [[V26]], [[V27]], [[V28]] }, [x8]
811+
; CHECK-NEXT: add x8, x0, #192
812+
; CHECK-NEXT: st4 { [[V29]], [[V30]], [[V31]], [[V32]] }, [x8]
813+
; CHECK-NEXT: ldp d15, d14, [sp], #64 // 16-byte Folded Reload
814+
; CHECK-NEXT: ret
815+
816+
%v0 = shufflevector <4 x i32> %a0, <4 x i32> %a1, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
817+
%v1 = shufflevector <4 x i32> %a2, <4 x i32> %a3, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
818+
%v2 = shufflevector <4 x i32> %a4, <4 x i32> %a5, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
819+
%v3 = shufflevector <4 x i32> %a6, <4 x i32> %a7, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
820+
%v4 = shufflevector <4 x i32> %a8, <4 x i32> %a9, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
821+
%v5 = shufflevector <4 x i32> %a10, <4 x i32> %a11, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
822+
%v6 = shufflevector <4 x i32> %a12, <4 x i32> %a13, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
823+
%v7 = shufflevector <4 x i32> %a14, <4 x i32> %a15, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
824+
825+
%s0 = shufflevector <8 x i32> %v0, <8 x i32> %v1, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
826+
%s1 = shufflevector <8 x i32> %v2, <8 x i32> %v3, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
827+
%s2 = shufflevector <8 x i32> %v4, <8 x i32> %v5, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
828+
%s3 = shufflevector <8 x i32> %v6, <8 x i32> %v7, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
829+
830+
%d0 = shufflevector <16 x i32> %s0, <16 x i32> %s1, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
831+
%d1 = shufflevector <16 x i32> %s2, <16 x i32> %s3, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
832+
833+
%interleaved.vec = shufflevector <32 x i32> %d0, <32 x i32> %d1, <64 x i32> <i32 0, i32 4, i32 8, i32 12, i32 16, i32 20, i32 24, i32 28, i32 32, i32 36, i32 40, i32 44, i32 48, i32 52, i32 56, i32 60, i32 1, i32 5, i32 9, i32 13, i32 17, i32 21, i32 25, i32 29, i32 33, i32 37, i32 41, i32 45, i32 49, i32 53, i32 57, i32 61, i32 2, i32 6, i32 10, i32 14, i32 18, i32 22, i32 26, i32 30, i32 34, i32 38, i32 42, i32 46, i32 50, i32 54, i32 58, i32 62, i32 3, i32 7, i32 11, i32 15, i32 19, i32 23, i32 27, i32 31, i32 35, i32 39, i32 43, i32 47, i32 51, i32 55, i32 59, i32 63>
834+
store <64 x i32> %interleaved.vec, ptr %ptr, align 4
835+
ret void
836+
}
837+
733838
declare void @llvm.dbg.value(metadata, metadata, metadata)
734839

735840
!llvm.dbg.cu = !{!0}

0 commit comments

Comments
 (0)