Skip to content

Commit 17fdacc

Browse files
committed
[CaptureTracking] Ignore ephemeral values when determining pointer escapeness
Ephemeral values cannot cause a pointer to escape. No change in compile time: https://llvm-compile-time-tracker.com/compare.php?from=4371710085ba1c376a094948b806ddd3b88319de&to=c5ddbcc4866f38026737762ee8d7b9b00395d4f4&stat=instructions This partially fixes some regressions caused by more calls to `__builtin_assume` (D122397). Reviewed By: asbirlea Differential Revision: https://reviews.llvm.org/D123162
1 parent 26d974d commit 17fdacc

File tree

4 files changed

+50
-13
lines changed

4 files changed

+50
-13
lines changed

llvm/include/llvm/Analysis/CaptureTracking.h

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

2930
/// getDefaultMaxUsesToExploreForCaptureTracking - Return default value of
3031
/// the maximal number of uses to explore before giving up. It is used by
@@ -41,8 +42,14 @@ namespace llvm {
4142
/// MaxUsesToExplore specifies how many uses the analysis should explore for
4243
/// one value before giving up due too "too many uses". If MaxUsesToExplore
4344
/// is zero, a default value is assumed.
45+
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
46+
bool StoreCaptures, unsigned MaxUsesToExplore = 0);
47+
48+
/// Variant of the above function which accepts a set of Values that are
49+
/// ephemeral and cannot cause pointers to escape.
4450
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
4551
bool StoreCaptures,
52+
const SmallPtrSetImpl<const Value *> &EphValues,
4653
unsigned MaxUsesToExplore = 0);
4754

4855
/// PointerMayBeCapturedBefore - Return true if this pointer value may be

llvm/lib/Analysis/CaptureTracking.cpp

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

