Skip to content

Revert "[CaptureTracking] Ignore ephemeral values when determining po… #71066

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions llvm/include/llvm/Analysis/AliasAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,9 @@ class EarliestEscapeInfo final : public CaptureInfo {
/// This is used for cache invalidation purposes.
DenseMap<Instruction *, TinyPtrVector<const Value *>> Inst2Obj;

const SmallPtrSetImpl<const Value *> *EphValues;

public:
EarliestEscapeInfo(DominatorTree &DT, const LoopInfo *LI = nullptr,
const SmallPtrSetImpl<const Value *> *EphValues = nullptr)
: DT(DT), LI(LI), EphValues(EphValues) {}
EarliestEscapeInfo(DominatorTree &DT, const LoopInfo *LI = nullptr)
: DT(DT), LI(LI) {}

bool isNotCapturedBeforeOrAt(const Value *Object,
const Instruction *I) override;
Expand Down
17 changes: 4 additions & 13 deletions llvm/include/llvm/Analysis/CaptureTracking.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ namespace llvm {
class DominatorTree;
class LoopInfo;
class Function;
template <typename T> class SmallPtrSetImpl;

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

/// Variant of the above function which accepts a set of Values that are
/// ephemeral and cannot cause pointers to escape.
bool PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
bool StoreCaptures,
const SmallPtrSetImpl<const Value *> &EphValues,
unsigned MaxUsesToExplore = 0);

/// PointerMayBeCapturedBefore - Return true if this pointer value may be
/// captured by the enclosing function (which is required to exist). If a
/// DominatorTree is provided, only captures which happen before the given
Expand Down Expand Up @@ -80,11 +72,10 @@ namespace llvm {
// nullptr is returned. Note that the caller of the function has to ensure
// that the instruction the result value is compared against is not in a
// cycle.
Instruction *
FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures,
bool StoreCaptures, const DominatorTree &DT,
const SmallPtrSetImpl<const Value *> *EphValues = nullptr,
unsigned MaxUsesToExplore = 0);
Instruction *FindEarliestCapture(const Value *V, Function &F,
bool ReturnCaptures, bool StoreCaptures,
const DominatorTree &DT,
unsigned MaxUsesToExplore = 0);

/// This callback is used in conjunction with PointerMayBeCaptured. In
/// addition to the interface here, you'll need to provide your own getters
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Analysis/BasicAliasAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ bool EarliestEscapeInfo::isNotCapturedBeforeOrAt(const Value *Object,
if (Iter.second) {
Instruction *EarliestCapture = FindEarliestCapture(
Object, *const_cast<Function *>(I->getFunction()),
/*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT, EphValues);
/*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT);
if (EarliestCapture) {
auto Ins = Inst2Obj.insert({EarliestCapture, {}});
Ins.first->second.push_back(Object);
Expand Down
46 changes: 10 additions & 36 deletions llvm/lib/Analysis/CaptureTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
//===----------------------------------------------------------------------===//

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

namespace {
struct SimpleCaptureTracker : public CaptureTracker {
explicit SimpleCaptureTracker(

const SmallPtrSetImpl<const Value *> &EphValues, bool ReturnCaptures)
: EphValues(EphValues), ReturnCaptures(ReturnCaptures) {}
explicit SimpleCaptureTracker(bool ReturnCaptures)
: ReturnCaptures(ReturnCaptures) {}

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

if (EphValues.contains(U->getUser()))
return false;

LLVM_DEBUG(dbgs() << "Captured by: " << *U->getUser() << "\n");

Captured = true;
return true;
}

const SmallPtrSetImpl<const Value *> &EphValues;

bool ReturnCaptures;

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

EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT,
const SmallPtrSetImpl<const Value *> *EphValues)
: EphValues(EphValues), DT(DT), ReturnCaptures(ReturnCaptures), F(F) {}
EarliestCaptures(bool ReturnCaptures, Function &F, const DominatorTree &DT)
: DT(DT), ReturnCaptures(ReturnCaptures), F(F) {}

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

if (EphValues && EphValues->contains(I))
return false;

if (!EarliestCapture)
EarliestCapture = I;
else
Expand All @@ -194,8 +182,6 @@ namespace {
return false;
}

const SmallPtrSetImpl<const Value *> *EphValues;

Instruction *EarliestCapture = nullptr;

const DominatorTree &DT;
Expand All @@ -217,17 +203,6 @@ namespace {
/// counts as capturing it or not.
bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
bool StoreCaptures, unsigned MaxUsesToExplore) {
SmallPtrSet<const Value *, 1> Empty;
return PointerMayBeCaptured(V, ReturnCaptures, StoreCaptures, Empty,
MaxUsesToExplore);
}

/// Variant of the above function which accepts a set of Values that are
/// ephemeral and cannot cause pointers to escape.
bool llvm::PointerMayBeCaptured(const Value *V, bool ReturnCaptures,
bool StoreCaptures,
const SmallPtrSetImpl<const Value *> &EphValues,
unsigned MaxUsesToExplore) {
assert(!isa<GlobalValue>(V) &&
"It doesn't make sense to ask whether a global is captured.");

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

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

SimpleCaptureTracker SCT(EphValues, ReturnCaptures);
SimpleCaptureTracker SCT(ReturnCaptures);
PointerMayBeCaptured(V, &SCT, MaxUsesToExplore);
if (SCT.Captured)
++NumCaptured;
Expand Down Expand Up @@ -283,15 +258,14 @@ bool llvm::PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
return CB.Captured;
}

Instruction *
llvm::FindEarliestCapture(const Value *V, Function &F, bool ReturnCaptures,
bool StoreCaptures, const DominatorTree &DT,
const SmallPtrSetImpl<const Value *> *EphValues,
unsigned MaxUsesToExplore) {
Instruction *llvm::FindEarliestCapture(const Value *V, Function &F,
bool ReturnCaptures, bool StoreCaptures,
const DominatorTree &DT,
unsigned MaxUsesToExplore) {
assert(!isa<GlobalValue>(V) &&
"It doesn't make sense to ask whether a global is captured.");

EarliestCaptures CB(ReturnCaptures, F, DT, EphValues);
EarliestCaptures CB(ReturnCaptures, F, DT);
PointerMayBeCaptured(V, &CB, MaxUsesToExplore);
if (CB.Captured)
++NumCapturedBefore;
Expand Down
25 changes: 8 additions & 17 deletions llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/CodeMetrics.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h"
Expand Down Expand Up @@ -842,9 +840,6 @@ struct DSEState {
// Post-order numbers for each basic block. Used to figure out if memory
// accesses are executed before another access.
DenseMap<BasicBlock *, unsigned> PostOrderNumbers;
// Values that are only used with assumes. Used to refine pointer escape
// analysis.
SmallPtrSet<const Value *, 32> EphValues;

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

DSEState(Function &F, AliasAnalysis &AA, MemorySSA &MSSA, DominatorTree &DT,
PostDominatorTree &PDT, AssumptionCache &AC,
const TargetLibraryInfo &TLI, const LoopInfo &LI)
: F(F), AA(AA), EI(DT, &LI, &EphValues), BatchAA(AA, &EI), MSSA(MSSA),
DT(DT), PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI) {
PostDominatorTree &PDT, const TargetLibraryInfo &TLI,
const LoopInfo &LI)
: F(F), AA(AA), EI(DT, &LI), BatchAA(AA, &EI), MSSA(MSSA), DT(DT),
PDT(PDT), TLI(TLI), DL(F.getParent()->getDataLayout()), LI(LI) {
// Collect blocks with throwing instructions not modeled in MemorySSA and
// alloc-like objects.
unsigned PO = 0;
Expand Down Expand Up @@ -897,8 +892,6 @@ struct DSEState {
AnyUnreachableExit = any_of(PDT.roots(), [](const BasicBlock *E) {
return isa<UnreachableInst>(E->getTerminator());
});

CodeMetrics::collectEphemeralValues(&F, &AC, EphValues);
}

LocationSize strengthenLocationSize(const Instruction *I,
Expand Down Expand Up @@ -1075,7 +1068,7 @@ struct DSEState {
if (!isInvisibleToCallerOnUnwind(V)) {
I.first->second = false;
} else if (isNoAliasCall(V)) {
I.first->second = !PointerMayBeCaptured(V, true, false, EphValues);
I.first->second = !PointerMayBeCaptured(V, true, false);
}
}
return I.first->second;
Expand All @@ -1094,7 +1087,7 @@ struct DSEState {
// with the killing MemoryDef. But we refrain from doing so for now to
// limit compile-time and this does not cause any changes to the number
// of stores removed on a large test set in practice.
I.first->second = PointerMayBeCaptured(V, false, true, EphValues);
I.first->second = PointerMayBeCaptured(V, false, true);
return !I.first->second;
}

Expand Down Expand Up @@ -2065,12 +2058,11 @@ struct DSEState {

static bool eliminateDeadStores(Function &F, AliasAnalysis &AA, MemorySSA &MSSA,
DominatorTree &DT, PostDominatorTree &PDT,
AssumptionCache &AC,
const TargetLibraryInfo &TLI,
const LoopInfo &LI) {
bool MadeChange = false;

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

bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, AC, TLI, LI);
bool Changed = eliminateDeadStores(F, AA, MSSA, DT, PDT, TLI, LI);

#ifdef LLVM_ENABLE_STATS
if (AreStatisticsEnabled())
Expand Down
3 changes: 3 additions & 0 deletions llvm/test/Transforms/DeadStoreElimination/assume.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ define void @f() {
; CHECK-NEXT: [[TMP1:%.*]] = call noalias ptr @_Znwm(i64 32)
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt ptr [[TMP1]], @global
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
; CHECK-NEXT: store i8 0, ptr [[TMP1]], align 1
; CHECK-NEXT: ret void
;
%tmp1 = call noalias ptr @_Znwm(i64 32)
Expand All @@ -22,6 +23,7 @@ define void @f2() {
; CHECK-NEXT: [[TMP1:%.*]] = call noalias ptr @_Znwm(i64 32)
; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt ptr [[TMP1]], @global
; CHECK-NEXT: call void @llvm.assume(i1 [[TMP2]])
; CHECK-NEXT: store i8 0, ptr [[TMP1]], align 1
; CHECK-NEXT: call void @quux(ptr @global)
; CHECK-NEXT: ret void
;
Expand All @@ -37,6 +39,7 @@ define void @f2() {
define void @pr70547() {
; CHECK-LABEL: @pr70547(
; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
; CHECK-NEXT: store i8 0, ptr [[A]], align 1
; CHECK-NEXT: [[CALL:%.*]] = call ptr @quux(ptr [[A]]) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: [[V:%.*]] = load i8, ptr [[CALL]], align 1
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[V]], 1
Expand Down