@@ -192,18 +192,20 @@ static bool areBothVScale(const Value *V1, const Value *V2) {
192192
193193CaptureAnalysis::~CaptureAnalysis () = default ;
194194
195- bool SimpleCaptureAnalysis::isNotCapturedBefore (const Value *Object,
196- const Instruction *I,
197- bool OrAt) {
195+ CaptureComponents SimpleCaptureAnalysis::getCapturesBefore (const Value *Object,
196+ const Instruction *I,
197+ bool OrAt) {
198198 if (!isIdentifiedFunctionLocal (Object))
199- return false ;
199+ return CaptureComponents::Provenance ;
200200
201- auto [CacheIt, Inserted] = IsCapturedCache.insert ({Object, false });
201+ auto [CacheIt, Inserted] =
202+ IsCapturedCache.insert ({Object, CaptureComponents::Provenance});
202203 if (!Inserted)
203204 return CacheIt->second ;
204205
205- bool Ret = !capturesAnything (PointerMayBeCaptured (
206- Object, /* ReturnCaptures=*/ false , CaptureComponents::Provenance));
206+ CaptureComponents Ret = PointerMayBeCaptured (
207+ Object, /* ReturnCaptures=*/ false , CaptureComponents::Provenance,
208+ [](CaptureComponents CC) { return capturesFullProvenance (CC); });
207209 CacheIt->second = Ret;
208210 return Ret;
209211}
@@ -216,37 +218,44 @@ static bool isNotInCycle(const Instruction *I, const DominatorTree *DT,
216218 !isPotentiallyReachableFromMany (Succs, BB, nullptr , DT, LI);
217219}
218220
219- bool EarliestEscapeAnalysis::isNotCapturedBefore ( const Value *Object,
220- const Instruction *I ,
221- bool OrAt) {
221+ CaptureComponents
222+ EarliestEscapeAnalysis::getCapturesBefore ( const Value *Object ,
223+ const Instruction *I, bool OrAt) {
222224 if (!isIdentifiedFunctionLocal (Object))
223- return false ;
225+ return CaptureComponents::Provenance ;
224226
225227 auto Iter = EarliestEscapes.try_emplace (Object);
226228 if (Iter.second ) {
227- Instruction *EarliestCapture = FindEarliestCapture (
228- Object, *const_cast <Function *>(DT.getRoot ()->getParent ()),
229- /* ReturnCaptures=*/ false , DT, CaptureComponents::Provenance);
230- if (EarliestCapture)
231- Inst2Obj[EarliestCapture].push_back (Object);
229+ std::pair<Instruction *, CaptureComponents> EarliestCapture =
230+ FindEarliestCapture (
231+ Object, *const_cast <Function *>(DT.getRoot ()->getParent ()),
232+ /* ReturnCaptures=*/ false , DT, CaptureComponents::Provenance);
233+ if (EarliestCapture.first )
234+ Inst2Obj[EarliestCapture.first ].push_back (Object);
232235 Iter.first ->second = EarliestCapture;
233236 }
234237
235- // No capturing instruction.
236- if (!Iter.first ->second )
237- return true ;
238-
239- // No context instruction means any use is capturing.
240- if (!I)
241- return false ;
238+ auto IsNotCapturedBefore = [&]() {
239+ // No capturing instruction.
240+ Instruction *CaptureInst = Iter.first ->second .first ;
241+ if (!CaptureInst)
242+ return true ;
242243
243- if (I == Iter. first -> second ) {
244- if (OrAt )
244+ // No context instruction means any use is capturing.
245+ if (!I )
245246 return false ;
246- return isNotInCycle (I, &DT, LI);
247- }
248247
249- return !isPotentiallyReachable (Iter.first ->second , I, nullptr , &DT, LI);
248+ if (I == CaptureInst) {
249+ if (OrAt)
250+ return false ;
251+ return isNotInCycle (I, &DT, LI);
252+ }
253+
254+ return !isPotentiallyReachable (CaptureInst, I, nullptr , &DT, LI);
255+ };
256+ if (IsNotCapturedBefore ())
257+ return CaptureComponents::None;
258+ return Iter.first ->second .second ;
250259}
251260
252261void EarliestEscapeAnalysis::removeInstruction (Instruction *I) {
@@ -946,9 +955,14 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
946955 // As an exception, ignore allocas, as setjmp is not required to preserve
947956 // non-volatile stores for them.
948957 if (isModOrRefSet (OtherMR) && !isa<Constant>(Object) && Call != Object &&
949- AAQI.CA ->isNotCapturedBefore (Object, Call, /* OrAt=*/ false ) &&
950- (isa<AllocaInst>(Object) || !Call->hasFnAttr (Attribute::ReturnsTwice)))
951- OtherMR = ModRefInfo::NoModRef;
958+ (isa<AllocaInst>(Object) || !Call->hasFnAttr (Attribute::ReturnsTwice))) {
959+ CaptureComponents CC =
960+ AAQI.CA ->getCapturesBefore (Object, Call, /* OrAt=*/ false );
961+ if (capturesNothing (CC))
962+ OtherMR = ModRefInfo::NoModRef;
963+ else if (capturesReadProvenanceOnly (CC))
964+ OtherMR = ModRefInfo::Ref;
965+ }
952966
953967 // Refine the modref info for argument memory. We only bother to do this
954968 // 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,
16141628 // temporary store the nocapture argument's value in a temporary memory
16151629 // location if that memory location doesn't escape. Or it may pass a
16161630 // nocapture value to other functions as long as they don't capture it.
1617- if (isEscapeSource (O1) && AAQI.CA ->isNotCapturedBefore (
1618- O2, dyn_cast<Instruction>(O1), /* OrAt*/ true ))
1631+ if (isEscapeSource (O1) &&
1632+ capturesNothing (AAQI.CA ->getCapturesBefore (
1633+ O2, dyn_cast<Instruction>(O1), /* OrAt*/ true )))
16191634 return AliasResult::NoAlias;
1620- if (isEscapeSource (O2) && AAQI.CA ->isNotCapturedBefore (
1621- O1, dyn_cast<Instruction>(O2), /* OrAt*/ true ))
1635+ if (isEscapeSource (O2) &&
1636+ capturesNothing (AAQI.CA ->getCapturesBefore (
1637+ O1, dyn_cast<Instruction>(O2), /* OrAt*/ true )))
16221638 return AliasResult::NoAlias;
16231639 }
16241640
0 commit comments