Skip to content

Commit f3428d3

Browse files
nikicfhahn
authored andcommitted
[AA] Move earliest escape tracking from DSE to AA
This is a followup to D109844 (and alternative to D109907), which integrates the new "earliest escape" tracking into AliasAnalysis. This is done by replacing the pre-existing context-free capture cache in AAQueryInfo with a replaceable (virtual) object with two implementations: The SimpleCaptureInfo implements the previous behavior (check whether object is captured at all), while EarliestEscapeInfo implements the new behavior from DSE. This combines the "earliest escape" analysis with the full power of BasicAA: It subsumes the call handling from D109907, considers a wider range of escape sources, and works with AA recursion. The compile-time cost is slightly higher than with D109907. Differential Revision: https://reviews.llvm.org/D110368 (cherry-picked from ba664d9)
1 parent 15c3fea commit f3428d3

File tree

7 files changed

+129
-103
lines changed

7 files changed

+129
-103
lines changed

llvm/include/llvm/Analysis/AliasAnalysis.h

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class DominatorTree;
6161
class FenceInst;
6262
class Function;
6363
class InvokeInst;
64+
class LoopInfo;
6465
class PreservedAnalyses;
6566
class TargetLibraryInfo;
6667
class Value;
@@ -378,6 +379,50 @@ createModRefInfo(const FunctionModRefBehavior FMRB) {
378379
return ModRefInfo(FMRB & static_cast<int>(ModRefInfo::ModRef));
379380
}
380381

