xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/AliasSetTracker.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the AliasSetTracker and AliasSet classes.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Analysis/AliasSetTracker.h"
147a6dacacSDimitry Andric #include "llvm/ADT/SetVector.h"
1506c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
16fe6060f1SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
170b57cec5SDimitry Andric #include "llvm/Analysis/GuardUtils.h"
180b57cec5SDimitry Andric #include "llvm/Analysis/MemoryLocation.h"
190b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
200b57cec5SDimitry Andric #include "llvm/IR/Function.h"
210b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h"
220b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
230b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
24e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h"
250b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h"
260b57cec5SDimitry Andric #include "llvm/IR/Value.h"
27480093f4SDimitry Andric #include "llvm/InitializePasses.h"
280b57cec5SDimitry Andric #include "llvm/Pass.h"
290b57cec5SDimitry Andric #include "llvm/Support/AtomicOrdering.h"
300b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
310b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
320b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
340b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
387a6dacacSDimitry Andric static cl::opt<unsigned> SaturationThreshold(
397a6dacacSDimitry Andric     "alias-set-saturation-threshold", cl::Hidden, cl::init(250),
407a6dacacSDimitry Andric     cl::desc("The maximum total number of memory locations alias "
410b57cec5SDimitry Andric              "sets may contain before degradation"));
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric /// mergeSetIn - Merge the specified alias set into this alias set.
44bdd1243dSDimitry Andric void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST,
45bdd1243dSDimitry Andric                           BatchAAResults &BatchAA) {
460b57cec5SDimitry Andric   assert(!AS.Forward && "Alias set is already forwarding!");
470b57cec5SDimitry Andric   assert(!Forward && "This set is a forwarding set!!");
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric   // Update the alias and access types of this set...
500b57cec5SDimitry Andric   Access |= AS.Access;
510b57cec5SDimitry Andric   Alias  |= AS.Alias;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   if (Alias == SetMustAlias) {
547a6dacacSDimitry Andric     // Check that these two merged sets really are must aliases. If we cannot
557a6dacacSDimitry Andric     // find a must-alias pair between them, this set becomes a may alias.
567a6dacacSDimitry Andric     if (!any_of(MemoryLocs, [&](const MemoryLocation &MemLoc) {
577a6dacacSDimitry Andric           return any_of(AS.MemoryLocs, [&](const MemoryLocation &ASMemLoc) {
587a6dacacSDimitry Andric             return BatchAA.isMustAlias(MemLoc, ASMemLoc);
597a6dacacSDimitry Andric           });
607a6dacacSDimitry Andric         }))
610b57cec5SDimitry Andric       Alias = SetMayAlias;
620b57cec5SDimitry Andric   }
630b57cec5SDimitry Andric 
647a6dacacSDimitry Andric   // Merge the list of constituent memory locations...
657a6dacacSDimitry Andric   if (MemoryLocs.empty()) {
667a6dacacSDimitry Andric     std::swap(MemoryLocs, AS.MemoryLocs);
677a6dacacSDimitry Andric   } else {
687a6dacacSDimitry Andric     append_range(MemoryLocs, AS.MemoryLocs);
697a6dacacSDimitry Andric     AS.MemoryLocs.clear();
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   bool ASHadUnknownInsts = !AS.UnknownInsts.empty();
730b57cec5SDimitry Andric   if (UnknownInsts.empty()) {            // Merge call sites...
740b57cec5SDimitry Andric     if (ASHadUnknownInsts) {
750b57cec5SDimitry Andric       std::swap(UnknownInsts, AS.UnknownInsts);
760b57cec5SDimitry Andric       addRef();
770b57cec5SDimitry Andric     }
780b57cec5SDimitry Andric   } else if (ASHadUnknownInsts) {
79e8d8bef9SDimitry Andric     llvm::append_range(UnknownInsts, AS.UnknownInsts);
800b57cec5SDimitry Andric     AS.UnknownInsts.clear();
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   AS.Forward = this; // Forward across AS now...
840b57cec5SDimitry Andric   addRef();          // AS is now pointing to us...
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   if (ASHadUnknownInsts)
870b57cec5SDimitry Andric     AS.dropRef(AST);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric void AliasSetTracker::removeAliasSet(AliasSet *AS) {
910b57cec5SDimitry Andric   if (AliasSet *Fwd = AS->Forward) {
920b57cec5SDimitry Andric     Fwd->dropRef(*this);
930b57cec5SDimitry Andric     AS->Forward = nullptr;
947a6dacacSDimitry Andric   } else // Update TotalAliasSetSize only if not forwarding.
957a6dacacSDimitry Andric     TotalAliasSetSize -= AS->size();
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   AliasSets.erase(AS);
988bcb0991SDimitry Andric   // If we've removed the saturated alias set, set saturated marker back to
998bcb0991SDimitry Andric   // nullptr and ensure this tracker is empty.
1008bcb0991SDimitry Andric   if (AS == AliasAnyAS) {
1018bcb0991SDimitry Andric     AliasAnyAS = nullptr;
1028bcb0991SDimitry Andric     assert(AliasSets.empty() && "Tracker not empty");
1038bcb0991SDimitry Andric   }
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric void AliasSet::removeFromTracker(AliasSetTracker &AST) {
1070b57cec5SDimitry Andric   assert(RefCount == 0 && "Cannot remove non-dead alias set from tracker!");
1080b57cec5SDimitry Andric   AST.removeAliasSet(this);
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1117a6dacacSDimitry Andric void AliasSet::addMemoryLocation(AliasSetTracker &AST,
1127a6dacacSDimitry Andric                                  const MemoryLocation &MemLoc,
1137a6dacacSDimitry Andric                                  bool KnownMustAlias) {
1147a6dacacSDimitry Andric   if (isMustAlias() && !KnownMustAlias) {
1157a6dacacSDimitry Andric     // If we cannot find a must-alias with any of the existing MemoryLocs, we
1167a6dacacSDimitry Andric     // must downgrade to may-alias.
1177a6dacacSDimitry Andric     if (!any_of(MemoryLocs, [&](const MemoryLocation &ASMemLoc) {
1187a6dacacSDimitry Andric           return AST.getAliasAnalysis().isMustAlias(MemLoc, ASMemLoc);
1197a6dacacSDimitry Andric         }))
1200b57cec5SDimitry Andric       Alias = SetMayAlias;
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   // Add it to the end of the list...
1247a6dacacSDimitry Andric   MemoryLocs.push_back(MemLoc);
1250b57cec5SDimitry Andric 
1267a6dacacSDimitry Andric   AST.TotalAliasSetSize++;
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
129bdd1243dSDimitry Andric void AliasSet::addUnknownInst(Instruction *I, BatchAAResults &AA) {
1300b57cec5SDimitry Andric   if (UnknownInsts.empty())
1310b57cec5SDimitry Andric     addRef();
1320b57cec5SDimitry Andric   UnknownInsts.emplace_back(I);
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   // Guards are marked as modifying memory for control flow modelling purposes,
1350b57cec5SDimitry Andric   // but don't actually modify any specific memory location.
1360b57cec5SDimitry Andric   using namespace PatternMatch;
1370b57cec5SDimitry Andric   bool MayWriteMemory = I->mayWriteToMemory() && !isGuard(I) &&
1380b57cec5SDimitry Andric     !(I->use_empty() && match(I, m_Intrinsic<Intrinsic::invariant_start>()));
1390b57cec5SDimitry Andric   if (!MayWriteMemory) {
1400b57cec5SDimitry Andric     Alias = SetMayAlias;
1410b57cec5SDimitry Andric     Access |= RefAccess;
1420b57cec5SDimitry Andric     return;
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   // FIXME: This should use mod/ref information to make this not suck so bad
1460b57cec5SDimitry Andric   Alias = SetMayAlias;
1470b57cec5SDimitry Andric   Access = ModRefAccess;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
1507a6dacacSDimitry Andric /// aliasesMemoryLocation - If the specified memory location "may" (or must)
1517a6dacacSDimitry Andric /// alias one of the members in the set return the appropriate AliasResult.
1527a6dacacSDimitry Andric /// Otherwise return NoAlias.
1530b57cec5SDimitry Andric ///
1547a6dacacSDimitry Andric AliasResult AliasSet::aliasesMemoryLocation(const MemoryLocation &MemLoc,
155bdd1243dSDimitry Andric                                             BatchAAResults &AA) const {
1560b57cec5SDimitry Andric   if (AliasAny)
157fe6060f1SDimitry Andric     return AliasResult::MayAlias;
1580b57cec5SDimitry Andric 
1597a6dacacSDimitry Andric   // Check all of the memory locations in the set...
1607a6dacacSDimitry Andric   for (const auto &ASMemLoc : MemoryLocs) {
1617a6dacacSDimitry Andric     AliasResult AR = AA.alias(MemLoc, ASMemLoc);
162fe6060f1SDimitry Andric     if (AR != AliasResult::NoAlias)
1630b57cec5SDimitry Andric       return AR;
164fe6060f1SDimitry Andric   }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   // Check the unknown instructions...
167bdd1243dSDimitry Andric   for (Instruction *Inst : UnknownInsts)
1687a6dacacSDimitry Andric     if (isModOrRefSet(AA.getModRefInfo(Inst, MemLoc)))
169fe6060f1SDimitry Andric       return AliasResult::MayAlias;
1700b57cec5SDimitry Andric 
171fe6060f1SDimitry Andric   return AliasResult::NoAlias;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
174bdd1243dSDimitry Andric ModRefInfo AliasSet::aliasesUnknownInst(const Instruction *Inst,
175bdd1243dSDimitry Andric                                         BatchAAResults &AA) const {
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   if (AliasAny)
178bdd1243dSDimitry Andric     return ModRefInfo::ModRef;
1790b57cec5SDimitry Andric 
18081ad6265SDimitry Andric   if (!Inst->mayReadOrWriteMemory())
181bdd1243dSDimitry Andric     return ModRefInfo::NoModRef;
1820b57cec5SDimitry Andric 
183bdd1243dSDimitry Andric   for (Instruction *UnknownInst : UnknownInsts) {
1840b57cec5SDimitry Andric     const auto *C1 = dyn_cast<CallBase>(UnknownInst);
1850b57cec5SDimitry Andric     const auto *C2 = dyn_cast<CallBase>(Inst);
1860b57cec5SDimitry Andric     if (!C1 || !C2 || isModOrRefSet(AA.getModRefInfo(C1, C2)) ||
187bdd1243dSDimitry Andric         isModOrRefSet(AA.getModRefInfo(C2, C1))) {
188bdd1243dSDimitry Andric       // TODO: Could be more precise, but not really useful right now.
189bdd1243dSDimitry Andric       return ModRefInfo::ModRef;
1900b57cec5SDimitry Andric     }
1910b57cec5SDimitry Andric   }
1920b57cec5SDimitry Andric 
193bdd1243dSDimitry Andric   ModRefInfo MR = ModRefInfo::NoModRef;
1947a6dacacSDimitry Andric   for (const auto &ASMemLoc : MemoryLocs) {
1957a6dacacSDimitry Andric     MR |= AA.getModRefInfo(Inst, ASMemLoc);
196bdd1243dSDimitry Andric     if (isModAndRefSet(MR))
197bdd1243dSDimitry Andric       return MR;
198bdd1243dSDimitry Andric   }
1990b57cec5SDimitry Andric 
200bdd1243dSDimitry Andric   return MR;
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric 
2037a6dacacSDimitry Andric AliasSet::PointerVector AliasSet::getPointers() const {
2047a6dacacSDimitry Andric   SmallSetVector<const Value *, 8> Pointers;
2057a6dacacSDimitry Andric   for (const MemoryLocation &MemLoc : MemoryLocs)
2067a6dacacSDimitry Andric     Pointers.insert(MemLoc.Ptr);
2077a6dacacSDimitry Andric   return Pointers.takeVector();
2087a6dacacSDimitry Andric }
2097a6dacacSDimitry Andric 
2100b57cec5SDimitry Andric void AliasSetTracker::clear() {
2110b57cec5SDimitry Andric   PointerMap.clear();
2120b57cec5SDimitry Andric   AliasSets.clear();
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
2157a6dacacSDimitry Andric /// mergeAliasSetsForMemoryLocation - Given a memory location, merge all alias
2167a6dacacSDimitry Andric /// sets that may alias it. Return the unified set, or nullptr if no aliasing
2177a6dacacSDimitry Andric /// set was found. A known existing alias set for the pointer value of the
2187a6dacacSDimitry Andric /// memory location can be passed in (or nullptr if not available). MustAliasAll
2197a6dacacSDimitry Andric /// is updated to true/false if the memory location is found to MustAlias all
2207a6dacacSDimitry Andric /// the sets it merged.
2217a6dacacSDimitry Andric AliasSet *AliasSetTracker::mergeAliasSetsForMemoryLocation(
2227a6dacacSDimitry Andric     const MemoryLocation &MemLoc, AliasSet *PtrAS, bool &MustAliasAll) {
2230b57cec5SDimitry Andric   AliasSet *FoundSet = nullptr;
224fe6060f1SDimitry Andric   MustAliasAll = true;
225fe6060f1SDimitry Andric   for (AliasSet &AS : llvm::make_early_inc_range(*this)) {
226fe6060f1SDimitry Andric     if (AS.Forward)
2270b57cec5SDimitry Andric       continue;
2280b57cec5SDimitry Andric 
2297a6dacacSDimitry Andric     // An alias set that already contains a memory location with the same
2307a6dacacSDimitry Andric     // pointer value is directly assumed to MustAlias; we bypass the AA query in
2317a6dacacSDimitry Andric     // this case.
2327a6dacacSDimitry Andric     // Note: it is not guaranteed that AA would always provide the same result;
2337a6dacacSDimitry Andric     // a known exception are undef pointer values, where alias(undef, undef) is
2347a6dacacSDimitry Andric     // NoAlias, while we treat it as MustAlias.
2357a6dacacSDimitry Andric     if (&AS != PtrAS) {
2367a6dacacSDimitry Andric       AliasResult AR = AS.aliasesMemoryLocation(MemLoc, AA);
237fe6060f1SDimitry Andric       if (AR == AliasResult::NoAlias)
2380b57cec5SDimitry Andric         continue;
2390b57cec5SDimitry Andric 
240fe6060f1SDimitry Andric       if (AR != AliasResult::MustAlias)
241fe6060f1SDimitry Andric         MustAliasAll = false;
2427a6dacacSDimitry Andric     }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric     if (!FoundSet) {
2450b57cec5SDimitry Andric       // If this is the first alias set ptr can go into, remember it.
246fe6060f1SDimitry Andric       FoundSet = &AS;
2470b57cec5SDimitry Andric     } else {
2480b57cec5SDimitry Andric       // Otherwise, we must merge the sets.
249bdd1243dSDimitry Andric       FoundSet->mergeSetIn(AS, *this, AA);
2500b57cec5SDimitry Andric     }
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   return FoundSet;
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric AliasSet *AliasSetTracker::findAliasSetForUnknownInst(Instruction *Inst) {
2570b57cec5SDimitry Andric   AliasSet *FoundSet = nullptr;
258fe6060f1SDimitry Andric   for (AliasSet &AS : llvm::make_early_inc_range(*this)) {
259bdd1243dSDimitry Andric     if (AS.Forward || !isModOrRefSet(AS.aliasesUnknownInst(Inst, AA)))
2600b57cec5SDimitry Andric       continue;
2610b57cec5SDimitry Andric     if (!FoundSet) {
2620b57cec5SDimitry Andric       // If this is the first alias set ptr can go into, remember it.
263fe6060f1SDimitry Andric       FoundSet = &AS;
2640b57cec5SDimitry Andric     } else {
2650b57cec5SDimitry Andric       // Otherwise, we must merge the sets.
266bdd1243dSDimitry Andric       FoundSet->mergeSetIn(AS, *this, AA);
2670b57cec5SDimitry Andric     }
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric   return FoundSet;
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric AliasSet &AliasSetTracker::getAliasSetFor(const MemoryLocation &MemLoc) {
2737a6dacacSDimitry Andric   // The alias sets are indexed with a map from the memory locations' pointer
2747a6dacacSDimitry Andric   // values. If the memory location is already registered, we can find it in the
2757a6dacacSDimitry Andric   // alias set associated with its pointer.
2767a6dacacSDimitry Andric   AliasSet *&MapEntry = PointerMap[MemLoc.Ptr];
2777a6dacacSDimitry Andric   if (MapEntry) {
2787a6dacacSDimitry Andric     collapseForwardingIn(MapEntry);
2797a6dacacSDimitry Andric     if (is_contained(MapEntry->MemoryLocs, MemLoc))
2807a6dacacSDimitry Andric       return *MapEntry;
2817a6dacacSDimitry Andric   }
2820b57cec5SDimitry Andric 
2837a6dacacSDimitry Andric   AliasSet *AS;
2847a6dacacSDimitry Andric   bool MustAliasAll = false;
2850b57cec5SDimitry Andric   if (AliasAnyAS) {
2860b57cec5SDimitry Andric     // At this point, the AST is saturated, so we only have one active alias
2870b57cec5SDimitry Andric     // set. That means we already know which alias set we want to return, and
2887a6dacacSDimitry Andric     // just need to add the memory location to that set to keep the data
2897a6dacacSDimitry Andric     // structure consistent.
2900b57cec5SDimitry Andric     // This, of course, means that we will never need a merge here.
2917a6dacacSDimitry Andric     AS = AliasAnyAS;
2927a6dacacSDimitry Andric   } else if (AliasSet *AliasAS = mergeAliasSetsForMemoryLocation(
2937a6dacacSDimitry Andric                  MemLoc, MapEntry, MustAliasAll)) {
2940b57cec5SDimitry Andric     // Add it to the alias set it aliases.
2957a6dacacSDimitry Andric     AS = AliasAS;
2967a6dacacSDimitry Andric   } else {
2977a6dacacSDimitry Andric     // Otherwise create a new alias set to hold the new memory location.
2987a6dacacSDimitry Andric     AliasSets.push_back(AS = new AliasSet());
2997a6dacacSDimitry Andric     MustAliasAll = true;
3007a6dacacSDimitry Andric   }
3017a6dacacSDimitry Andric 
3027a6dacacSDimitry Andric   // Register memory location in selected alias set.
3037a6dacacSDimitry Andric   AS->addMemoryLocation(*this, MemLoc, MustAliasAll);
3047a6dacacSDimitry Andric   // Register selected alias set in pointer map (or ensure it is consistent with
3057a6dacacSDimitry Andric   // earlier map entry after taking into account new merging).
3067a6dacacSDimitry Andric   if (MapEntry) {
3077a6dacacSDimitry Andric     collapseForwardingIn(MapEntry);
3087a6dacacSDimitry Andric     assert(MapEntry == AS && "Memory locations with same pointer value cannot "
3097a6dacacSDimitry Andric                              "be in different alias sets");
3107a6dacacSDimitry Andric   } else {
3117a6dacacSDimitry Andric     AS->addRef();
3127a6dacacSDimitry Andric     MapEntry = AS;
3137a6dacacSDimitry Andric   }
3140b57cec5SDimitry Andric   return *AS;
3150b57cec5SDimitry Andric }
3160b57cec5SDimitry Andric 
3175f757f3fSDimitry Andric void AliasSetTracker::add(const MemoryLocation &Loc) {
3187a6dacacSDimitry Andric   addMemoryLocation(Loc, AliasSet::NoAccess);
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric void AliasSetTracker::add(LoadInst *LI) {
3220b57cec5SDimitry Andric   if (isStrongerThanMonotonic(LI->getOrdering()))
3230b57cec5SDimitry Andric     return addUnknown(LI);
3247a6dacacSDimitry Andric   addMemoryLocation(MemoryLocation::get(LI), AliasSet::RefAccess);
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric void AliasSetTracker::add(StoreInst *SI) {
3280b57cec5SDimitry Andric   if (isStrongerThanMonotonic(SI->getOrdering()))
3290b57cec5SDimitry Andric     return addUnknown(SI);
3307a6dacacSDimitry Andric   addMemoryLocation(MemoryLocation::get(SI), AliasSet::ModAccess);
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric void AliasSetTracker::add(VAArgInst *VAAI) {
3347a6dacacSDimitry Andric   addMemoryLocation(MemoryLocation::get(VAAI), AliasSet::ModRefAccess);
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric void AliasSetTracker::add(AnyMemSetInst *MSI) {
3387a6dacacSDimitry Andric   addMemoryLocation(MemoryLocation::getForDest(MSI), AliasSet::ModAccess);
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric void AliasSetTracker::add(AnyMemTransferInst *MTI) {
3427a6dacacSDimitry Andric   addMemoryLocation(MemoryLocation::getForDest(MTI), AliasSet::ModAccess);
3437a6dacacSDimitry Andric   addMemoryLocation(MemoryLocation::getForSource(MTI), AliasSet::RefAccess);
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric void AliasSetTracker::addUnknown(Instruction *Inst) {
3470b57cec5SDimitry Andric   if (isa<DbgInfoIntrinsic>(Inst))
3480b57cec5SDimitry Andric     return; // Ignore DbgInfo Intrinsics.
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   if (auto *II = dyn_cast<IntrinsicInst>(Inst)) {
3510b57cec5SDimitry Andric     // These intrinsics will show up as affecting memory, but they are just
3520b57cec5SDimitry Andric     // markers.
3530b57cec5SDimitry Andric     switch (II->getIntrinsicID()) {
3540b57cec5SDimitry Andric     default:
3550b57cec5SDimitry Andric       break;
3560b57cec5SDimitry Andric       // FIXME: Add lifetime/invariant intrinsics (See: PR30807).
357*0fca6ea1SDimitry Andric     case Intrinsic::allow_runtime_check:
358*0fca6ea1SDimitry Andric     case Intrinsic::allow_ubsan_check:
3590b57cec5SDimitry Andric     case Intrinsic::assume:
360e8d8bef9SDimitry Andric     case Intrinsic::experimental_noalias_scope_decl:
3610b57cec5SDimitry Andric     case Intrinsic::sideeffect:
362e8d8bef9SDimitry Andric     case Intrinsic::pseudoprobe:
3630b57cec5SDimitry Andric       return;
3640b57cec5SDimitry Andric     }
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric   if (!Inst->mayReadOrWriteMemory())
3670b57cec5SDimitry Andric     return; // doesn't alias anything
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   if (AliasSet *AS = findAliasSetForUnknownInst(Inst)) {
3700b57cec5SDimitry Andric     AS->addUnknownInst(Inst, AA);
3710b57cec5SDimitry Andric     return;
3720b57cec5SDimitry Andric   }
3730b57cec5SDimitry Andric   AliasSets.push_back(new AliasSet());
3740b57cec5SDimitry Andric   AliasSets.back().addUnknownInst(Inst, AA);
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric void AliasSetTracker::add(Instruction *I) {
3780b57cec5SDimitry Andric   // Dispatch to one of the other add methods.
3790b57cec5SDimitry Andric   if (LoadInst *LI = dyn_cast<LoadInst>(I))
3800b57cec5SDimitry Andric     return add(LI);
3810b57cec5SDimitry Andric   if (StoreInst *SI = dyn_cast<StoreInst>(I))
3820b57cec5SDimitry Andric     return add(SI);
3830b57cec5SDimitry Andric   if (VAArgInst *VAAI = dyn_cast<VAArgInst>(I))
3840b57cec5SDimitry Andric     return add(VAAI);
3850b57cec5SDimitry Andric   if (AnyMemSetInst *MSI = dyn_cast<AnyMemSetInst>(I))
3860b57cec5SDimitry Andric     return add(MSI);
3870b57cec5SDimitry Andric   if (AnyMemTransferInst *MTI = dyn_cast<AnyMemTransferInst>(I))
3880b57cec5SDimitry Andric     return add(MTI);
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric   // Handle all calls with known mod/ref sets genericall
3910b57cec5SDimitry Andric   if (auto *Call = dyn_cast<CallBase>(I))
3920b57cec5SDimitry Andric     if (Call->onlyAccessesArgMemory()) {
3930b57cec5SDimitry Andric       auto getAccessFromModRef = [](ModRefInfo MRI) {
3940b57cec5SDimitry Andric         if (isRefSet(MRI) && isModSet(MRI))
3950b57cec5SDimitry Andric           return AliasSet::ModRefAccess;
3960b57cec5SDimitry Andric         else if (isModSet(MRI))
3970b57cec5SDimitry Andric           return AliasSet::ModAccess;
3980b57cec5SDimitry Andric         else if (isRefSet(MRI))
3990b57cec5SDimitry Andric           return AliasSet::RefAccess;
4000b57cec5SDimitry Andric         else
4010b57cec5SDimitry Andric           return AliasSet::NoAccess;
4020b57cec5SDimitry Andric       };
4030b57cec5SDimitry Andric 
404bdd1243dSDimitry Andric       ModRefInfo CallMask = AA.getMemoryEffects(Call).getModRef();
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric       // Some intrinsics are marked as modifying memory for control flow
4070b57cec5SDimitry Andric       // modelling purposes, but don't actually modify any specific memory
4080b57cec5SDimitry Andric       // location.
4090b57cec5SDimitry Andric       using namespace PatternMatch;
4100b57cec5SDimitry Andric       if (Call->use_empty() &&
4110b57cec5SDimitry Andric           match(Call, m_Intrinsic<Intrinsic::invariant_start>()))
412bdd1243dSDimitry Andric         CallMask &= ModRefInfo::Ref;
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric       for (auto IdxArgPair : enumerate(Call->args())) {
4150b57cec5SDimitry Andric         int ArgIdx = IdxArgPair.index();
4160b57cec5SDimitry Andric         const Value *Arg = IdxArgPair.value();
4170b57cec5SDimitry Andric         if (!Arg->getType()->isPointerTy())
4180b57cec5SDimitry Andric           continue;
4190b57cec5SDimitry Andric         MemoryLocation ArgLoc =
4200b57cec5SDimitry Andric             MemoryLocation::getForArgument(Call, ArgIdx, nullptr);
4210b57cec5SDimitry Andric         ModRefInfo ArgMask = AA.getArgModRefInfo(Call, ArgIdx);
422bdd1243dSDimitry Andric         ArgMask &= CallMask;
4230b57cec5SDimitry Andric         if (!isNoModRef(ArgMask))
4247a6dacacSDimitry Andric           addMemoryLocation(ArgLoc, getAccessFromModRef(ArgMask));
4250b57cec5SDimitry Andric       }
4260b57cec5SDimitry Andric       return;
4270b57cec5SDimitry Andric     }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   return addUnknown(I);
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric void AliasSetTracker::add(BasicBlock &BB) {
4330b57cec5SDimitry Andric   for (auto &I : BB)
4340b57cec5SDimitry Andric     add(&I);
4350b57cec5SDimitry Andric }
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric void AliasSetTracker::add(const AliasSetTracker &AST) {
4380b57cec5SDimitry Andric   assert(&AA == &AST.AA &&
4390b57cec5SDimitry Andric          "Merging AliasSetTracker objects with different Alias Analyses!");
4400b57cec5SDimitry Andric 
4417a6dacacSDimitry Andric   // Loop over all of the alias sets in AST, adding the members contained
4420b57cec5SDimitry Andric   // therein into the current alias sets.  This can cause alias sets to be
4430b57cec5SDimitry Andric   // merged together in the current AST.
4440b57cec5SDimitry Andric   for (const AliasSet &AS : AST) {
4450b57cec5SDimitry Andric     if (AS.Forward)
4460b57cec5SDimitry Andric       continue; // Ignore forwarding alias sets
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric     // If there are any call sites in the alias set, add them to this AST.
449bdd1243dSDimitry Andric     for (Instruction *Inst : AS.UnknownInsts)
4500b57cec5SDimitry Andric       add(Inst);
4510b57cec5SDimitry Andric 
4527a6dacacSDimitry Andric     // Loop over all of the memory locations in this alias set.
4537a6dacacSDimitry Andric     for (const MemoryLocation &ASMemLoc : AS.MemoryLocs)
4547a6dacacSDimitry Andric       addMemoryLocation(ASMemLoc, (AliasSet::AccessLattice)AS.Access);
4550b57cec5SDimitry Andric   }
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric AliasSet &AliasSetTracker::mergeAllAliasSets() {
4597a6dacacSDimitry Andric   assert(!AliasAnyAS && (TotalAliasSetSize > SaturationThreshold) &&
4600b57cec5SDimitry Andric          "Full merge should happen once, when the saturation threshold is "
4610b57cec5SDimitry Andric          "reached");
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric   // Collect all alias sets, so that we can drop references with impunity
4640b57cec5SDimitry Andric   // without worrying about iterator invalidation.
4650b57cec5SDimitry Andric   std::vector<AliasSet *> ASVector;
4660b57cec5SDimitry Andric   ASVector.reserve(SaturationThreshold);
467fe6060f1SDimitry Andric   for (AliasSet &AS : *this)
468fe6060f1SDimitry Andric     ASVector.push_back(&AS);
4690b57cec5SDimitry Andric 
4707a6dacacSDimitry Andric   // Copy all instructions and memory locations into a new set, and forward all
4717a6dacacSDimitry Andric   // other sets to it.
4720b57cec5SDimitry Andric   AliasSets.push_back(new AliasSet());
4730b57cec5SDimitry Andric   AliasAnyAS = &AliasSets.back();
4740b57cec5SDimitry Andric   AliasAnyAS->Alias = AliasSet::SetMayAlias;
4750b57cec5SDimitry Andric   AliasAnyAS->Access = AliasSet::ModRefAccess;
4760b57cec5SDimitry Andric   AliasAnyAS->AliasAny = true;
4770b57cec5SDimitry Andric 
478fcaf7f86SDimitry Andric   for (auto *Cur : ASVector) {
4790b57cec5SDimitry Andric     // If Cur was already forwarding, just forward to the new AS instead.
4800b57cec5SDimitry Andric     AliasSet *FwdTo = Cur->Forward;
4810b57cec5SDimitry Andric     if (FwdTo) {
4820b57cec5SDimitry Andric       Cur->Forward = AliasAnyAS;
4830b57cec5SDimitry Andric       AliasAnyAS->addRef();
4840b57cec5SDimitry Andric       FwdTo->dropRef(*this);
4850b57cec5SDimitry Andric       continue;
4860b57cec5SDimitry Andric     }
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric     // Otherwise, perform the actual merge.
489bdd1243dSDimitry Andric     AliasAnyAS->mergeSetIn(*Cur, *this, AA);
4900b57cec5SDimitry Andric   }
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   return *AliasAnyAS;
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric 
4957a6dacacSDimitry Andric AliasSet &AliasSetTracker::addMemoryLocation(MemoryLocation Loc,
4960b57cec5SDimitry Andric                                              AliasSet::AccessLattice E) {
4970b57cec5SDimitry Andric   AliasSet &AS = getAliasSetFor(Loc);
4980b57cec5SDimitry Andric   AS.Access |= E;
4990b57cec5SDimitry Andric 
5007a6dacacSDimitry Andric   if (!AliasAnyAS && (TotalAliasSetSize > SaturationThreshold)) {
5010b57cec5SDimitry Andric     // The AST is now saturated. From here on, we conservatively consider all
5027a6dacacSDimitry Andric     // elements to alias each-other.
5030b57cec5SDimitry Andric     return mergeAllAliasSets();
5040b57cec5SDimitry Andric   }
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric   return AS;
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5100b57cec5SDimitry Andric //               AliasSet/AliasSetTracker Printing Support
5110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric void AliasSet::print(raw_ostream &OS) const {
5140b57cec5SDimitry Andric   OS << "  AliasSet[" << (const void*)this << ", " << RefCount << "] ";
5150b57cec5SDimitry Andric   OS << (Alias == SetMustAlias ? "must" : "may") << " alias, ";
5160b57cec5SDimitry Andric   switch (Access) {
5170b57cec5SDimitry Andric   case NoAccess:     OS << "No access "; break;
5180b57cec5SDimitry Andric   case RefAccess:    OS << "Ref       "; break;
5190b57cec5SDimitry Andric   case ModAccess:    OS << "Mod       "; break;
5200b57cec5SDimitry Andric   case ModRefAccess: OS << "Mod/Ref   "; break;
5210b57cec5SDimitry Andric   default: llvm_unreachable("Bad value for Access!");
5220b57cec5SDimitry Andric   }
5230b57cec5SDimitry Andric   if (Forward)
5240b57cec5SDimitry Andric     OS << " forwarding to " << (void*)Forward;
5250b57cec5SDimitry Andric 
5267a6dacacSDimitry Andric   if (!MemoryLocs.empty()) {
5277a6dacacSDimitry Andric     ListSeparator LS;
5287a6dacacSDimitry Andric     OS << "Memory locations: ";
5297a6dacacSDimitry Andric     for (const MemoryLocation &MemLoc : MemoryLocs) {
5307a6dacacSDimitry Andric       OS << LS;
5317a6dacacSDimitry Andric       MemLoc.Ptr->printAsOperand(OS << "(");
5327a6dacacSDimitry Andric       if (MemLoc.Size == LocationSize::afterPointer())
533e8d8bef9SDimitry Andric         OS << ", unknown after)";
5347a6dacacSDimitry Andric       else if (MemLoc.Size == LocationSize::beforeOrAfterPointer())
535e8d8bef9SDimitry Andric         OS << ", unknown before-or-after)";
5360b57cec5SDimitry Andric       else
5377a6dacacSDimitry Andric         OS << ", " << MemLoc.Size << ")";
5380b57cec5SDimitry Andric     }
5390b57cec5SDimitry Andric   }
5400b57cec5SDimitry Andric   if (!UnknownInsts.empty()) {
541bdd1243dSDimitry Andric     ListSeparator LS;
5420b57cec5SDimitry Andric     OS << "\n    " << UnknownInsts.size() << " Unknown instructions: ";
543bdd1243dSDimitry Andric     for (Instruction *I : UnknownInsts) {
544bdd1243dSDimitry Andric       OS << LS;
5450b57cec5SDimitry Andric       if (I->hasName())
5460b57cec5SDimitry Andric         I->printAsOperand(OS);
5470b57cec5SDimitry Andric       else
5480b57cec5SDimitry Andric         I->print(OS);
5490b57cec5SDimitry Andric     }
5500b57cec5SDimitry Andric   }
5510b57cec5SDimitry Andric   OS << "\n";
5520b57cec5SDimitry Andric }
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric void AliasSetTracker::print(raw_ostream &OS) const {
5558bcb0991SDimitry Andric   OS << "Alias Set Tracker: " << AliasSets.size();
5568bcb0991SDimitry Andric   if (AliasAnyAS)
5578bcb0991SDimitry Andric     OS << " (Saturated)";
5588bcb0991SDimitry Andric   OS << " alias sets for " << PointerMap.size() << " pointer values.\n";
5590b57cec5SDimitry Andric   for (const AliasSet &AS : *this)
5600b57cec5SDimitry Andric     AS.print(OS);
5610b57cec5SDimitry Andric   OS << "\n";
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
5650b57cec5SDimitry Andric LLVM_DUMP_METHOD void AliasSet::dump() const { print(dbgs()); }
5660b57cec5SDimitry Andric LLVM_DUMP_METHOD void AliasSetTracker::dump() const { print(dbgs()); }
5670b57cec5SDimitry Andric #endif
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5700b57cec5SDimitry Andric //                            AliasSetPrinter Pass
5710b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5720b57cec5SDimitry Andric 
573e8d8bef9SDimitry Andric AliasSetsPrinterPass::AliasSetsPrinterPass(raw_ostream &OS) : OS(OS) {}
574e8d8bef9SDimitry Andric 
575e8d8bef9SDimitry Andric PreservedAnalyses AliasSetsPrinterPass::run(Function &F,
576e8d8bef9SDimitry Andric                                             FunctionAnalysisManager &AM) {
577e8d8bef9SDimitry Andric   auto &AA = AM.getResult<AAManager>(F);
578bdd1243dSDimitry Andric   BatchAAResults BatchAA(AA);
579bdd1243dSDimitry Andric   AliasSetTracker Tracker(BatchAA);
580e8d8bef9SDimitry Andric   OS << "Alias sets for function '" << F.getName() << "':\n";
581fe6060f1SDimitry Andric   for (Instruction &I : instructions(F))
582fe6060f1SDimitry Andric     Tracker.add(&I);
583e8d8bef9SDimitry Andric   Tracker.print(OS);
584e8d8bef9SDimitry Andric   return PreservedAnalyses::all();
585e8d8bef9SDimitry Andric }
586