aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/BasicAliasAnalysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/BasicAliasAnalysis.cpp')
-rw-r--r--llvm/lib/Analysis/BasicAliasAnalysis.cpp86
1 files changed, 51 insertions, 35 deletions
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index f862d69..31611df 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -192,18 +192,20 @@ static bool areBothVScale(const Value *V1, const Value *V2) {
CaptureAnalysis::~CaptureAnalysis() = default;
-bool SimpleCaptureAnalysis::isNotCapturedBefore(const Value *Object,
- const Instruction *I,
- bool OrAt) {
+CaptureComponents SimpleCaptureAnalysis::getCapturesBefore(const Value *Object,
+ const Instruction *I,
+ bool OrAt) {
if (!isIdentifiedFunctionLocal(Object))
- return false;
+ return CaptureComponents::Provenance;
- auto [CacheIt, Inserted] = IsCapturedCache.insert({Object, false});
+ auto [CacheIt, Inserted] =
+ IsCapturedCache.insert({Object, CaptureComponents::Provenance});
if (!Inserted)
return CacheIt->second;
- bool Ret = !capturesAnything(PointerMayBeCaptured(
- Object, /*ReturnCaptures=*/false, CaptureComponents::Provenance));
+ CaptureComponents Ret = PointerMayBeCaptured(
+ Object, /*ReturnCaptures=*/false, CaptureComponents::Provenance,
+ [](CaptureComponents CC) { return capturesFullProvenance(CC); });
CacheIt->second = Ret;
return Ret;
}
@@ -216,37 +218,44 @@ static bool isNotInCycle(const Instruction *I, const DominatorTree *DT,
!isPotentiallyReachableFromMany(Succs, BB, nullptr, DT, LI);
}
-bool EarliestEscapeAnalysis::isNotCapturedBefore(const Value *Object,
- const Instruction *I,
- bool OrAt) {
+CaptureComponents
+EarliestEscapeAnalysis::getCapturesBefore(const Value *Object,
+ const Instruction *I, bool OrAt) {
if (!isIdentifiedFunctionLocal(Object))
- return false;
+ return CaptureComponents::Provenance;
auto Iter = EarliestEscapes.try_emplace(Object);
if (Iter.second) {
- Instruction *EarliestCapture = FindEarliestCapture(
- Object, *const_cast<Function *>(DT.getRoot()->getParent()),
- /*ReturnCaptures=*/false, DT, CaptureComponents::Provenance);
- if (EarliestCapture)
- Inst2Obj[EarliestCapture].push_back(Object);
+ std::pair<Instruction *, CaptureComponents> EarliestCapture =
+ FindEarliestCapture(
+ Object, *const_cast<Function *>(DT.getRoot()->getParent()),
+ /*ReturnCaptures=*/false, DT, CaptureComponents::Provenance);
+ if (EarliestCapture.first)
+ Inst2Obj[EarliestCapture.first].push_back(Object);
Iter.first->second = EarliestCapture;
}
- // No capturing instruction.
- if (!Iter.first->second)
- return true;
-
- // No context instruction means any use is capturing.
- if (!I)
- return false;
+ auto IsNotCapturedBefore = [&]() {
+ // No capturing instruction.
+ Instruction *CaptureInst = Iter.first->second.first;
+ if (!CaptureInst)
+ return true;
- if (I == Iter.first->second) {
- if (OrAt)
+ // No context instruction means any use is capturing.
+ if (!I)
return false;
- return isNotInCycle(I, &DT, LI);
- }
- return !isPotentiallyReachable(Iter.first->second, I, nullptr, &DT, LI);
+ if (I == CaptureInst) {
+ if (OrAt)
+ return false;
+ return isNotInCycle(I, &DT, LI);
+ }
+
+ return !isPotentiallyReachable(CaptureInst, I, nullptr, &DT, LI);
+ };
+ if (IsNotCapturedBefore())
+ return CaptureComponents::None;
+ return Iter.first->second.second;
}
void EarliestEscapeAnalysis::removeInstruction(Instruction *I) {
@@ -946,9 +955,14 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
// As an exception, ignore allocas, as setjmp is not required to preserve
// non-volatile stores for them.
if (isModOrRefSet(OtherMR) && !isa<Constant>(Object) && Call != Object &&
- AAQI.CA->isNotCapturedBefore(Object, Call, /*OrAt=*/false) &&
- (isa<AllocaInst>(Object) || !Call->hasFnAttr(Attribute::ReturnsTwice)))
- OtherMR = ModRefInfo::NoModRef;
+ (isa<AllocaInst>(Object) || !Call->hasFnAttr(Attribute::ReturnsTwice))) {
+ CaptureComponents CC =
+ AAQI.CA->getCapturesBefore(Object, Call, /*OrAt=*/false);
+ if (capturesNothing(CC))
+ OtherMR = ModRefInfo::NoModRef;
+ else if (capturesReadProvenanceOnly(CC))
+ OtherMR = ModRefInfo::Ref;
+ }
// Refine the modref info for argument memory. We only bother to do this
// if ArgMR is not a subset of OtherMR, otherwise this won't have an impact
@@ -1614,11 +1628,13 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
// temporary store the nocapture argument's value in a temporary memory
// location if that memory location doesn't escape. Or it may pass a
// nocapture value to other functions as long as they don't capture it.
- if (isEscapeSource(O1) && AAQI.CA->isNotCapturedBefore(
- O2, dyn_cast<Instruction>(O1), /*OrAt*/ true))
+ if (isEscapeSource(O1) &&
+ capturesNothing(AAQI.CA->getCapturesBefore(
+ O2, dyn_cast<Instruction>(O1), /*OrAt*/ true)))
return AliasResult::NoAlias;
- if (isEscapeSource(O2) && AAQI.CA->isNotCapturedBefore(
- O1, dyn_cast<Instruction>(O2), /*OrAt*/ true))
+ if (isEscapeSource(O2) &&
+ capturesNothing(AAQI.CA->getCapturesBefore(
+ O1, dyn_cast<Instruction>(O2), /*OrAt*/ true)))
return AliasResult::NoAlias;
}