Skip to content

Commit 62625a7

Browse files
committed
Rewrite to use SSAUpdater
1 parent cf3bbdc commit 62625a7

File tree

3 files changed

+105
-114
lines changed

3 files changed

+105
-114
lines changed

llvm/lib/Transforms/Scalar/SROA.cpp

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
8585
#include "llvm/Transforms/Utils/Local.h"
8686
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
87+
#include "llvm/Transforms/Utils/SSAUpdater.h"
8788
#include <algorithm>
8889
#include <cassert>
8990
#include <cstddef>
@@ -1401,9 +1402,8 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
14011402
Function *Callee = CB.getCalledFunction();
14021403
if (Callee && CB.arg_size() == Callee->arg_size() &&
14031404
!CB.hasOperandBundles() && all_of(enumerate(CB.args()), [&](auto V) {
1404-
return V.value() != *U ||
1405-
(Callee->getArg(V.index())->hasNoCaptureAttr() &&
1406-
Callee->getArg(V.index())->onlyReadsMemory());
1405+
return V.value() != *U || (CB.doesNotCapture(V.index()) &&
1406+
CB.onlyReadsMemory(V.index()));
14071407
})) {
14081408
PI.setEscapedReadOnly(&CB);
14091409
return;
@@ -5479,51 +5479,71 @@ void SROA::clobberUse(Use &U) {
54795479
}
54805480
}
54815481

5482-
bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
5483-
for (auto &P : AS.partitions()) {
5484-
StoreInst *Store = nullptr;
5485-
// Make sure all the slices inside the partition are the full width.
5486-
if (any_of(P, [&P](Slice &S) {
5487-
return S.beginOffset() != P.beginOffset() ||
5488-
S.beginOffset() != P.beginOffset();
5489-
}))
5490-
continue;
5482+
// A basic LoadAndStorePromoter that does not remove store nodes.
5483+
class BasicLoadAndStorePromoter : public LoadAndStorePromoter {
5484+
public:
5485+
BasicLoadAndStorePromoter(ArrayRef<const Instruction *> Insts, SSAUpdater &S)
5486+
: LoadAndStorePromoter(Insts, S) {}
5487+
bool shouldDelete(Instruction *I) const override {
5488+
return !isa<StoreInst>(I);
5489+
}
5490+
};
54915491

5492-
// Check there is a single store and nothing else other than loads.
5493-
for (Slice &S : P) {
5494-
if (S.isDead())
5495-
continue;
5496-
if (auto *St = dyn_cast<StoreInst>(S.getUse()->getUser())) {
5497-
if (Store) {
5498-
Store = nullptr;
5499-
break;
5500-
}
5501-
Store = St;
5502-
} else if (!isa<LoadInst>(S.getUse()->getUser()) &&
5503-
!isAssumeLikeIntrinsic(
5504-
cast<Instruction>(S.getUse()->getUser()))) {
5505-
Store = nullptr;
5506-
break;
5492+
bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
5493+
// Look through each "partition", looking for slices with the same start/end
5494+
// that do not overlap with any before them. The slices are sorted by
5495+
// increasing beginOffset. We don't use AS.partitions(), as it will use a more
5496+
// sophisticated algorithm that takes splittable slices into account.
5497+
auto PartitionBegin = AS.begin();
5498+
auto PartitionEnd = PartitionBegin;
5499+
uint64_t BeginOffset = PartitionBegin->beginOffset();
5500+
uint64_t EndOffset = PartitionBegin->endOffset();
5501+
while (PartitionBegin != AS.end()) {
5502+
bool AllSameAndValid = true;
5503+
SmallVector<Instruction *> Insts;
5504+
Type *PartitionType = nullptr;
5505+
while (PartitionEnd != AS.end() &&
5506+
(PartitionEnd->beginOffset() < EndOffset ||
5507+
PartitionEnd->endOffset() <= EndOffset)) {
5508+
EndOffset = std::max(EndOffset, PartitionEnd->endOffset());
5509+
if (AllSameAndValid) {
5510+
AllSameAndValid &= PartitionEnd->beginOffset() == BeginOffset &&
5511+
PartitionEnd->endOffset() == EndOffset;
5512+
Instruction *User =
5513+
cast<Instruction>(PartitionEnd->getUse()->getUser());
5514+
if (isa<LoadInst>(User) || isa<StoreInst>(User)) {
5515+
// LoadAndStorePromoter requires all the types are the same.
5516+
Type *UserTy = getLoadStoreType(User);
5517+
if (PartitionType && UserTy != PartitionType)
5518+
AllSameAndValid = false;
5519+
PartitionType = UserTy;
5520+
Insts.push_back(User);
5521+
} else if (!isAssumeLikeIntrinsic(User))
5522+
AllSameAndValid = false;
55075523
}
5524+
++PartitionEnd;
55085525
}
55095526

5510-
if (!Store)
5511-
continue;
5512-
5513-
// Replace loads by the value that was stored.
5514-
for (Slice &S : P) {
5515-
if (auto *Ld = dyn_cast<LoadInst>(S.getUse()->getUser())) {
5516-
if (DTU->getDomTree().dominates(Store, Ld)) {
5517-
if (Store->getValueOperand()->getType() == Ld->getType()) {
5518-
LLVM_DEBUG(dbgs() << " Replacing " << *Ld << " with "
5519-
<< *Store->getValueOperand() << "\n");
5520-
Ld->replaceAllUsesWith(Store->getValueOperand());
5521-
}
5522-
}
5523-
}
5527+
// So long as all the slices start and end offsets matched, update loads to
5528+
// the values stored in the partition.
5529+
if (AllSameAndValid && !Insts.empty()) {
5530+
LLVM_DEBUG(dbgs() << "Propagate values on slice [" << BeginOffset << ", "
5531+
<< EndOffset << ")\n");
5532+
SmallVector<PHINode *, 4> NewPHIs;
5533+
SSAUpdater SSA(&NewPHIs);
5534+
BasicLoadAndStorePromoter Promoter(Insts, SSA);
5535+
// Add a zero value at the point of the alloca, to prevent the SSA updater
5536+
// replacing loads with poison which would not be valid for padded loads.
5537+
SSA.AddAvailableValue(AI.getParent(),
5538+
Constant::getNullValue(PartitionType));
5539+
Promoter.run(Insts);
55245540
}
5525-
}
55265541

5542+
// Step on to the next partition.
5543+
PartitionBegin = PartitionEnd;
5544+
BeginOffset = PartitionBegin->beginOffset();
5545+
EndOffset = PartitionBegin->endOffset();
5546+
}
55275547
return true;
55285548
}
55295549

0 commit comments

Comments
 (0)