1 //===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements the AliasSetTracker and AliasSet classes.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Analysis/AliasSetTracker.h"
14 #include "llvm/ADT/SetVector.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/Analysis/AliasAnalysis.h"
17 #include "llvm/Analysis/GuardUtils.h"
18 #include "llvm/Analysis/MemoryLocation.h"
19 #include "llvm/Config/llvm-config.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/IR/InstIterator.h"
22 #include "llvm/IR/Instructions.h"
23 #include "llvm/IR/IntrinsicInst.h"
24 #include "llvm/IR/PassManager.h"
25 #include "llvm/IR/PatternMatch.h"
26 #include "llvm/IR/Value.h"
27 #include "llvm/Pass.h"
28 #include "llvm/Support/AtomicOrdering.h"
29 #include "llvm/Support/CommandLine.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/raw_ostream.h"
37 static cl::opt
<unsigned> SaturationThreshold(
38 "alias-set-saturation-threshold", cl::Hidden
, cl::init(250),
39 cl::desc("The maximum total number of memory locations alias "
40 "sets may contain before degradation"));
42 /// mergeSetIn - Merge the specified alias set into this alias set.
43 void AliasSet::mergeSetIn(AliasSet
&AS
, AliasSetTracker
&AST
,
44 BatchAAResults
&BatchAA
) {
45 assert(!AS
.Forward
&& "Alias set is already forwarding!");
46 assert(!Forward
&& "This set is a forwarding set!!");
48 // Update the alias and access types of this set...
52 if (Alias
== SetMustAlias
) {
53 // Check that these two merged sets really are must aliases. If we cannot
54 // find a must-alias pair between them, this set becomes a may alias.
55 if (!any_of(MemoryLocs
, [&](const MemoryLocation
&MemLoc
) {
56 return any_of(AS
.MemoryLocs
, [&](const MemoryLocation
&ASMemLoc
) {
57 return BatchAA
.isMustAlias(MemLoc
, ASMemLoc
);
63 // Merge the list of constituent memory locations...
64 if (MemoryLocs
.empty()) {
65 std::swap(MemoryLocs
, AS
.MemoryLocs
);
67 append_range(MemoryLocs
, AS
.MemoryLocs
);
68 AS
.MemoryLocs
.clear();
71 bool ASHadUnknownInsts
= !AS
.UnknownInsts
.empty();
72 if (UnknownInsts
.empty()) { // Merge call sites...
73 if (ASHadUnknownInsts
) {
74 std::swap(UnknownInsts
, AS
.UnknownInsts
);
77 } else if (ASHadUnknownInsts
) {
78 llvm::append_range(UnknownInsts
, AS
.UnknownInsts
);
79 AS
.UnknownInsts
.clear();
82 AS
.Forward
= this; // Forward across AS now...
83 addRef(); // AS is now pointing to us...
85 if (ASHadUnknownInsts
)
89 void AliasSetTracker::removeAliasSet(AliasSet
*AS
) {
90 if (AliasSet
*Fwd
= AS
->Forward
) {
92 AS
->Forward
= nullptr;
93 } else // Update TotalAliasSetSize only if not forwarding.
94 TotalAliasSetSize
-= AS
->size();
97 // If we've removed the saturated alias set, set saturated marker back to
98 // nullptr and ensure this tracker is empty.
99 if (AS
== AliasAnyAS
) {
100 AliasAnyAS
= nullptr;
101 assert(AliasSets
.empty() && "Tracker not empty");
105 void AliasSet::removeFromTracker(AliasSetTracker
&AST
) {
106 assert(RefCount
== 0 && "Cannot remove non-dead alias set from tracker!");
107 AST
.removeAliasSet(this);
110 void AliasSet::addMemoryLocation(AliasSetTracker
&AST
,
111 const MemoryLocation
&MemLoc
,
112 bool KnownMustAlias
) {
113 if (isMustAlias() && !KnownMustAlias
) {
114 // If we cannot find a must-alias with any of the existing MemoryLocs, we
115 // must downgrade to may-alias.
116 if (!any_of(MemoryLocs
, [&](const MemoryLocation
&ASMemLoc
) {
117 return AST
.getAliasAnalysis().isMustAlias(MemLoc
, ASMemLoc
);
122 // Add it to the end of the list...
123 MemoryLocs
.push_back(MemLoc
);
125 AST
.TotalAliasSetSize
++;
128 void AliasSet::addUnknownInst(Instruction
*I
, BatchAAResults
&AA
) {
129 if (UnknownInsts
.empty())
131 UnknownInsts
.emplace_back(I
);
133 // Guards are marked as modifying memory for control flow modelling purposes,
134 // but don't actually modify any specific memory location.
135 using namespace PatternMatch
;
136 bool MayWriteMemory
= I
->mayWriteToMemory() && !isGuard(I
) &&
137 !(I
->use_empty() && match(I
, m_Intrinsic
<Intrinsic::invariant_start
>()));
138 if (!MayWriteMemory
) {
144 // FIXME: This should use mod/ref information to make this not suck so bad
146 Access
= ModRefAccess
;
149 /// aliasesMemoryLocation - If the specified memory location "may" (or must)
150 /// alias one of the members in the set return the appropriate AliasResult.
151 /// Otherwise return NoAlias.
153 AliasResult
AliasSet::aliasesMemoryLocation(const MemoryLocation
&MemLoc
,
154 BatchAAResults
&AA
) const {
156 return AliasResult::MayAlias
;
158 // Check all of the memory locations in the set...
159 for (const auto &ASMemLoc
: MemoryLocs
) {
160 AliasResult AR
= AA
.alias(MemLoc
, ASMemLoc
);
161 if (AR
!= AliasResult::NoAlias
)
165 // Check the unknown instructions...
166 for (Instruction
*Inst
: UnknownInsts
)
167 if (isModOrRefSet(AA
.getModRefInfo(Inst
, MemLoc
)))
168 return AliasResult::MayAlias
;
170 return AliasResult::NoAlias
;
173 ModRefInfo
AliasSet::aliasesUnknownInst(const Instruction
*Inst
,
174 BatchAAResults
&AA
) const {
177 return ModRefInfo::ModRef
;
179 if (!Inst
->mayReadOrWriteMemory())
180 return ModRefInfo::NoModRef
;
182 for (Instruction
*UnknownInst
: UnknownInsts
) {
183 const auto *C1
= dyn_cast
<CallBase
>(UnknownInst
);
184 const auto *C2
= dyn_cast
<CallBase
>(Inst
);
185 if (!C1
|| !C2
|| isModOrRefSet(AA
.getModRefInfo(C1
, C2
)) ||
186 isModOrRefSet(AA
.getModRefInfo(C2
, C1
))) {
187 // TODO: Could be more precise, but not really useful right now.
188 return ModRefInfo::ModRef
;
192 ModRefInfo MR
= ModRefInfo::NoModRef
;
193 for (const auto &ASMemLoc
: MemoryLocs
) {
194 MR
|= AA
.getModRefInfo(Inst
, ASMemLoc
);
195 if (isModAndRefSet(MR
))
202 AliasSet::PointerVector
AliasSet::getPointers() const {
203 SmallSetVector
<const Value
*, 8> Pointers
;
204 for (const MemoryLocation
&MemLoc
: MemoryLocs
)
205 Pointers
.insert(MemLoc
.Ptr
);
206 return Pointers
.takeVector();
209 void AliasSetTracker::clear() {
214 /// mergeAliasSetsForMemoryLocation - Given a memory location, merge all alias
215 /// sets that may alias it. Return the unified set, or nullptr if no aliasing
216 /// set was found. A known existing alias set for the pointer value of the
217 /// memory location can be passed in (or nullptr if not available). MustAliasAll
218 /// is updated to true/false if the memory location is found to MustAlias all
219 /// the sets it merged.
220 AliasSet
*AliasSetTracker::mergeAliasSetsForMemoryLocation(
221 const MemoryLocation
&MemLoc
, AliasSet
*PtrAS
, bool &MustAliasAll
) {
222 AliasSet
*FoundSet
= nullptr;
224 for (AliasSet
&AS
: llvm::make_early_inc_range(*this)) {
228 // An alias set that already contains a memory location with the same
229 // pointer value is directly assumed to MustAlias; we bypass the AA query in
231 // Note: it is not guaranteed that AA would always provide the same result;
232 // a known exception are undef pointer values, where alias(undef, undef) is
233 // NoAlias, while we treat it as MustAlias.
235 AliasResult AR
= AS
.aliasesMemoryLocation(MemLoc
, AA
);
236 if (AR
== AliasResult::NoAlias
)
239 if (AR
!= AliasResult::MustAlias
)
240 MustAliasAll
= false;
244 // If this is the first alias set ptr can go into, remember it.
247 // Otherwise, we must merge the sets.
248 FoundSet
->mergeSetIn(AS
, *this, AA
);
255 AliasSet
*AliasSetTracker::findAliasSetForUnknownInst(Instruction
*Inst
) {
256 AliasSet
*FoundSet
= nullptr;
257 for (AliasSet
&AS
: llvm::make_early_inc_range(*this)) {
258 if (AS
.Forward
|| !isModOrRefSet(AS
.aliasesUnknownInst(Inst
, AA
)))
261 // If this is the first alias set ptr can go into, remember it.
264 // Otherwise, we must merge the sets.
265 FoundSet
->mergeSetIn(AS
, *this, AA
);
271 AliasSet
&AliasSetTracker::getAliasSetFor(const MemoryLocation
&MemLoc
) {
272 // The alias sets are indexed with a map from the memory locations' pointer
273 // values. If the memory location is already registered, we can find it in the
274 // alias set associated with its pointer.
275 AliasSet
*&MapEntry
= PointerMap
[MemLoc
.Ptr
];
277 collapseForwardingIn(MapEntry
);
278 if (is_contained(MapEntry
->MemoryLocs
, MemLoc
))
283 bool MustAliasAll
= false;
285 // At this point, the AST is saturated, so we only have one active alias
286 // set. That means we already know which alias set we want to return, and
287 // just need to add the memory location to that set to keep the data
288 // structure consistent.
289 // This, of course, means that we will never need a merge here.
291 } else if (AliasSet
*AliasAS
= mergeAliasSetsForMemoryLocation(
292 MemLoc
, MapEntry
, MustAliasAll
)) {
293 // Add it to the alias set it aliases.
296 // Otherwise create a new alias set to hold the new memory location.
297 AliasSets
.push_back(AS
= new AliasSet());
301 // Register memory location in selected alias set.
302 AS
->addMemoryLocation(*this, MemLoc
, MustAliasAll
);
303 // Register selected alias set in pointer map (or ensure it is consistent with
304 // earlier map entry after taking into account new merging).
306 collapseForwardingIn(MapEntry
);
307 assert(MapEntry
== AS
&& "Memory locations with same pointer value cannot "
308 "be in different alias sets");
316 void AliasSetTracker::add(const MemoryLocation
&Loc
) {
317 addMemoryLocation(Loc
, AliasSet::NoAccess
);
320 void AliasSetTracker::add(LoadInst
*LI
) {
321 if (isStrongerThanMonotonic(LI
->getOrdering()))
322 return addUnknown(LI
);
323 addMemoryLocation(MemoryLocation::get(LI
), AliasSet::RefAccess
);
326 void AliasSetTracker::add(StoreInst
*SI
) {
327 if (isStrongerThanMonotonic(SI
->getOrdering()))
328 return addUnknown(SI
);
329 addMemoryLocation(MemoryLocation::get(SI
), AliasSet::ModAccess
);
332 void AliasSetTracker::add(VAArgInst
*VAAI
) {
333 addMemoryLocation(MemoryLocation::get(VAAI
), AliasSet::ModRefAccess
);
336 void AliasSetTracker::add(AnyMemSetInst
*MSI
) {
337 addMemoryLocation(MemoryLocation::getForDest(MSI
), AliasSet::ModAccess
);
340 void AliasSetTracker::add(AnyMemTransferInst
*MTI
) {
341 addMemoryLocation(MemoryLocation::getForDest(MTI
), AliasSet::ModAccess
);
342 addMemoryLocation(MemoryLocation::getForSource(MTI
), AliasSet::RefAccess
);
345 void AliasSetTracker::addUnknown(Instruction
*Inst
) {
346 if (isa
<DbgInfoIntrinsic
>(Inst
))
347 return; // Ignore DbgInfo Intrinsics.
349 if (auto *II
= dyn_cast
<IntrinsicInst
>(Inst
)) {
350 // These intrinsics will show up as affecting memory, but they are just
352 switch (II
->getIntrinsicID()) {
355 // FIXME: Add lifetime/invariant intrinsics (See: PR30807).
356 case Intrinsic::allow_runtime_check
:
357 case Intrinsic::allow_ubsan_check
:
358 case Intrinsic::assume
:
359 case Intrinsic::experimental_noalias_scope_decl
:
360 case Intrinsic::sideeffect
:
361 case Intrinsic::pseudoprobe
:
365 if (!Inst
->mayReadOrWriteMemory())
366 return; // doesn't alias anything
368 if (AliasSet
*AS
= findAliasSetForUnknownInst(Inst
)) {
369 AS
->addUnknownInst(Inst
, AA
);
372 AliasSets
.push_back(new AliasSet());
373 AliasSets
.back().addUnknownInst(Inst
, AA
);
376 void AliasSetTracker::add(Instruction
*I
) {
377 // Dispatch to one of the other add methods.
378 if (LoadInst
*LI
= dyn_cast
<LoadInst
>(I
))
380 if (StoreInst
*SI
= dyn_cast
<StoreInst
>(I
))
382 if (VAArgInst
*VAAI
= dyn_cast
<VAArgInst
>(I
))
384 if (AnyMemSetInst
*MSI
= dyn_cast
<AnyMemSetInst
>(I
))
386 if (AnyMemTransferInst
*MTI
= dyn_cast
<AnyMemTransferInst
>(I
))
389 // Handle all calls with known mod/ref sets genericall
390 if (auto *Call
= dyn_cast
<CallBase
>(I
))
391 if (Call
->onlyAccessesArgMemory()) {
392 auto getAccessFromModRef
= [](ModRefInfo MRI
) {
393 if (isRefSet(MRI
) && isModSet(MRI
))
394 return AliasSet::ModRefAccess
;
395 else if (isModSet(MRI
))
396 return AliasSet::ModAccess
;
397 else if (isRefSet(MRI
))
398 return AliasSet::RefAccess
;
400 return AliasSet::NoAccess
;
403 ModRefInfo CallMask
= AA
.getMemoryEffects(Call
).getModRef();
405 // Some intrinsics are marked as modifying memory for control flow
406 // modelling purposes, but don't actually modify any specific memory
408 using namespace PatternMatch
;
409 if (Call
->use_empty() &&
410 match(Call
, m_Intrinsic
<Intrinsic::invariant_start
>()))
411 CallMask
&= ModRefInfo::Ref
;
413 for (auto IdxArgPair
: enumerate(Call
->args())) {
414 int ArgIdx
= IdxArgPair
.index();
415 const Value
*Arg
= IdxArgPair
.value();
416 if (!Arg
->getType()->isPointerTy())
418 MemoryLocation ArgLoc
=
419 MemoryLocation::getForArgument(Call
, ArgIdx
, nullptr);
420 ModRefInfo ArgMask
= AA
.getArgModRefInfo(Call
, ArgIdx
);
422 if (!isNoModRef(ArgMask
))
423 addMemoryLocation(ArgLoc
, getAccessFromModRef(ArgMask
));
428 return addUnknown(I
);
431 void AliasSetTracker::add(BasicBlock
&BB
) {
436 void AliasSetTracker::add(const AliasSetTracker
&AST
) {
437 assert(&AA
== &AST
.AA
&&
438 "Merging AliasSetTracker objects with different Alias Analyses!");
440 // Loop over all of the alias sets in AST, adding the members contained
441 // therein into the current alias sets. This can cause alias sets to be
442 // merged together in the current AST.
443 for (const AliasSet
&AS
: AST
) {
445 continue; // Ignore forwarding alias sets
447 // If there are any call sites in the alias set, add them to this AST.
448 for (Instruction
*Inst
: AS
.UnknownInsts
)
451 // Loop over all of the memory locations in this alias set.
452 for (const MemoryLocation
&ASMemLoc
: AS
.MemoryLocs
)
453 addMemoryLocation(ASMemLoc
, (AliasSet::AccessLattice
)AS
.Access
);
457 AliasSet
&AliasSetTracker::mergeAllAliasSets() {
458 assert(!AliasAnyAS
&& (TotalAliasSetSize
> SaturationThreshold
) &&
459 "Full merge should happen once, when the saturation threshold is "
462 // Collect all alias sets, so that we can drop references with impunity
463 // without worrying about iterator invalidation.
464 std::vector
<AliasSet
*> ASVector
;
465 ASVector
.reserve(SaturationThreshold
);
466 for (AliasSet
&AS
: *this)
467 ASVector
.push_back(&AS
);
469 // Copy all instructions and memory locations into a new set, and forward all
471 AliasSets
.push_back(new AliasSet());
472 AliasAnyAS
= &AliasSets
.back();
473 AliasAnyAS
->Alias
= AliasSet::SetMayAlias
;
474 AliasAnyAS
->Access
= AliasSet::ModRefAccess
;
475 AliasAnyAS
->AliasAny
= true;
477 for (auto *Cur
: ASVector
) {
478 // If Cur was already forwarding, just forward to the new AS instead.
479 AliasSet
*FwdTo
= Cur
->Forward
;
481 Cur
->Forward
= AliasAnyAS
;
482 AliasAnyAS
->addRef();
483 FwdTo
->dropRef(*this);
487 // Otherwise, perform the actual merge.
488 AliasAnyAS
->mergeSetIn(*Cur
, *this, AA
);
494 AliasSet
&AliasSetTracker::addMemoryLocation(MemoryLocation Loc
,
495 AliasSet::AccessLattice E
) {
496 AliasSet
&AS
= getAliasSetFor(Loc
);
499 if (!AliasAnyAS
&& (TotalAliasSetSize
> SaturationThreshold
)) {
500 // The AST is now saturated. From here on, we conservatively consider all
501 // elements to alias each-other.
502 return mergeAllAliasSets();
508 //===----------------------------------------------------------------------===//
509 // AliasSet/AliasSetTracker Printing Support
510 //===----------------------------------------------------------------------===//
512 void AliasSet::print(raw_ostream
&OS
) const {
513 OS
<< " AliasSet[" << (const void*)this << ", " << RefCount
<< "] ";
514 OS
<< (Alias
== SetMustAlias
? "must" : "may") << " alias, ";
516 case NoAccess
: OS
<< "No access "; break;
517 case RefAccess
: OS
<< "Ref "; break;
518 case ModAccess
: OS
<< "Mod "; break;
519 case ModRefAccess
: OS
<< "Mod/Ref "; break;
520 default: llvm_unreachable("Bad value for Access!");
523 OS
<< " forwarding to " << (void*)Forward
;
525 if (!MemoryLocs
.empty()) {
527 OS
<< "Memory locations: ";
528 for (const MemoryLocation
&MemLoc
: MemoryLocs
) {
530 MemLoc
.Ptr
->printAsOperand(OS
<< "(");
531 if (MemLoc
.Size
== LocationSize::afterPointer())
532 OS
<< ", unknown after)";
533 else if (MemLoc
.Size
== LocationSize::beforeOrAfterPointer())
534 OS
<< ", unknown before-or-after)";
536 OS
<< ", " << MemLoc
.Size
<< ")";
539 if (!UnknownInsts
.empty()) {
541 OS
<< "\n " << UnknownInsts
.size() << " Unknown instructions: ";
542 for (Instruction
*I
: UnknownInsts
) {
545 I
->printAsOperand(OS
);
553 void AliasSetTracker::print(raw_ostream
&OS
) const {
554 OS
<< "Alias Set Tracker: " << AliasSets
.size();
556 OS
<< " (Saturated)";
557 OS
<< " alias sets for " << PointerMap
.size() << " pointer values.\n";
558 for (const AliasSet
&AS
: *this)
563 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
564 LLVM_DUMP_METHOD
void AliasSet::dump() const { print(dbgs()); }
565 LLVM_DUMP_METHOD
void AliasSetTracker::dump() const { print(dbgs()); }
568 //===----------------------------------------------------------------------===//
569 // AliasSetPrinter Pass
570 //===----------------------------------------------------------------------===//
572 AliasSetsPrinterPass::AliasSetsPrinterPass(raw_ostream
&OS
) : OS(OS
) {}
574 PreservedAnalyses
AliasSetsPrinterPass::run(Function
&F
,
575 FunctionAnalysisManager
&AM
) {
576 auto &AA
= AM
.getResult
<AAManager
>(F
);
577 BatchAAResults
BatchAA(AA
);
578 AliasSetTracker
Tracker(BatchAA
);
579 OS
<< "Alias sets for function '" << F
.getName() << "':\n";
580 for (Instruction
&I
: instructions(F
))
583 return PreservedAnalyses::all();