1818
#include "llvm/Analysis/CaptureTracking.h"
19+
#include "llvm/ADT/SmallPtrSet.h"
1920
#include "llvm/ADT/SmallSet.h"
2021
#include "llvm/ADT/SmallVector.h"
2122
#include "llvm/ADT/Statistic.h"
@@ -74,19 +75,26 @@ bool CaptureTracker::isDereferenceableOrNull(Value *O, const DataLayout &DL) {
7475

7576
namespace {
7677
struct SimpleCaptureTracker : public CaptureTracker {
77-
explicit SimpleCaptureTracker(bool ReturnCaptures)
78-
: ReturnCaptures(ReturnCaptures) {}
78+
explicit SimpleCaptureTracker(
79+
80+
const SmallPtrSetImpl<const Value *> &EphValues, bool ReturnCaptures)
81+
: EphValues(EphValues), ReturnCaptures(ReturnCaptures) {}
7982

8083
void tooManyUses() override { Captured = true; }
8184

8285
bool captured(const Use *U) override {
8386
if (isa<ReturnInst>(U->getUser()) && !ReturnCaptures)
8487
return false;
8588

89+
if (EphValues.contains(U->getUser()))
90+
return false;
91+
8692
Captured = true;
8793
return true;
8894
}
8995

96+
const SmallPtrSetImpl<const Value *> &EphValues;
97+
9098
bool ReturnCaptures;
9199

92100
bool Captured = false;
@@ -212,8 +220,18 @@ namespace {
212220
/// counts as capturing it or not. The boolean StoreCaptures specified whether
213221
/// storing the value (or part of it) into memory anywhere automatically
214222
/// counts as capturing it or not.
215-
bool llvm::PointerMayBeCaptured(const Value *V,
216-
bool ReturnCaptures, bool StoreCaptures,
223+
bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
224+
bool StoreCaptures, unsigned MaxUsesToExplore) {
225+
SmallPtrSet<const Value *, 1> Empty;
226+
return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures, Empty,
227+
MaxUsesToExplore);
228+
}
229+
230+
/// Variant of the above function which accepts a set of Values that are
231+
/// ephemeral and cannot cause pointers to escape.
232+
bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
233+
bool StoreCaptures,
234+
const SmallPtrSetImpl<const Value *> &EphValues,
217235
unsigned MaxUsesToExplore) {
218236
assert(!isa<GlobalValue>(V) &&
219237
"It doesn't make sense to ask whether a global is captured.");
@@ -224,7 +242,7 @@ bool llvm::PointerMayBeCaptured(const Value *V,
224242
// take advantage of this.
225243
(void)StoreCaptures;
226244

227-
SimpleCaptureTracker SCT(ReturnCaptures);
245+
SimpleCaptureTracker SCT(EphValues, ReturnCaptures);
228246
PointerMayBeCaptured(V, &SCT, MaxUsesToExplore);
229247
if (SCT.Captured)
230248
++NumCaptured;

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@
3838
#include "llvm/ADT/Statistic.h"
3939
#include "llvm/ADT/StringRef.h"
4040
#include "llvm/Analysis/AliasAnalysis.h"
41+
#include "llvm/Analysis/AssumptionCache.h"
4142
#include "llvm/Analysis/CaptureTracking.h"
43+
#include "llvm/Analysis/CodeMetrics.h"
4244
#include "llvm/Analysis/GlobalsModRef.h"
4345
#include "llvm/Analysis/LoopInfo.h"
4446
#include "llvm/Analysis/MemoryBuiltins.h"
@@ -762,6 +764,9 @@ struct DSEState {
762764
// Post-order numbers for each basic block. Used to figure out if memory
763765
// accesses are executed before another access.
764766
DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
767+
// Values that are only used with assumes. Used to refine pointer escape
768+
// analysis.
769+
SmallPtrSet<const Value *, 32> EphValues;
765770

766771
/// Keep track of instructions (partly) overlapping with killing MemoryDefs per
767772
/// basic block.
@@ -776,8 +781,8 @@ struct DSEState {
776781
DSEState &operator=(const DSEState &) = delete;
777782

778783
DSEState(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT,
779-
PostDominatorTree &PDT, const TargetLibraryInfo &TLI,
780-
const LoopInfo &LI)
784+
PostDominatorTree &PDT, AssumptionCache &AC,
785+
const TargetLibraryInfo &TLI, const LoopInfo &LI)
781786
: F(F), AA(AA), EI(DT, LI), BatchAA(AA, &EI), MSSA(MSSA), DT(DT),
782787
PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI) {
783788
// Collect blocks with throwing instructions not modeled in MemorySSA and
@@ -809,6 +814,8 @@ struct DSEState {
809814
AnyUnreachableExit = any_of(PDT.roots(), [](const BasicBlock *E) {
810815
return isa<UnreachableInst>(E->getTerminator());
811816
});
817+
818+
CodeMetrics::collectEphemeralValues(&F, &AC, EphValues);
812819
}
813820

814821
/// Return 'OW_Complete' if a store to the 'KillingLoc' location (by \p
@@ -955,7 +962,7 @@ struct DSEState {
955962
if (!isInvisibleToCallerOnUnwind(V)) {
956963
I.first->second = false;
957964
} else if (isNoAliasCall(V)) {
958-
I.first->second = !PointerMayBeCaptured(V, true, false);
965+
I.first->second = !PointerMayBeCaptured(V, true, false, EphValues);
959966
}
960967
}
961968
return I.first->second;
@@ -974,7 +981,7 @@ struct DSEState {
974981
// with the killing MemoryDef. But we refrain from doing so for now to
975982
// limit compile-time and this does not cause any changes to the number
976983
// of stores removed on a large test set in practice.
977-
I.first->second = PointerMayBeCaptured(V, false, true);
984+
I.first->second = PointerMayBeCaptured(V, false, true, EphValues);
978985
return !I.first->second;
979986
}
980987

@@ -1929,12 +1936,13 @@ struct DSEState {
19291936

19301937
static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
19311938
DominatorTree &DT, PostDominatorTree &PDT,
1939+
AssumptionCache &AC,
19321940
const TargetLibraryInfo &TLI,
19331941
const LoopInfo &LI) {
19341942
bool MadeChange = false;
19351943

19361944
MSSA.ensureOptimizedUses();
1937-
DSEState State(F, AA, MSSA, DT, PDT, TLI, LI);
1945+
DSEState State(F, AA, MSSA, DT, PDT, AC, TLI, LI);
19381946
// For each store:
19391947
for (unsigned I = 0; I < State.MemDefs.size(); I++) {
19401948
MemoryDef *KillingDef = State.MemDefs[I];
@@ -2114,9 +2122,10 @@ PreservedAnalyses DSEPass::run(Function &F, FunctionAnalysisManager &AM) {
21142122
DominatorTree &DT = AM.getResult<DominatorTreeAnalysis>(F);
21152123
MemorySSA &MSSA = AM.getResult<MemorySSAAnalysis>(F).getMSSA();
21162124
PostDominatorTree &PDT = AM.getResult<PostDominatorTreeAnalysis>(F);
2125+
AssumptionCache &AC = AM.getResult<AssumptionAnalysis>(F);
21172126
LoopInfo &LI = AM.getResult<LoopAnalysis>(F);
21182127

2119-
bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, TLI, LI);
2128+
bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, AC, TLI, LI);
21202129

21212130
#ifdef LLVM_ENABLE_STATS
21222131
if (AreStatisticsEnabled())
@@ -2156,9 +2165,11 @@ class DSELegacyPass : public FunctionPass {
21562165
MemorySSA &MSSA = getAnalysis<MemorySSAWrapperPass>().getMSSA();
21572166
PostDominatorTree &PDT =
21582167
getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
2168+
AssumptionCache &AC =
2169+
getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
21592170
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
21602171

2161-
bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, TLI, LI);
2172+
bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, AC, TLI, LI);
21622173

21632174
#ifdef LLVM_ENABLE_STATS
21642175
if (AreStatisticsEnabled())
@@ -2182,6 +2193,7 @@ class DSELegacyPass : public FunctionPass {
21822193
AU.addPreserved<MemorySSAWrapperPass>();
21832194
AU.addRequired<LoopInfoWrapperPass>();
21842195
AU.addPreserved<LoopInfoWrapperPass>();
2196+
AU.addRequired<AssumptionCacheTracker>();
21852197
}
21862198
};
21872199

@@ -2199,6 +2211,7 @@ INITIALIZE_PASS_DEPENDENCY(MemorySSAWrapperPass)
21992211
INITIALIZE_PASS_DEPENDENCY(MemoryDependenceWrapperPass)
22002212
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
22012213
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
2214+
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
22022215
INITIALIZE_PASS_END(DSELegacyPass, "dse", "Dead Store Elimination", false,
22032216
false)
22042217

llvm/test/Transforms/DeadStoreElimination/assume.ll

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ define void @f() {
88
; CHECK-NEXT: [[TMP1:%.*]] = call noalias i8* @_Znwm(i64 32)
99
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt i8* [[TMP1]], @global
1010
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
11-
; CHECK-NEXT: store i8 0, i8* [[TMP1]], align 1
1211
; CHECK-NEXT: ret void
1312
;
1413
%tmp1 = call noalias i8* @_Znwm(i64 32)

0 commit comments

Comments
 (0)