Skip to content

Commit e3676aa

Browse files
committed
Revert "[SROA] Optimize reloaded values in allocas that escape into readonly nocapture calls. (#116645)"
Causing buffer overflow: SUMMARY: AddressSanitizer: heap-buffer-overflow llvm/lib/Transforms/Scalar/SROA.cpp:5552:35 This reverts commit 5e247d7.
1 parent 7071cd3 commit e3676aa

File tree

6 files changed

+82
-191
lines changed

6 files changed

+82
-191
lines changed

llvm/include/llvm/Analysis/PtrUseVisitor.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,6 @@ class PtrUseVisitorBase {
6464
/// Is the pointer escaped at some point?
6565
bool isEscaped() const { return EscapedInfo != nullptr; }
6666

67-
/// Is the pointer escaped into a read-only nocapture call at some point?
68-
bool isEscapedReadOnly() const { return EscapedReadOnly != nullptr; }
69-
7067
/// Get the instruction causing the visit to abort.
7168
/// \returns a pointer to the instruction causing the abort if one is
7269
/// available; otherwise returns null.
@@ -77,10 +74,6 @@ class PtrUseVisitorBase {
7774
/// is available; otherwise returns null.
7875
Instruction *getEscapingInst() const { return EscapedInfo; }
7976

80-
/// Get the instruction causing the pointer to escape which is a read-only
81-
/// nocapture call.
82-
Instruction *getEscapedReadOnlyInst() const { return EscapedReadOnly; }
83-
8477
/// Mark the visit as aborted. Intended for use in a void return.
8578
/// \param I The instruction which caused the visit to abort, if available.
8679
void setAborted(Instruction *I) {
@@ -95,12 +88,6 @@ class PtrUseVisitorBase {
9588
EscapedInfo = I;
9689
}
9790

98-
/// Mark the pointer as escaped into a readonly-nocapture call.
99-
void setEscapedReadOnly(Instruction *I) {
100-
assert(I && "Expected a valid pointer in setEscapedReadOnly");
101-
EscapedReadOnly = I;
102-
}
103-
10491
/// Mark the pointer as escaped, and the visit as aborted. Intended
10592
/// for use in a void return.
10693
/// \param I The instruction which both escapes the pointer and aborts the
@@ -113,7 +100,6 @@ class PtrUseVisitorBase {
113100
private:
114101
Instruction *AbortedInfo = nullptr;
115102
Instruction *EscapedInfo = nullptr;
116-
Instruction *EscapedReadOnly = nullptr;
117103
};
118104

119105
protected:

llvm/include/llvm/Transforms/Utils/SSAUpdater.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,6 @@ class LoadAndStorePromoter {
188188
/// Return false if a sub-class wants to keep one of the loads/stores
189189
/// after the SSA construction.
190190
virtual bool shouldDelete(Instruction *I) const { return true; }
191-
192-
/// Return the value to use for the point in the code that the alloca is
193-
/// positioned. This will only be used if an Alloca is included in Insts,
194-
/// otherwise the value of a uninitialized load will be assumed to be poison.
195-
virtual Value *getValueToUseForAlloca(Instruction *AI) const {
196-
return nullptr;
197-
}
198191
};
199192

200193
} // end namespace llvm

llvm/lib/Transforms/Scalar/SROA.cpp

Lines changed: 1 addition & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343
#include "llvm/Analysis/GlobalsModRef.h"
4444
#include "llvm/Analysis/Loads.h"
4545
#include "llvm/Analysis/PtrUseVisitor.h"
46-
#include "llvm/Analysis/ValueTracking.h"
4746
#include "llvm/Config/llvm-config.h"
4847
#include "llvm/IR/BasicBlock.h"
4948
#include "llvm/IR/Constant.h"
@@ -84,7 +83,6 @@
8483
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
8584
#include "llvm/Transforms/Utils/Local.h"
8685
#include "llvm/Transforms/Utils/PromoteMemToReg.h"
87-
#include "llvm/Transforms/Utils/SSAUpdater.h"
8886
#include <algorithm>
8987
#include <cassert>
9088
#include <cstddef>
@@ -248,7 +246,6 @@ class SROA {
248246
bool presplitLoadsAndStores(AllocaInst &AI, AllocaSlices &AS);
249247
AllocaInst *rewritePartition(AllocaInst &AI, AllocaSlices &AS, Partition &P);
250248
bool splitAlloca(AllocaInst &AI, AllocaSlices &AS);
251-
bool propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS);
252249
std::pair<bool /*Changed*/, bool /*CFGChanged*/> runOnAlloca(AllocaInst &AI);
253250
void clobberUse(Use &U);
254251
bool deleteDeadInstructions(SmallPtrSetImpl<AllocaInst *> &DeletedAllocas);
@@ -601,7 +598,6 @@ class AllocaSlices {
601598
/// If this is true, the slices are never fully built and should be
602599
/// ignored.
603600
bool isEscaped() const { return PointerEscapingInstr; }
604-
bool isEscapedReadOnly() const { return PointerEscapingInstrReadOnly; }
605601

606602
/// Support for iterating over the slices.
607603
/// @{
@@ -684,7 +680,6 @@ class AllocaSlices {
684680
/// store a pointer to that here and abort trying to form slices of the
685681
/// alloca. This will be null if the alloca slices are analyzed successfully.
686682
Instruction *PointerEscapingInstr;
687-
Instruction *PointerEscapingInstrReadOnly;
688683

689684
/// The slices of the alloca.
690685
///
@@ -1395,26 +1390,14 @@ class AllocaSlices::SliceBuilder : public PtrUseVisitor<SliceBuilder> {
13951390

13961391
/// Disable SROA entirely if there are unhandled users of the alloca.
13971392
void visitInstruction(Instruction &I) { PI.setAborted(&I); }
1398-
1399-
void visitCallBase(CallBase &CB) {
1400-
// If the call operand is NoCapture ReadOnly, then we mark it as
1401-
// EscapedReadOnly.
1402-
if (CB.doesNotCapture(U->getOperandNo()) &&
1403-
CB.onlyReadsMemory(U->getOperandNo())) {
1404-
PI.setEscapedReadOnly(&CB);
1405-
return;
1406-
}
1407-
1408-
Base::visitCallBase(CB);
1409-
}
14101393
};
14111394

14121395
AllocaSlices::AllocaSlices(const DataLayout &DL, AllocaInst &AI)
14131396
:
14141397
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
14151398
AI(AI),
14161399
#endif
1417-
PointerEscapingInstr(nullptr), PointerEscapingInstrReadOnly(nullptr) {
1400+
PointerEscapingInstr(nullptr) {
14181401
SliceBuilder PB(DL, AI, *this);
14191402
SliceBuilder::PtrInfo PtrI = PB.visitPtr(AI);
14201403
if (PtrI.isEscaped() || PtrI.isAborted()) {
@@ -1425,7 +1408,6 @@ AllocaSlices::AllocaSlices(const DataLayout &DL, AllocaInst &AI)
14251408
assert(PointerEscapingInstr && "Did not track a bad instruction");
14261409
return;
14271410
}
1428-
PointerEscapingInstrReadOnly = PtrI.getEscapedReadOnlyInst();
14291411

14301412
llvm::erase_if(Slices, [](const Slice &S) { return S.isDead(); });
14311413

@@ -1463,9 +1445,6 @@ void AllocaSlices::print(raw_ostream &OS) const {
14631445
return;
14641446
}
14651447

1466-
if (PointerEscapingInstrReadOnly)
1467-
OS << "Escapes into ReadOnly: " << *PointerEscapingInstrReadOnly << "\n";
1468-
14691448
OS << "Slices of alloca: " << AI << "\n";
14701449
for (const_iterator I = begin(), E = end(); I != E; ++I)
14711450
print(OS, I);
@@ -5475,86 +5454,6 @@ void SROA::clobberUse(Use &U) {
54755454
}
54765455
}
54775456

5478-
/// A basic LoadAndStorePromoter that does not remove store nodes.
5479-
class BasicLoadAndStorePromoter : public LoadAndStorePromoter {
5480-
public:
5481-
BasicLoadAndStorePromoter(ArrayRef<const Instruction *> Insts, SSAUpdater &S,
5482-
Type *ZeroType)
5483-
: LoadAndStorePromoter(Insts, S), ZeroType(ZeroType) {}
5484-
bool shouldDelete(Instruction *I) const override {
5485-
return !isa<StoreInst>(I) && !isa<AllocaInst>(I);
5486-
}
5487-
5488-
Value *getValueToUseForAlloca(Instruction *I) const override {
5489-
return UndefValue::get(ZeroType);
5490-
}
5491-
5492-
private:
5493-
Type *ZeroType;
5494-
};
5495-
5496-
bool SROA::propagateStoredValuesToLoads(AllocaInst &AI, AllocaSlices &AS) {
5497-
// Look through each "partition", looking for slices with the same start/end
5498-
// that do not overlap with any before them. The slices are sorted by
5499-
// increasing beginOffset. We don't use AS.partitions(), as it will use a more
5500-
// sophisticated algorithm that takes splittable slices into account.
5501-
auto PartitionBegin = AS.begin();
5502-
auto PartitionEnd = PartitionBegin;
5503-
uint64_t BeginOffset = PartitionBegin->beginOffset();
5504-
uint64_t EndOffset = PartitionBegin->endOffset();
5505-
while (PartitionBegin != AS.end()) {
5506-
bool AllSameAndValid = true;
5507-
SmallVector<Instruction *> Insts;
5508-
Type *PartitionType = nullptr;
5509-
while (PartitionEnd != AS.end() &&
5510-
(PartitionEnd->beginOffset() < EndOffset ||
5511-
PartitionEnd->endOffset() <= EndOffset)) {
5512-
if (AllSameAndValid) {
5513-
AllSameAndValid &= PartitionEnd->beginOffset() == BeginOffset &&
5514-
PartitionEnd->endOffset() == EndOffset;
5515-
Instruction *User =
5516-
cast<Instruction>(PartitionEnd->getUse()->getUser());
5517-
if (auto *LI = dyn_cast<LoadInst>(User)) {
5518-
Type *UserTy = LI->getType();
5519-
// LoadAndStorePromoter requires all the types to be the same.
5520-
if (!LI->isSimple() || (PartitionType && UserTy != PartitionType))
5521-
AllSameAndValid = false;
5522-
PartitionType = UserTy;
5523-
Insts.push_back(User);
5524-
} else if (auto *SI = dyn_cast<StoreInst>(User)) {
5525-
Type *UserTy = SI->getValueOperand()->getType();
5526-
if (!SI->isSimple() || PartitionType && UserTy != PartitionType)
5527-
AllSameAndValid = false;
5528-
PartitionType = UserTy;
5529-
Insts.push_back(User);
5530-
} else if (!isAssumeLikeIntrinsic(User)) {
5531-
AllSameAndValid = false;
5532-
}
5533-
}
5534-
EndOffset = std::max(EndOffset, PartitionEnd->endOffset());
5535-
++PartitionEnd;
5536-
}
5537-
5538-
// So long as all the slices start and end offsets matched, update loads to
5539-
// the values stored in the partition.
5540-
if (AllSameAndValid && !Insts.empty()) {
5541-
LLVM_DEBUG(dbgs() << "Propagate values on slice [" << BeginOffset << ", "
5542-
<< EndOffset << ")\n");
5543-
SmallVector<PHINode *, 4> NewPHIs;
5544-
SSAUpdater SSA(&NewPHIs);
5545-
Insts.push_back(&AI);
5546-
BasicLoadAndStorePromoter Promoter(Insts, SSA, PartitionType);
5547-
Promoter.run(Insts);
5548-
}
5549-
5550-
// Step on to the next partition.
5551-
PartitionBegin = PartitionEnd;
5552-
BeginOffset = PartitionBegin->beginOffset();
5553-
EndOffset = PartitionBegin->endOffset();
5554-
}
5555-
return true;
5556-
}
5557-
55585457
/// Analyze an alloca for SROA.
55595458
///
55605459
/// This analyzes the alloca to ensure we can reason about it, builds
@@ -5595,11 +5494,6 @@ SROA::runOnAlloca(AllocaInst &AI) {
55955494
if (AS.isEscaped())
55965495
return {Changed, CFGChanged};
55975496

5598-
if (AS.isEscapedReadOnly()) {
5599-
Changed |= propagateStoredValuesToLoads(AI, AS);
5600-
return {Changed, CFGChanged};
5601-
}
5602-
56035497
// Delete all the dead users of this alloca before splitting and rewriting it.
56045498
for (Instruction *DeadUser : AS.getDeadUsers()) {
56055499
// Free up everything used by this instruction.

llvm/lib/Transforms/Utils/SSAUpdater.cpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -412,21 +412,17 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
412412
if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
413413
updateDebugInfo(SI);
414414
SSA.AddAvailableValue(BB, SI->getOperand(0));
415-
} else if (auto *AI = dyn_cast<AllocaInst>(User)) {
416-
// We treat AllocaInst as a store of an getValueToUseForAlloca value.
417-
SSA.AddAvailableValue(BB, getValueToUseForAlloca(AI));
418-
} else {
415+
} else
419416
// Otherwise it is a load, queue it to rewrite as a live-in load.
420417
LiveInLoads.push_back(cast<LoadInst>(User));
421-
}
422418
BlockUses.clear();
423419
continue;
424420
}
425421

426422
// Otherwise, check to see if this block is all loads.
427423
bool HasStore = false;
428424
for (Instruction *I : BlockUses) {
429-
if (isa<StoreInst>(I) || isa<AllocaInst>(I)) {
425+
if (isa<StoreInst>(I)) {
430426
HasStore = true;
431427
break;
432428
}
@@ -472,12 +468,6 @@ void LoadAndStorePromoter::run(const SmallVectorImpl<Instruction *> &Insts) {
472468

473469
// Remember that this is the active value in the block.
474470
StoredValue = SI->getOperand(0);
475-
} else if (auto *AI = dyn_cast<AllocaInst>(&I)) {
476-
// Check if this an alloca, in which case we treat it as a store of
477-
// getValueToUseForAlloca.
478-
if (!isInstInList(AI, Insts))
479-
continue;
480-
StoredValue = getValueToUseForAlloca(AI);
481471
}
482472
}
483473

0 commit comments

Comments
 (0)