Skip to content

Commit fd95f39

Browse files
authored
Revert "[CaptureTracking] Ignore ephemeral values when determining po… (#71066)
Unfortunately the commit (D123162) introduced a mis-compile (#70547), which wasn't fixed by the alternative fix (c0de28b) I think as long as the call considered as ephemeral is not removed, we need to be conservative. To address the correctness issue quickly, I think we should revert the patch (as this patch does, it doens't revert cleanly) This reverts commit 17fdacc. Fixes #70547
1 parent 29fd9ba commit fd95f39

File tree

6 files changed

+28
-72
lines changed

6 files changed

+28
-72
lines changed

llvm/include/llvm/Analysis/AliasAnalysis.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,9 @@ class EarliestEscapeInfo final : public CaptureInfo {
184184
/// This is used for cache invalidation purposes.
185185
DenseMap<Instruction *, TinyPtrVector<const Value *>> Inst2Obj;
186186

187-
const SmallPtrSetImpl<const Value *> *EphValues;
188-
189187
public:
190-
EarliestEscapeInfo(DominatorTree &DT, const LoopInfo *LI = nullptr,
191-
const SmallPtrSetImpl<const Value *> *EphValues = nullptr)
192-
: DT(DT), LI(LI), EphValues(EphValues) {}
188+
EarliestEscapeInfo(DominatorTree &DT, const LoopInfo *LI = nullptr)
189+
: DT(DT), LI(LI) {}
193190

194191
bool isNotCapturedBeforeOrAt(const Value *Object,
195192
const Instruction *I) override;

llvm/include/llvm/Analysis/CaptureTracking.h

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ namespace llvm {
2525
class DominatorTree;
2626
class LoopInfo;
2727
class Function;
28-
template <typename T> class SmallPtrSetImpl;
2928

3029
/// getDefaultMaxUsesToExploreForCaptureTracking - Return default value of
3130
/// the maximal number of uses to explore before giving up. It is used by
@@ -45,13 +44,6 @@ namespace llvm {
4544
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
4645
bool StoreCaptures, unsigned MaxUsesToExplore = 0);
4746

48-
/// Variant of the above function which accepts a set of Values that are
49-
/// ephemeral and cannot cause pointers to escape.
50-
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
51-
bool StoreCaptures,
52-
const SmallPtrSetImpl<const Value *> &EphValues,
53-
unsigned MaxUsesToExplore = 0);
54-
5547
/// PointerMayBeCapturedBefore - Return true if this pointer value may be
5648
/// captured by the enclosing function (which is required to exist). If a
5749
/// DominatorTree is provided, only captures which happen before the given
@@ -80,11 +72,10 @@ namespace llvm {
8072
// nullptr is returned. Note that the caller of the function has to ensure
8173
// that the instruction the result value is compared against is not in a
8274
// cycle.
83-
Instruction *
84-
FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures,
85-
bool StoreCaptures, const DominatorTree &DT,
86-
const SmallPtrSetImpl<const Value *> *EphValues = nullptr,
87-
unsigned MaxUsesToExplore = 0);
75+
Instruction *FindEarliestCapture(const Value *V, Function &F,
76+
bool ReturnCaptures, bool StoreCaptures,
77+
const DominatorTree &DT,
78+
unsigned MaxUsesToExplore = 0);
8879

8980
/// This callback is used in conjunction with PointerMayBeCaptured. In
9081
/// addition to the interface here, you'll need to provide your own getters

llvm/lib/Analysis/BasicAliasAnalysis.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ bool EarliestEscapeInfo::isNotCapturedBeforeOrAt(const Value *Object,
208208
if (Iter.second) {
209209
Instruction *EarliestCapture = FindEarliestCapture(
210210
Object, *const_cast<Function *>(I->getFunction()),
211-
/*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT, EphValues);
211+
/*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT);
212212
if (EarliestCapture) {
213213
auto Ins = Inst2Obj.insert({EarliestCapture, {}});
214214
Ins.first->second.push_back(Object);

llvm/lib/Analysis/CaptureTracking.cpp

Lines changed: 10 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "llvm/Analysis/CaptureTracking.h"
19-
#include "llvm/ADT/SmallPtrSet.h"
2019
#include "llvm/ADT/SmallSet.h"
2120
#include "llvm/ADT/SmallVector.h"
2221
#include "llvm/ADT/Statistic.h"
@@ -74,10 +73,8 @@ bool CaptureTracker::isDereferenceableOrNull(Value *O, const DataLayout &DL) {
7473

7574
namespace {
7675
struct SimpleCaptureTracker : public CaptureTracker {
77-
explicit SimpleCaptureTracker(
78-
79-
const SmallPtrSetImpl<const Value *> &EphValues, bool ReturnCaptures)
80-
: EphValues(EphValues), ReturnCaptures(ReturnCaptures) {}
76+
explicit SimpleCaptureTracker(bool ReturnCaptures)
77+
: ReturnCaptures(ReturnCaptures) {}
8178

8279
void tooManyUses() override {
8380
LLVM_DEBUG(dbgs() << "Captured due to too many uses\n");
@@ -88,17 +85,12 @@ namespace {
8885
if (isa<ReturnInst>(U->getUser()) && !ReturnCaptures)
8986
return false;
9087

91-
if (EphValues.contains(U->getUser()))
92-
return false;
93-
9488
LLVM_DEBUG(dbgs() << "Captured by: " << *U->getUser() << "\n");
9589

9690
Captured = true;
9791
return true;
9892
}
9993

100-
const SmallPtrSetImpl<const Value *> &EphValues;
101-
10294
bool ReturnCaptures;
10395

10496
bool Captured = false;
@@ -166,9 +158,8 @@ namespace {
166158
// escape are not in a cycle.
167159
struct EarliestCaptures : public CaptureTracker {
168160

169-
EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT,
170-
const SmallPtrSetImpl<const Value *> *EphValues)
171-
: EphValues(EphValues), DT(DT), ReturnCaptures(ReturnCaptures), F(F) {}
161+
EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT)
162+
: DT(DT), ReturnCaptures(ReturnCaptures), F(F) {}
172163

173164
void tooManyUses() override {
174165
Captured = true;
@@ -180,9 +171,6 @@ namespace {
180171
if (isa<ReturnInst>(I) && !ReturnCaptures)
181172
return false;
182173

183-
if (EphValues && EphValues->contains(I))
184-
return false;
185-
186174
if (!EarliestCapture)
187175
EarliestCapture = I;
188176
else
@@ -194,8 +182,6 @@ namespace {
194182
return false;
195183
}
196184

197-
const SmallPtrSetImpl<const Value *> *EphValues;
198-
199185
Instruction *EarliestCapture = nullptr;
200186

201187
const DominatorTree &DT;
@@ -217,17 +203,6 @@ namespace {
217203
/// counts as capturing it or not.
218204
bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
219205
bool StoreCaptures, unsigned MaxUsesToExplore) {
220-
SmallPtrSet<const Value *, 1> Empty;
221-
return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures, Empty,
222-
MaxUsesToExplore);
223-
}
224-
225-
/// Variant of the above function which accepts a set of Values that are
226-
/// ephemeral and cannot cause pointers to escape.
227-
bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
228-
bool StoreCaptures,
229-
const SmallPtrSetImpl<const Value *> &EphValues,
230-
unsigned MaxUsesToExplore) {
231206
assert(!isa<GlobalValue>(V) &&
232207
"It doesn't make sense to ask whether a global is captured.");
233208

@@ -239,7 +214,7 @@ bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
239214

240215
LLVM_DEBUG(dbgs() << "Captured?: " << *V << " = ");
241216

242-
SimpleCaptureTracker SCT(EphValues, ReturnCaptures);
217+
SimpleCaptureTracker SCT(ReturnCaptures);
243218
PointerMayBeCaptured(V, &SCT, MaxUsesToExplore);
244219
if (SCT.Captured)
245220
++NumCaptured;
@@ -283,15 +258,14 @@ bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
283258
return CB.Captured;
284259
}
285260

286-
Instruction *
287-
llvm::FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures,
288-
bool StoreCaptures, const DominatorTree &DT,
289-
const SmallPtrSetImpl<const Value *> *EphValues,
290-
unsigned MaxUsesToExplore) {
261+
Instruction *llvm::FindEarliestCapture(const Value *V, Function &F,
262+
bool ReturnCaptures, bool StoreCaptures,
263+
const DominatorTree &DT,
264+
unsigned MaxUsesToExplore) {
291265
assert(!isa<GlobalValue>(V) &&
292266
"It doesn't make sense to ask whether a global is captured.");
293267

294-
EarliestCaptures CB(ReturnCaptures, F, DT, EphValues);
268+
EarliestCaptures CB(ReturnCaptures, F, DT);
295269
PointerMayBeCaptured(V, &CB, MaxUsesToExplore);
296270
if (CB.Captured)
297271
++NumCapturedBefore;

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@
3838
#include "llvm/ADT/Statistic.h"
3939
#include "llvm/ADT/StringRef.h"
4040
#include "llvm/Analysis/AliasAnalysis.h"
41-
#include "llvm/Analysis/AssumptionCache.h"
4241
#include "llvm/Analysis/CaptureTracking.h"
43-
#include "llvm/Analysis/CodeMetrics.h"
4442
#include "llvm/Analysis/GlobalsModRef.h"
4543
#include "llvm/Analysis/LoopInfo.h"
4644
#include "llvm/Analysis/MemoryBuiltins.h"
@@ -842,9 +840,6 @@ struct DSEState {
842840
// Post-order numbers for each basic block. Used to figure out if memory
843841
// accesses are executed before another access.
844842
DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
845-
// Values that are only used with assumes. Used to refine pointer escape
846-
// analysis.
847-
SmallPtrSet<const Value *, 32> EphValues;
848843

849844
/// Keep track of instructions (partly) overlapping with killing MemoryDefs per
850845
/// basic block.
@@ -864,10 +859,10 @@ struct DSEState {
864859
DSEState &operator=(const DSEState &) = delete;
865860

866861
DSEState(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT,
867-
PostDominatorTree &PDT, AssumptionCache &AC,
868-
const TargetLibraryInfo &TLI, const LoopInfo &LI)
869-
: F(F), AA(AA), EI(DT, &LI, &EphValues), BatchAA(AA, &EI), MSSA(MSSA),
870-
DT(DT), PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI) {
862+
PostDominatorTree &PDT, const TargetLibraryInfo &TLI,
863+
const LoopInfo &LI)
864+
: F(F), AA(AA), EI(DT, &LI), BatchAA(AA, &EI), MSSA(MSSA), DT(DT),
865+
PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI) {
871866
// Collect blocks with throwing instructions not modeled in MemorySSA and
872867
// alloc-like objects.
873868
unsigned PO = 0;
@@ -897,8 +892,6 @@ struct DSEState {
897892
AnyUnreachableExit = any_of(PDT.roots(), [](const BasicBlock *E) {
898893
return isa<UnreachableInst>(E->getTerminator());
899894
});
900-
901-
CodeMetrics::collectEphemeralValues(&F, &AC, EphValues);
902895
}
903896

904897
LocationSize strengthenLocationSize(const Instruction *I,
@@ -1075,7 +1068,7 @@ struct DSEState {
10751068
if (!isInvisibleToCallerOnUnwind(V)) {
10761069
I.first->second = false;
10771070
} else if (isNoAliasCall(V)) {
1078-
I.first->second = !PointerMayBeCaptured(V, true, false, EphValues);
1071+
I.first->second = !PointerMayBeCaptured(V, true, false);
10791072
}
10801073
}
10811074
return I.first->second;
@@ -1094,7 +1087,7 @@ struct DSEState {
10941087
// with the killing MemoryDef. But we refrain from doing so for now to
10951088
// limit compile-time and this does not cause any changes to the number
10961089
// of stores removed on a large test set in practice.
1097-
I.first->second = PointerMayBeCaptured(V, false, true, EphValues);
1090+
I.first->second = PointerMayBeCaptured(V, false, true);
10981091
return !I.first->second;
10991092
}
11001093

@@ -2065,12 +2058,11 @@ struct DSEState {
20652058

20662059
static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
20672060
DominatorTree &DT, PostDominatorTree &PDT,
2068-
AssumptionCache &AC,
20692061
const TargetLibraryInfo &TLI,
20702062
const LoopInfo &LI) {
20712063
bool MadeChange = false;
20722064

2073-
DSEState State(F, AA, MSSA, DT, PDT, AC, TLI, LI);
2065+
DSEState State(F, AA, MSSA, DT, PDT, TLI, LI);
20742066
// For each store:
20752067
for (unsigned I = 0; I < State.MemDefs.size(); I++) {
20762068
MemoryDef *KillingDef = State.MemDefs[I];
@@ -2251,10 +2243,9 @@ PreservedAnalyses DSEPass::run(Function &F, FunctionAnalysisManager &AM) {
22512243
DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F);
22522244
MemorySSA &MSSA = AM.getResult<MemorySSAAnalysis>(F).getMSSA();
22532245
PostDominatorTree &PDT = AM.getResult<PostDominatorTreeAnalysis>(F);
2254-
AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F);
22552246
LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
22562247

2257-
bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, AC, TLI, LI);
2248+
bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, TLI, LI);
22582249

22592250
#ifdef LLVM_ENABLE_STATS
22602251
if (AreStatisticsEnabled())

llvm/test/Transforms/DeadStoreElimination/assume.ll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ define void @f() {
88
; CHECK-NEXT: [[TMP1:%.*]] = call noalias ptr @_Znwm(i64 32)
99
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt ptr [[TMP1]], @global
1010
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
11+
; CHECK-NEXT: store i8 0, ptr [[TMP1]], align 1
1112
; CHECK-NEXT: ret void
1213
;
1314
%tmp1 = call noalias ptr @_Znwm(i64 32)
@@ -22,6 +23,7 @@ define void @f2() {
2223
; CHECK-NEXT: [[TMP1:%.*]] = call noalias ptr @_Znwm(i64 32)
2324
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt ptr [[TMP1]], @global
2425
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
26+
; CHECK-NEXT: store i8 0, ptr [[TMP1]], align 1
2527
; CHECK-NEXT: call void @quux(ptr @global)
2628
; CHECK-NEXT: ret void
2729
;
@@ -37,6 +39,7 @@ define void @f2() {
3739
define void @pr70547() {
3840
; CHECK-LABEL: @pr70547(
3941
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
42+
; CHECK-NEXT: store i8 0, ptr [[A]], align 1
4043
; CHECK-NEXT: [[CALL:%.*]] = call ptr @quux(ptr [[A]]) #[[ATTR1:[0-9]+]]
4144
; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[CALL]], align 1
4245
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[V]], 1

0 commit comments

Comments
 (0)