Skip to content

Commit 599e806

Browse files
committed
Introduce separate UseCaptureInfo class
1 parent 3cc1dc5 commit 599e806

File tree

8 files changed

+90
-70
lines changed

8 files changed

+90
-70
lines changed

llvm/include/llvm/Analysis/CaptureTracking.h

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LLVM_ANALYSIS_CAPTURETRACKING_H
1515

1616
#include "llvm/ADT/DenseMap.h"
17+
#include "llvm/Support/ModRef.h"
1718

1819
namespace llvm {
1920

@@ -78,6 +79,28 @@ namespace llvm {
7879
const DominatorTree &DT,
7980
unsigned MaxUsesToExplore = 0);
8081

82+
/// Capture information for a specific Use.
83+
struct UseCaptureInfo {
84+
/// Components captured by this use.
85+
CaptureComponents UseCC;
86+
/// Components captured by the return value of the user of this Use.
87+
CaptureComponents ResultCC;
88+
89+
UseCaptureInfo(CaptureComponents UseCC,
90+
CaptureComponents ResultCC = CaptureComponents::None)
91+
: UseCC(UseCC), ResultCC(ResultCC) {}
92+
93+
static UseCaptureInfo passthrough() {
94+
return UseCaptureInfo(CaptureComponents::None, CaptureComponents::All);
95+
}
96+
97+
bool isPassthrough() const {
98+
return capturesNothing(UseCC) && capturesAnything(ResultCC);
99+
}
100+
101+
operator CaptureComponents() const { return UseCC | ResultCC; }
102+
};
103+
81104
/// This callback is used in conjunction with PointerMayBeCaptured. In
82105
/// addition to the interface here, you'll need to provide your own getters
83106
/// to see whether anything was captured.
@@ -110,12 +133,12 @@ namespace llvm {
110133
/// U->getUser() is always an Instruction.
111134
virtual bool shouldExplore(const Use *U);
112135

113-
/// Use U directly captures CI.getOtherComponents() and additionally
114-
/// CI.getRetComponents() through the return value of the user of U.
136+
/// Use U directly captures CI.UseCC and additionally CI.ResultCC
137+
/// through the return value of the user of U.
115138
///
116139
/// Return one of Stop, Continue or ContinueIgnoringReturn to control
117140
/// further traversal.
118-
virtual Action captured(const Use *U, CaptureInfo CI) = 0;
141+
virtual Action captured(const Use *U, UseCaptureInfo CI) = 0;
119142

120143
/// isDereferenceableOrNull - Overload to allow clients with additional
121144
/// knowledge about pointer dereferenceability to provide it and thereby
@@ -125,15 +148,15 @@ namespace llvm {
125148

126149
/// Determine what kind of capture behaviour \p U may exhibit.
127150
///
128-
/// The Other part of the returned CaptureInfo indicates which component of
129-
/// the pointer may be captured directly by the use. The Ret part indicates
130-
/// which components may be captured by following uses of the user of \p U.
131-
/// The \p IsDereferenceableOrNull callback is used to rule out capturing for
132-
/// certain comparisons.
151+
/// The returned UseCaptureInfo contains the components captured directly
152+
/// by the use (UseCC) and the components captured through the return value
153+
/// of the user (ResultCC).
133154
///
134155
/// \p Base is the starting value of the capture analysis, which is
135156
/// relevant for address_is_null captures.
136-
CaptureInfo
157+
/// The \p IsDereferenceableOrNull callback is used to rule out capturing for
158+
/// certain comparisons.
159+
UseCaptureInfo
137160
DetermineUseCaptureKind(const Use &U, const Value *Base,
138161
llvm::function_ref<bool(Value *, const DataLayout &)>
139162
IsDereferenceableOrNull);

llvm/lib/Analysis/CaptureTracking.cpp

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ struct SimpleCaptureTracker : public CaptureTracker {
8181
Captured = true;
8282
}
8383

84-
Action captured(const Use *U, CaptureInfo CI) override {
85-
// TODO(captures): Use CaptureInfo.
84+
Action captured(const Use *U, UseCaptureInfo CI) override {
85+
// TODO(captures): Use UseCaptureInfo.
8686
if (isa<ReturnInst>(U->getUser()) && !ReturnCaptures)
8787
return ContinueIgnoringReturn;
8888

@@ -123,8 +123,8 @@ struct CapturesBefore : public CaptureTracker {
123123
return !isPotentiallyReachable(I, BeforeHere, nullptr, DT, LI);
124124
}
125125

126-
Action captured(const Use *U, CaptureInfo CI) override {
127-
// TODO(captures): Use CaptureInfo.
126+
Action captured(const Use *U, UseCaptureInfo CI) override {
127+
// TODO(captures): Use UseCaptureInfo.
128128
Instruction *I = cast<Instruction>(U->getUser());
129129
if (isa<ReturnInst>(I) && !ReturnCaptures)
130130
return ContinueIgnoringReturn;
@@ -169,8 +169,8 @@ struct EarliestCaptures : public CaptureTracker {
169169
EarliestCapture = &*F.getEntryBlock().begin();
170170
}
171171

172-
Action captured(const Use *U, CaptureInfo CI) override {
173-
// TODO(captures): Use CaptureInfo.
172+
Action captured(const Use *U, UseCaptureInfo CI) override {
173+
// TODO(captures): Use UseCaptureInfo.
174174
Instruction *I = cast<Instruction>(U->getUser());
175175
if (isa<ReturnInst>(I) && !ReturnCaptures)
176176
return ContinueIgnoringReturn;
@@ -279,14 +279,14 @@ Instruction *llvm::FindEarliestCapture(const Value *V, Function &F,
279279
return CB.EarliestCapture;
280280
}
281281

282-
CaptureInfo llvm::DetermineUseCaptureKind(
282+
UseCaptureInfo llvm::DetermineUseCaptureKind(
283283
const Use &U, const Value *Base,
284284
function_ref<bool(Value *, const DataLayout &)> IsDereferenceableOrNull) {
285285
Instruction *I = dyn_cast<Instruction>(U.getUser());
286286

287287
// TODO: Investigate non-instruction uses.
288288
if (!I)
289-
return CaptureInfo::otherOnly();
289+
return CaptureComponents::All;
290290

291291
switch (I->getOpcode()) {
292292
case Instruction::Call:
@@ -298,21 +298,21 @@ CaptureInfo llvm::DetermineUseCaptureKind(
298298
// by throwing an exception or not depending on the input value).
299299
if (Call->onlyReadsMemory() && Call->doesNotThrow() &&
300300
Call->getType()->isVoidTy())
301-
return CaptureInfo::none();
301+
return CaptureComponents::None;
302302

303303
// The pointer is not captured if returned pointer is not captured.
304304
// NOTE: CaptureTracking users should not assume that only functions
305305
// marked with nocapture do not capture. This means that places like
306306
// getUnderlyingObject in ValueTracking or DecomposeGEPExpression
307307
// in BasicAA also need to know about this property.
308308
if (isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(Call, true))
309-
return CaptureInfo::retOnly();
309+
return UseCaptureInfo::passthrough();
310310

311311
// Volatile operations effectively capture the memory location that they
312312
// load and store to.
313313
if (auto *MI = dyn_cast<MemIntrinsic>(Call))
314314
if (MI->isVolatile())
315-
return CaptureInfo::otherOnly();
315+
return CaptureComponents::All;
316316

317317
// Calling a function pointer does not in itself cause the pointer to
318318
// be captured. This is a subtle point considering that (for example)
@@ -321,26 +321,27 @@ CaptureInfo llvm::DetermineUseCaptureKind(
321321
// captured, even though the loaded value might be the pointer itself
322322
// (think of self-referential objects).
323323
if (Call->isCallee(&U))
324-
return CaptureInfo::none();
324+
return CaptureComponents::None;
325325

326326
// Not captured if only passed via 'nocapture' arguments.
327327
assert(Call->isDataOperand(&U) && "Non-callee must be data operand");
328-
return Call->getCaptureInfo(Call->getDataOperandNo(&U));
328+
CaptureInfo CI = Call->getCaptureInfo(Call->getDataOperandNo(&U));
329+
return UseCaptureInfo(CI.getOtherComponents(), CI.getRetComponents());
329330
}
330331
case Instruction::Load:
331332
// Volatile loads make the address observable.
332333
if (cast<LoadInst>(I)->isVolatile())
333-
return CaptureInfo::otherOnly();
334-
return CaptureInfo::none();
334+
return CaptureComponents::All;
335+
return CaptureComponents::None;
335336
case Instruction::VAArg:
336337
// "va-arg" from a pointer does not cause it to be captured.
337-
return CaptureInfo::none();
338+
return CaptureComponents::None;
338339
case Instruction::Store:
339340
// Stored the pointer - conservatively assume it may be captured.
340341
// Volatile stores make the address observable.
341342
if (U.getOperandNo() == 0 || cast<StoreInst>(I)->isVolatile())
342-
return CaptureInfo::otherOnly();
343-
return CaptureInfo::none();
343+
return CaptureComponents::All;
344+
return CaptureComponents::None;
344345
case Instruction::AtomicRMW: {
345346
// atomicrmw conceptually includes both a load and store from
346347
// the same location.
@@ -349,8 +350,8 @@ CaptureInfo llvm::DetermineUseCaptureKind(
349350
// Volatile stores make the address observable.
350351
auto *ARMWI = cast<AtomicRMWInst>(I);
351352
if (U.getOperandNo() == 1 || ARMWI->isVolatile())
352-
return CaptureInfo::otherOnly();
353-
return CaptureInfo::none();
353+
return CaptureComponents::All;
354+
return CaptureComponents::None;
354355
}
355356
case Instruction::AtomicCmpXchg: {
356357
// cmpxchg conceptually includes both a load and store from
@@ -360,21 +361,21 @@ CaptureInfo llvm::DetermineUseCaptureKind(
360361
// Volatile stores make the address observable.
361362
auto *ACXI = cast<AtomicCmpXchgInst>(I);
362363
if (U.getOperandNo() == 1 || U.getOperandNo() == 2 || ACXI->isVolatile())
363-
return CaptureInfo::otherOnly();
364-
return CaptureInfo::none();
364+
return CaptureComponents::All;
365+
return CaptureComponents::None;
365366
}
366367
case Instruction::GetElementPtr:
367368
// AA does not support pointers of vectors, so GEP vector splats need to
368369
// be considered as captures.
369370
if (I->getType()->isVectorTy())
370-
return CaptureInfo::otherOnly();
371-
return CaptureInfo::retOnly();
371+
return CaptureComponents::All;
372+
return UseCaptureInfo::passthrough();
372373
case Instruction::BitCast:
373374
case Instruction::PHI:
374375
case Instruction::Select:
375376
case Instruction::AddrSpaceCast:
376377
// The original value is not captured via this if the new value isn't.
377-
return CaptureInfo::retOnly();
378+
return UseCaptureInfo::passthrough();
378379
case Instruction::ICmp: {
379380
unsigned Idx = U.getOperandNo();
380381
unsigned OtherIdx = 1 - Idx;
@@ -388,31 +389,31 @@ CaptureInfo llvm::DetermineUseCaptureKind(
388389
// with null, for example.
389390
if (U->getType()->getPointerAddressSpace() == 0)
390391
if (isNoAliasCall(U.get()->stripPointerCasts()))
391-
return CaptureInfo::none();
392+
return CaptureComponents::None;
392393
if (!I->getFunction()->nullPointerIsDefined()) {
393394
auto *O = I->getOperand(Idx)->stripPointerCastsSameRepresentation();
394395
// Comparing a dereferenceable_or_null pointer against null cannot
395396
// lead to pointer escapes, because if it is not null it must be a
396397
// valid (in-bounds) pointer.
397398
const DataLayout &DL = I->getDataLayout();
398399
if (IsDereferenceableOrNull && IsDereferenceableOrNull(O, DL))
399-
return CaptureInfo::none();
400+
return CaptureComponents::None;
400401
}
401402

402403
// Check whether this is a comparison of the base pointer against
403404
// null.
404405
if (U.get() == Base)
405-
return CaptureInfo::otherOnly(CaptureComponents::AddressIsNull);
406+
return CaptureComponents::AddressIsNull;
406407
}
407408

408409
// Otherwise, be conservative. There are crazy ways to capture pointers
409410
// using comparisons. However, only the address is captured, not the
410411
// provenance.
411-
return CaptureInfo::otherOnly(CaptureComponents::Address);
412+
return CaptureComponents::Address;
412413
}
413414
default:
414415
// Something else - be conservative and say it is captured.
415-
return CaptureInfo::otherOnly();
416+
return CaptureComponents::All;
416417
}
417418
}
418419

@@ -450,29 +451,25 @@ void llvm::PointerMayBeCaptured(const Value *V, CaptureTracker *Tracker,
450451
};
451452
while (!Worklist.empty()) {
452453
const Use *U = Worklist.pop_back_val();
453-
CaptureInfo CI = DetermineUseCaptureKind(*U, V, IsDereferenceableOrNull);
454-
if (capturesNothing(CI))
455-
continue;
456-
CaptureComponents OtherCC = CI.getOtherComponents();
457-
CaptureComponents RetCC = CI.getRetComponents();
458-
if (capturesAnything(OtherCC)) {
454+
UseCaptureInfo CI = DetermineUseCaptureKind(*U, V, IsDereferenceableOrNull);
455+
if (capturesAnything(CI.UseCC)) {
459456
switch (Tracker->captured(U, CI)) {
460457
case CaptureTracker::Stop:
461458
return;
462459
case CaptureTracker::ContinueIgnoringReturn:
463460
continue;
464461
case CaptureTracker::Continue:
465-
// Fall through to passthrough handling, but only if RetCC contains
466-
// additional components that OtherCC does not. We assume that a
462+
// Fall through to passthrough handling, but only if ResultCC contains
463+
// additional components that UseCC does not. We assume that a
467464
// capture at this point will be strictly more constraining than a
468465
// later capture from following the return value.
469-
if (capturesNothing(RetCC & ~OtherCC))
466+
if (capturesNothing(CI.ResultCC & ~CI.UseCC))
470467
continue;
471468
break;
472469
}
473470
}
474-
// TODO(captures): We could keep track of RetCC for the users.
475-
if (capturesAnything(RetCC) && !AddUses(U->getUser()))
471+
// TODO(captures): We could keep track of ResultCC for the users.
472+
if (capturesAnything(CI.ResultCC) && !AddUses(U->getUser()))
476473
return;
477474
}
478475

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2788,8 +2788,8 @@ static Constant *computePointerICmp(CmpPredicate Pred, Value *LHS, Value *RHS,
27882788
struct CustomCaptureTracker : public CaptureTracker {
27892789
bool Captured = false;
27902790
void tooManyUses() override { Captured = true; }
2791-
Action captured(const Use *U, CaptureInfo CI) override {
2792-
// TODO(captures): Use CaptureInfo.
2791+
Action captured(const Use *U, UseCaptureInfo CI) override {
2792+
// TODO(captures): Use UseCaptureInfo.
27932793
if (auto *ICmp = dyn_cast<ICmpInst>(U->getUser())) {
27942794
// Comparison against value stored in global variable. Given the
27952795
// pointer does not escape, its value cannot be guessed and stored

llvm/lib/Transforms/IPO/AttributorAttributes.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3971,11 +3971,11 @@ struct AANoAliasCallSiteArgument final : AANoAliasImpl {
39713971
// is CGSCC runs. For those we would need to "allow" AANoCapture for
39723972
// a value in the module slice.
39733973
// TODO(captures): Make this more precise.
3974-
CaptureInfo CI =
3974+
UseCaptureInfo CI =
39753975
DetermineUseCaptureKind(U, /*Base=*/nullptr, IsDereferenceableOrNull);
39763976
if (capturesNothing(CI))
39773977
return true;
3978-
if (CI.isRetOnly()) {
3978+
if (CI.isPassthrough()) {
39793979
Follow = true;
39803980
return true;
39813981
}
@@ -6019,11 +6019,11 @@ ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
60196019

60206020
auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
60216021
// TODO(captures): Make this more precise.
6022-
CaptureInfo CI =
6022+
UseCaptureInfo CI =
60236023
DetermineUseCaptureKind(U, /*Base=*/nullptr, IsDereferenceableOrNull);
60246024
if (capturesNothing(CI))
60256025
return true;
6026-
if (CI.isRetOnly()) {
6026+
if (CI.isPassthrough()) {
60276027
Follow = true;
60286028
return true;
60296029
}
@@ -12151,8 +12151,8 @@ struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {
1215112151
auto UsePred = [&](const Use &U, bool &Follow) -> bool {
1215212152
Uses.insert(&U);
1215312153
// TODO(captures): Make this more precise.
12154-
CaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr, nullptr);
12155-
if (capturesAnything(CI) && CI.isRetOnly()) {
12154+
UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr, nullptr);
12155+
if (CI.isPassthrough()) {
1215612156
Follow = true;
1215712157
return true;
1215812158
}

llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,8 +549,8 @@ struct ArgumentUsesTracker : public CaptureTracker {
549549

550550
void tooManyUses() override { CI = CaptureInfo::all(); }
551551

552-
Action captured(const Use *U, CaptureInfo UseCI) override {
553-
if (updateCaptureInfo(U, UseCI.getOtherComponents())) {
552+
Action captured(const Use *U, UseCaptureInfo UseCI) override {
553+
if (updateCaptureInfo(U, UseCI.UseCC)) {
554554
// Don't bother continuing if we already capture everything.
555555
if (capturesAll(CI.getOtherComponents()))
556556
return Stop;

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -882,8 +882,8 @@ bool InstCombinerImpl::foldAllocaCmp(AllocaInst *Alloca) {
882882

883883
void tooManyUses() override { Captured = true; }
884884

885-
Action captured(const Use *U, CaptureInfo CI) override {
886-
// TODO(captures): Use CaptureInfo.
885+
Action captured(const Use *U, UseCaptureInfo CI) override {
886+
// TODO(captures): Use UseCaptureInfo.
887887
auto *ICmp = dyn_cast<ICmpInst>(U->getUser());
888888
// We need to check that U is based *only* on the alloca, and doesn't
889889
// have other contributions from a select/phi operand.

llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,17 +1550,17 @@ bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,
15501550
}
15511551
if (!Visited.insert(&U).second)
15521552
continue;
1553-
CaptureInfo CI =
1553+
UseCaptureInfo CI =
15541554
DetermineUseCaptureKind(U, AI, IsDereferenceableOrNull);
15551555
// TODO(captures): Make this more precise.
1556-
if (capturesAnything(CI)) {
1557-
if (CI.isRetOnly()) {
1558-
Worklist.push_back(UI);
1559-
continue;
1560-
}
1561-
return false;
1556+
if (CI.isPassthrough()) {
1557+
Worklist.push_back(UI);
1558+
continue;
15621559
}
15631560

1561+
if (capturesAnything(CI))
1562+
return false;
1563+
15641564
if (UI->isLifetimeStartOrEnd()) {
15651565
// We note the locations of these intrinsic calls so that we can
15661566
// delete them later if the optimization succeeds, this is safe

0 commit comments

Comments
 (0)