382+
/// Virtual base class for providers of capture information.
383+
struct CaptureInfo {
384+
virtual ~CaptureInfo() = 0;
385+
virtual bool isNotCapturedBeforeOrAt(const Value *Object,
386+
const Instruction *I) = 0;
387+
};
388+
389+
/// Context-free CaptureInfo provider, which computes and caches whether an
390+
/// object is captured in the function at all, but does not distinguish whether
391+
/// it was captured before or after the context instruction.
392+
class SimpleCaptureInfo final : public CaptureInfo {
393+
SmallDenseMap<const Value *, bool, 8> IsCapturedCache;
394+
395+
public:
396+
bool isNotCapturedBeforeOrAt(const Value *Object,
397+
const Instruction *I) override;
398+
};
399+
400+
/// Context-sensitive CaptureInfo provider, which computes and caches the
401+
/// earliest common dominator closure of all captures. It provides a good
402+
/// approximation to a precise "captures before" analysis.
403+
class EarliestEscapeInfo final : public CaptureInfo {
404+
DominatorTree &DT;
405+
const LoopInfo &LI;
406+
407+
/// Map from identified local object to an instruction before which it does
408+
/// not escape, or nullptr if it never escapes. The "earliest" instruction
409+
/// may be a conservative approximation, e.g. the first instruction in the
410+
/// function is always a legal choice.
411+
DenseMap<const Value *, Instruction *> EarliestEscapes;
412+
413+
/// Reverse map from instruction to the objects it is the earliest escape for.
414+
/// This is used for cache invalidation purposes.
415+
DenseMap<Instruction *, TinyPtrVector<const Value *>> Inst2Obj;
416+
417+
public:
418+
EarliestEscapeInfo(DominatorTree &DT, const LoopInfo &LI) : DT(DT), LI(LI) {}
419+
420+
bool isNotCapturedBeforeOrAt(const Value *Object,
421+
const Instruction *I) override;
422+
423+
void removeInstruction(Instruction *I);
424+
};
425+
381426
/// Reduced version of MemoryLocation that only stores a pointer and size.
382427
/// Used for caching AATags independent BasicAA results.
383428
struct AACacheLoc {
@@ -425,8 +470,7 @@ class AAQueryInfo {
425470
using AliasCacheT = SmallDenseMap<LocPair, CacheEntry, 8>;
426471
AliasCacheT AliasCache;
427472

428-
using IsCapturedCacheT = SmallDenseMap<const Value *, bool, 8>;
429-
IsCapturedCacheT IsCapturedCache;
473+
CaptureInfo *CI;
430474

431475
/// Query depth used to distinguish recursive queries.
432476
unsigned Depth = 0;
@@ -439,18 +483,26 @@ class AAQueryInfo {
439483
/// assumption is disproven.
440484
SmallVector<AAQueryInfo::LocPair, 4> AssumptionBasedResults;
441485

442-
AAQueryInfo() : AliasCache(), IsCapturedCache() {}
486+
AAQueryInfo(CaptureInfo *CI) : CI(CI) {}
443487

444488
/// Create a new AAQueryInfo based on this one, but with the cache cleared.
445489
/// This is used for recursive queries across phis, where cache results may
446490
/// not be valid.
447491
AAQueryInfo withEmptyCache() {
448-
AAQueryInfo NewAAQI;
492+
AAQueryInfo NewAAQI(CI);
449493
NewAAQI.Depth = Depth;
450494
return NewAAQI;
451495
}
452496
};
453497

498+
/// AAQueryInfo that uses SimpleCaptureInfo.
499+
class SimpleAAQueryInfo : public AAQueryInfo {
500+
SimpleCaptureInfo CI;
501+
502+
public:
503+
SimpleAAQueryInfo() : AAQueryInfo(&CI) {}
504+
};
505+
454506
class BatchAAResults;
455507

456508
class AAResults {
@@ -770,7 +822,7 @@ class AAResults {
770822
/// helpers above.
771823
ModRefInfo getModRefInfo(const Instruction *I,
772824
const Optional<MemoryLocation> &OptLoc) {
773-
AAQueryInfo AAQIP;
825+
SimpleAAQueryInfo AAQIP;
774826
return getModRefInfo(I, OptLoc, AAQIP);
775827
}
776828

@@ -797,7 +849,7 @@ class AAResults {
797849
ModRefInfo callCapturesBefore(const Instruction *I,
798850
const MemoryLocation &MemLoc,
799851
DominatorTree *DT) {
800-
AAQueryInfo AAQIP;
852+
SimpleAAQueryInfo AAQIP;
801853
return callCapturesBefore(I, MemLoc, DT, AAQIP);
802854
}
803855

@@ -896,9 +948,12 @@ class AAResults {
896948
class BatchAAResults {
897949
AAResults &AA;
898950
AAQueryInfo AAQI;
951+
SimpleCaptureInfo SimpleCI;
899952

900953
public:
901-
BatchAAResults(AAResults &AAR) : AA(AAR), AAQI() {}
954+
BatchAAResults(AAResults &AAR) : AA(AAR), AAQI(&SimpleCI) {}
955+
BatchAAResults(AAResults &AAR, CaptureInfo *CI) : AA(AAR), AAQI(CI) {}
956+
902957
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
903958
return AA.alias(LocA, LocB, AAQI);
904959
}

llvm/lib/Analysis/AliasAnalysis.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ bool AAResults::invalidate(Function &F, const PreservedAnalyses &PA,
119119

120120
AliasResult AAResults::alias(const MemoryLocation &LocA,
121121
const MemoryLocation &LocB) {
122-
AAQueryInfo AAQIP;
122+
SimpleAAQueryInfo AAQIP;
123123
return alias(LocA, LocB, AAQIP);
124124
}
125125

@@ -162,7 +162,7 @@ AliasResult AAResults::alias(const MemoryLocation &LocA,
162162

163163
bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc,
164164
bool OrLocal) {
165-
AAQueryInfo AAQIP;
165+
SimpleAAQueryInfo AAQIP;
166166
return pointsToConstantMemory(Loc, AAQIP, OrLocal);
167167
}
168168

@@ -190,7 +190,7 @@ ModRefInfo AAResults::getArgModRefInfo(const CallBase *Call, unsigned ArgIdx) {
190190
}
191191

192192
ModRefInfo AAResults::getModRefInfo(Instruction *I, const CallBase *Call2) {
193-
AAQueryInfo AAQIP;
193+
SimpleAAQueryInfo AAQIP;
194194
return getModRefInfo(I, Call2, AAQIP);
195195
}
196196

@@ -218,7 +218,7 @@ ModRefInfo AAResults::getModRefInfo(Instruction *I, const CallBase *Call2,
218218

219219
ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
220220
const MemoryLocation &Loc) {
221-
AAQueryInfo AAQIP;
221+
SimpleAAQueryInfo AAQIP;
222222
return getModRefInfo(Call, Loc, AAQIP);
223223
}
224224

@@ -285,7 +285,7 @@ ModRefInfo AAResults::getModRefInfo(const CallBase *Call,
285285

286286
ModRefInfo AAResults::getModRefInfo(const CallBase *Call1,
287287
const CallBase *Call2) {
288-
AAQueryInfo AAQIP;
288+
SimpleAAQueryInfo AAQIP;
289289
return getModRefInfo(Call1, Call2, AAQIP);
290290
}
291291

@@ -475,7 +475,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, AliasResult AR) {
475475

476476
ModRefInfo AAResults::getModRefInfo(const LoadInst *L,
477477
const MemoryLocation &Loc) {
478-
AAQueryInfo AAQIP;
478+
SimpleAAQueryInfo AAQIP;
479479
return getModRefInfo(L, Loc, AAQIP);
480480
}
481481
ModRefInfo AAResults::getModRefInfo(const LoadInst *L,
@@ -500,7 +500,7 @@ ModRefInfo AAResults::getModRefInfo(const LoadInst *L,
500500

501501
ModRefInfo AAResults::getModRefInfo(const StoreInst *S,
502502
const MemoryLocation &Loc) {
503-
AAQueryInfo AAQIP;
503+
SimpleAAQueryInfo AAQIP;
504504
return getModRefInfo(S, Loc, AAQIP);
505505
}
506506
ModRefInfo AAResults::getModRefInfo(const StoreInst *S,
@@ -532,7 +532,7 @@ ModRefInfo AAResults::getModRefInfo(const StoreInst *S,
532532
}
533533

534534
ModRefInfo AAResults::getModRefInfo(const FenceInst *S, const MemoryLocation &Loc) {
535-
AAQueryInfo AAQIP;
535+
SimpleAAQueryInfo AAQIP;
536536
return getModRefInfo(S, Loc, AAQIP);
537537
}
538538

@@ -548,7 +548,7 @@ ModRefInfo AAResults::getModRefInfo(const FenceInst *S,
548548

549549
ModRefInfo AAResults::getModRefInfo(const VAArgInst *V,
550550
const MemoryLocation &Loc) {
551-
AAQueryInfo AAQIP;
551+
SimpleAAQueryInfo AAQIP;
552552
return getModRefInfo(V, Loc, AAQIP);
553553
}
554554

@@ -578,7 +578,7 @@ ModRefInfo AAResults::getModRefInfo(const VAArgInst *V,
578578

579579
ModRefInfo AAResults::getModRefInfo(const CatchPadInst *CatchPad,
580580
const MemoryLocation &Loc) {
581-
AAQueryInfo AAQIP;
581+
SimpleAAQueryInfo AAQIP;
582582
return getModRefInfo(CatchPad, Loc, AAQIP);
583583
}
584584

@@ -598,7 +598,7 @@ ModRefInfo AAResults::getModRefInfo(const CatchPadInst *CatchPad,
598598

599599
ModRefInfo AAResults::getModRefInfo(const CatchReturnInst *CatchRet,
600600
const MemoryLocation &Loc) {
601-
AAQueryInfo AAQIP;
601+
SimpleAAQueryInfo AAQIP;
602602
return getModRefInfo(CatchRet, Loc, AAQIP);
603603
}
604604

@@ -618,7 +618,7 @@ ModRefInfo AAResults::getModRefInfo(const CatchReturnInst *CatchRet,
618618

619619
ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX,
620620
const MemoryLocation &Loc) {
621-
AAQueryInfo AAQIP;
621+
SimpleAAQueryInfo AAQIP;
622622
return getModRefInfo(CX, Loc, AAQIP);
623623
}
624624

@@ -646,7 +646,7 @@ ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX,
646646

647647
ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW,
648648
const MemoryLocation &Loc) {
649-
AAQueryInfo AAQIP;
649+
SimpleAAQueryInfo AAQIP;
650650
return getModRefInfo(RMW, Loc, AAQIP);
651651
}
652652

llvm/lib/Analysis/BasicAliasAnalysis.cpp

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,51 @@ static bool isObjectSize(const Value *V, uint64_t Size, const DataLayout &DL,
223223
return ObjectSize != MemoryLocation::UnknownSize && ObjectSize == Size;
224224
}
225225

226+
//===----------------------------------------------------------------------===//
227+
// CaptureInfo implementations
228+
//===----------------------------------------------------------------------===//
229+
230+
CaptureInfo::~CaptureInfo() = default;
231+
232+
bool SimpleCaptureInfo::isNotCapturedBeforeOrAt(const Value *Object,
233+
const Instruction *I) {
234+
return isNonEscapingLocalObject(Object, &IsCapturedCache);
235+
}
236+
237+
bool EarliestEscapeInfo::isNotCapturedBeforeOrAt(const Value *Object,
238+
const Instruction *I) {
239+
if (!isIdentifiedFunctionLocal(Object))
240+
return false;
241+
242+
auto Iter = EarliestEscapes.insert({Object, nullptr});
243+
if (Iter.second) {
244+
Instruction *EarliestCapture = FindEarliestCapture(
245+
Object, *const_cast<Function *>(I->getFunction()),
246+
/*ReturnCaptures=*/false, /*StoreCaptures=*/true, DT);
247+
if (EarliestCapture) {
248+
auto Ins = Inst2Obj.insert({EarliestCapture, {}});
249+
Ins.first->second.push_back(Object);
250+
}
251+
Iter.first->second = EarliestCapture;
252+
}
253+
254+
// No capturing instruction.
255+
if (!Iter.first->second)
256+
return true;
257+
258+
return I != Iter.first->second &&
259+
!isPotentiallyReachable(Iter.first->second, I, nullptr, &DT, &LI);
260+
}
261+
262+
void EarliestEscapeInfo::removeInstruction(Instruction *I) {
263+
auto Iter = Inst2Obj.find(I);
264+
if (Iter != Inst2Obj.end()) {
265+
for (const Value *Obj : Iter->second)
266+
EarliestEscapes.erase(Obj);
267+
Inst2Obj.erase(I);
268+
}
269+
}
270+
226271
//===----------------------------------------------------------------------===//
227272
// GetElementPtr Instruction Decomposition and Analysis
228273
//===----------------------------------------------------------------------===//
@@ -835,7 +880,7 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
835880
// then the call can not mod/ref the pointer unless the call takes the pointer
836881
// as an argument, and itself doesn't capture it.
837882
if (!isa<Constant>(Object) && Call != Object &&
838-
isNonEscapingLocalObject(Object, &AAQI.IsCapturedCache)) {
883+
AAQI.CI->isNotCapturedBeforeOrAt(Object, Call)) {
839884

840885
// Optimistically assume that call doesn't touch Object and check this
841886
// assumption in the following loop.
@@ -1514,10 +1559,10 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
15141559
// location if that memory location doesn't escape. Or it may pass a
15151560
// nocapture value to other functions as long as they don't capture it.
15161561
if (isEscapeSource(O1) &&
1517-
isNonEscapingLocalObject(O2, &AAQI.IsCapturedCache))
1562+
AAQI.CI->isNotCapturedBeforeOrAt(O2, cast<Instruction>(O1)))
15181563
return AliasResult::NoAlias;
15191564
if (isEscapeSource(O2) &&
1520-
isNonEscapingLocalObject(O1, &AAQI.IsCapturedCache))
1565+
AAQI.CI->isNotCapturedBeforeOrAt(O1, cast<Instruction>(O2)))
15211566
return AliasResult::NoAlias;
15221567
}
15231568

0 commit comments

Comments
 (0)