Skip to content

Commit 0209739

Browse files
authored
[InterleavedAccessPass]: Ensure that dead nodes get erased only once (#122643)
Use SmallSetVector instead of SmallVector to avoid duplication, so that dead nodes get erased/deleted only once.
1 parent ea4a879 commit 0209739

File tree

2 files changed

+35
-20
lines changed

2 files changed

+35
-20
lines changed

llvm/lib/CodeGen/InterleavedAccessPass.cpp

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,21 +100,21 @@ class InterleavedAccessImpl {
100100

101101
/// Transform an interleaved load into target specific intrinsics.
102102
bool lowerInterleavedLoad(LoadInst *LI,
103-
SmallVectorImpl<Instruction *> &DeadInsts);
103+
SmallSetVector<Instruction *, 32> &DeadInsts);
104104

105105
/// Transform an interleaved store into target specific intrinsics.
106106
bool lowerInterleavedStore(StoreInst *SI,
107-
SmallVectorImpl<Instruction *> &DeadInsts);
107+
SmallSetVector<Instruction *, 32> &DeadInsts);
108108

109109
/// Transform a load and a deinterleave intrinsic into target specific
110110
/// instructions.
111111
bool lowerDeinterleaveIntrinsic(IntrinsicInst *II,
112-
SmallVectorImpl<Instruction *> &DeadInsts);
112+
SmallSetVector<Instruction *, 32> &DeadInsts);
113113

114114
/// Transform an interleave intrinsic and a store into target specific
115115
/// instructions.
116116
bool lowerInterleaveIntrinsic(IntrinsicInst *II,
117-
SmallVectorImpl<Instruction *> &DeadInsts);
117+
SmallSetVector<Instruction *, 32> &DeadInsts);
118118

119119
/// Returns true if the uses of an interleaved load by the
120120
/// extractelement instructions in \p Extracts can be replaced by uses of the
@@ -249,7 +249,7 @@ static bool isReInterleaveMask(ShuffleVectorInst *SVI, unsigned &Factor,
249249
}
250250

251251
bool InterleavedAccessImpl::lowerInterleavedLoad(
252-
LoadInst *LI, SmallVectorImpl<Instruction *> &DeadInsts) {
252+
LoadInst *LI, SmallSetVector<Instruction *, 32> &DeadInsts) {
253253
if (!LI->isSimple() || isa<ScalableVectorType>(LI->getType()))
254254
return false;
255255

@@ -348,9 +348,9 @@ bool InterleavedAccessImpl::lowerInterleavedLoad(
348348
return !Extracts.empty() || BinOpShuffleChanged;
349349
}
350350

351-
append_range(DeadInsts, Shuffles);
351+
DeadInsts.insert(Shuffles.begin(), Shuffles.end());
352352

353-
DeadInsts.push_back(LI);
353+
DeadInsts.insert(LI);
354354
return true;
355355
}
356356

@@ -453,7 +453,7 @@ bool InterleavedAccessImpl::tryReplaceExtracts(
453453
}
454454

