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