455455
bool InterleavedAccessImpl::lowerInterleavedStore(
456-
StoreInst *SI, SmallVectorImpl<Instruction *> &DeadInsts) {
456+
StoreInst *SI, SmallSetVector<Instruction *, 32> &DeadInsts) {
457457
if (!SI->isSimple())
458458
return false;
459459

@@ -473,13 +473,13 @@ bool InterleavedAccessImpl::lowerInterleavedStore(
473473
return false;
474474

475475
// Already have a new target specific interleaved store. Erase the old store.
476-
DeadInsts.push_back(SI);
477-
DeadInsts.push_back(SVI);
476+
DeadInsts.insert(SI);
477+
DeadInsts.insert(SVI);
478478
return true;
479479
}
480480

481481
bool InterleavedAccessImpl::lowerDeinterleaveIntrinsic(
482-
IntrinsicInst *DI, SmallVectorImpl<Instruction *> &DeadInsts) {
482+
IntrinsicInst *DI, SmallSetVector<Instruction *, 32> &DeadInsts) {
483483
LoadInst *LI = dyn_cast<LoadInst>(DI->getOperand(0));
484484

485485
if (!LI || !LI->hasOneUse() || !LI->isSimple())
@@ -488,17 +488,19 @@ bool InterleavedAccessImpl::lowerDeinterleaveIntrinsic(
488488
LLVM_DEBUG(dbgs() << "IA: Found a deinterleave intrinsic: " << *DI << "\n");
489489

490490
// Try and match this with target specific intrinsics.
491-
if (!TLI->lowerDeinterleaveIntrinsicToLoad(DI, LI, DeadInsts))
491+
SmallVector<Instruction *, 4> DeinterleaveDeadInsts;
492+
if (!TLI->lowerDeinterleaveIntrinsicToLoad(DI, LI, DeinterleaveDeadInsts))
492493
return false;
493494

495+
DeadInsts.insert(DeinterleaveDeadInsts.begin(), DeinterleaveDeadInsts.end());
494496
// We now have a target-specific load, so delete the old one.
495-
DeadInsts.push_back(DI);
496-
DeadInsts.push_back(LI);
497+
DeadInsts.insert(DI);
498+
DeadInsts.insert(LI);
497499
return true;
498500
}
499501

500502
bool InterleavedAccessImpl::lowerInterleaveIntrinsic(
501-
IntrinsicInst *II, SmallVectorImpl<Instruction *> &DeadInsts) {
503+
IntrinsicInst *II, SmallSetVector<Instruction *, 32> &DeadInsts) {
502504
if (!II->hasOneUse())
503505
return false;
504506

@@ -515,16 +517,15 @@ bool InterleavedAccessImpl::lowerInterleaveIntrinsic(
515517
return false;
516518

517519
// We now have a target-specific store, so delete the old one.
518-
DeadInsts.push_back(SI);
519-
DeadInsts.push_back(II);
520-
DeadInsts.insert(DeadInsts.end(), InterleaveDeadInsts.begin(),
521-
InterleaveDeadInsts.end());
520+
DeadInsts.insert(SI);
521+
DeadInsts.insert(II);
522+
DeadInsts.insert(InterleaveDeadInsts.begin(), InterleaveDeadInsts.end());
522523
return true;
523524
}
524525

525526
bool InterleavedAccessImpl::runOnFunction(Function &F) {
526527
// Holds dead instructions that will be erased later.
527-
SmallVector<Instruction *, 32> DeadInsts;
528+
SmallSetVector<Instruction *, 32> DeadInsts;
528529
bool Changed = false;
529530

530531
for (auto &I : instructions(F)) {

llvm/test/Transforms/InterleavedAccess/AArch64/sve-interleave4.ll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,17 @@ define void @mix_interleave4_interleave2(ptr %dst1, ptr %dst2, <vscale x 4 x i32
5555
store <vscale x 8 x i32> %interleaved, ptr %dst2, align 4
5656
ret void
5757
}
58+
59+
; This case tests when the interleave is using same parameter twice,
60+
; the dead parameter will not get deleted twice.
61+
define void @duplicate_by_interleave(<vscale x 4 x i32> %A, <vscale x 4 x i32> %B, ptr writeonly %AB_duplicate) {
62+
; CHECK-LABEL: define void @duplicate_by_interleave
63+
; CHECK-SAME: (<vscale x 4 x i32> [[A:%.*]], <vscale x 4 x i32> [[B:%.*]], ptr writeonly [[AB_DUPLICATE:%.*]]) #[[ATTR0]] {
64+
; CHECK-NEXT: call void @llvm.aarch64.sve.st4.nxv4i32(<vscale x 4 x i32> [[A]], <vscale x 4 x i32> [[A]], <vscale x 4 x i32> [[B]], <vscale x 4 x i32> [[B]], <vscale x 4 x i1> splat (i1 true), ptr [[AB_DUPLICATE]])
65+
; CHECK-NEXT: ret void
66+
;
67+
%interleave = tail call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> %A, <vscale x 4 x i32> %B)
68+
%duplicate_by_interleave = tail call <vscale x 16 x i32> @llvm.vector.interleave2.nxv16i32(<vscale x 8 x i32> %interleave, <vscale x 8 x i32> %interleave)
69+
store <vscale x 16 x i32> %duplicate_by_interleave, ptr %AB_duplicate, align 4
70+
ret void
71+
}

0 commit comments

Comments
 (0)