003 File Manager
Current Path:
/usr/src/contrib/llvm-project/llvm/lib/Analysis
usr
/
src
/
contrib
/
llvm-project
/
llvm
/
lib
/
Analysis
/
📁
..
📄
AliasAnalysis.cpp
(33.55 KB)
📄
AliasAnalysisEvaluator.cpp
(15.64 KB)
📄
AliasAnalysisSummary.cpp
(3.49 KB)
📄
AliasAnalysisSummary.h
(10.17 KB)
📄
AliasSetTracker.cpp
(25.86 KB)
📄
Analysis.cpp
(5.29 KB)
📄
AssumeBundleQueries.cpp
(7.96 KB)
📄
AssumptionCache.cpp
(10.94 KB)
📄
BasicAliasAnalysis.cpp
(85.81 KB)
📄
BlockFrequencyInfo.cpp
(12.39 KB)
📄
BlockFrequencyInfoImpl.cpp
(28.6 KB)
📄
BranchProbabilityInfo.cpp
(43.48 KB)
📄
CFG.cpp
(9.9 KB)
📄
CFGPrinter.cpp
(11.2 KB)
📄
CFLAndersAliasAnalysis.cpp
(33.01 KB)
📄
CFLGraph.h
(21.23 KB)
📄
CFLSteensAliasAnalysis.cpp
(13.24 KB)
📄
CGSCCPassManager.cpp
(31.2 KB)
📄
CallGraph.cpp
(12.86 KB)
📄
CallGraphSCCPass.cpp
(26.31 KB)
📄
CallPrinter.cpp
(9.48 KB)
📄
CaptureTracking.cpp
(15.38 KB)
📄
CmpInstAnalysis.cpp
(4.63 KB)
📄
CodeMetrics.cpp
(6.99 KB)
📄
ConstantFolding.cpp
(105.15 KB)
📄
CostModel.cpp
(3.87 KB)
📄
DDG.cpp
(11.29 KB)
📄
Delinearization.cpp
(4.49 KB)
📄
DemandedBits.cpp
(16.27 KB)
📄
DependenceAnalysis.cpp
(150.78 KB)
📄
DependenceGraphBuilder.cpp
(19.24 KB)
📄
DivergenceAnalysis.cpp
(15.59 KB)
📄
DomPrinter.cpp
(9.67 KB)
📄
DomTreeUpdater.cpp
(15.21 KB)
📄
DominanceFrontier.cpp
(3.2 KB)
📄
EHPersonalities.cpp
(5.89 KB)
📄
GlobalsModRef.cpp
(41 KB)
📄
GuardUtils.cpp
(3.27 KB)
📄
HeatUtils.cpp
(2.85 KB)
📄
IVDescriptors.cpp
(42.28 KB)
📄
IVUsers.cpp
(16.12 KB)
📄
IndirectCallPromotionAnalysis.cpp
(4.33 KB)
📄
InlineAdvisor.cpp
(15.28 KB)
📄
InlineCost.cpp
(99.47 KB)
📄
InlineFeaturesAnalysis.cpp
(1.59 KB)
📄
InlineSizeEstimatorAnalysis.cpp
(10.95 KB)
📄
InstCount.cpp
(2.45 KB)
📄
InstructionPrecedenceTracking.cpp
(4.8 KB)
📄
InstructionSimplify.cpp
(216.91 KB)
📄
Interval.cpp
(1.78 KB)
📄
IntervalPartition.cpp
(4.5 KB)
📄
LazyBlockFrequencyInfo.cpp
(2.81 KB)
📄
LazyBranchProbabilityInfo.cpp
(2.96 KB)
📄
LazyCallGraph.cpp
(67.33 KB)
📄
LazyValueInfo.cpp
(76.38 KB)
📄
LegacyDivergenceAnalysis.cpp
(14.82 KB)
📄
Lint.cpp
(29.07 KB)
📄
Loads.cpp
(20.6 KB)
📄
LoopAccessAnalysis.cpp
(88.02 KB)
📄
LoopAnalysisManager.cpp
(6.6 KB)
📄
LoopCacheAnalysis.cpp
(23.53 KB)
📄
LoopInfo.cpp
(37.15 KB)
📄
LoopNestAnalysis.cpp
(10.62 KB)
📄
LoopPass.cpp
(12.89 KB)
📄
LoopUnrollAnalyzer.cpp
(7.26 KB)
📄
MLInlineAdvisor.cpp
(11.36 KB)
📄
MemDepPrinter.cpp
(5.13 KB)
📄
MemDerefPrinter.cpp
(2.53 KB)
📄
MemoryBuiltins.cpp
(41.14 KB)
📄
MemoryDependenceAnalysis.cpp
(69.89 KB)
📄
MemoryLocation.cpp
(7.92 KB)
📄
MemorySSA.cpp
(90.16 KB)
📄
MemorySSAUpdater.cpp
(57.9 KB)
📄
ModuleDebugInfoPrinter.cpp
(4.02 KB)
📄
ModuleSummaryAnalysis.cpp
(38.13 KB)
📄
MustExecute.cpp
(31.18 KB)
📄
ObjCARCAliasAnalysis.cpp
(5.81 KB)
📄
ObjCARCAnalysisUtils.cpp
(1.07 KB)
📄
ObjCARCInstKind.cpp
(23.15 KB)
📄
OptimizationRemarkEmitter.cpp
(4.23 KB)
📄
PHITransAddr.cpp
(16.05 KB)
📄
PhiValues.cpp
(8.4 KB)
📄
PostDominators.cpp
(3.59 KB)
📄
ProfileSummaryInfo.cpp
(18.07 KB)
📄
PtrUseVisitor.cpp
(1.28 KB)
📄
RegionInfo.cpp
(6.5 KB)
📄
RegionPass.cpp
(9.23 KB)
📄
RegionPrinter.cpp
(8.61 KB)
📄
ReleaseModeModelRunner.cpp
(2.83 KB)
📄
ScalarEvolution.cpp
(475.26 KB)
📄
ScalarEvolutionAliasAnalysis.cpp
(5.96 KB)
📄
ScalarEvolutionDivision.cpp
(7.51 KB)
📄
ScalarEvolutionNormalization.cpp
(4.59 KB)
📄
ScopedNoAliasAA.cpp
(7.38 KB)
📄
StackLifetime.cpp
(12.22 KB)
📄
StackSafetyAnalysis.cpp
(31.81 KB)
📄
StratifiedSets.h
(18.67 KB)
📄
SyncDependenceAnalysis.cpp
(12.97 KB)
📄
SyntheticCountsUtils.cpp
(3.81 KB)
📄
TFUtils.cpp
(8.99 KB)
📄
TargetLibraryInfo.cpp
(58.98 KB)
📄
TargetTransformInfo.cpp
(48.15 KB)
📄
Trace.cpp
(1.8 KB)
📄
TypeBasedAliasAnalysis.cpp
(26.04 KB)
📄
TypeMetadataUtils.cpp
(5.93 KB)
📄
VFABIDemangling.cpp
(16.46 KB)
📄
ValueLattice.cpp
(1.19 KB)
📄
ValueLatticeUtils.cpp
(1.53 KB)
📄
ValueTracking.cpp
(243.08 KB)
📄
VectorUtils.cpp
(48.57 KB)
📁
models
Editing: AliasSetTracker.cpp
//===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the AliasSetTracker and AliasSet classes. // //===----------------------------------------------------------------------===// #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/GuardUtils.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/PatternMatch.h" #include "llvm/IR/Value.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <cassert> #include <cstdint> #include <vector> using namespace llvm; static cl::opt<unsigned> SaturationThreshold("alias-set-saturation-threshold", cl::Hidden, cl::init(250), cl::desc("The maximum number of pointers may-alias " "sets may contain before degradation")); /// mergeSetIn - Merge the specified alias set into this alias set. /// void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST) { assert(!AS.Forward && "Alias set is already forwarding!"); assert(!Forward && "This set is a forwarding set!!"); bool WasMustAlias = (Alias == SetMustAlias); // Update the alias and access types of this set... Access |= AS.Access; Alias |= AS.Alias; if (Alias == SetMustAlias) { // Check that these two merged sets really are must aliases. Since both // used to be must-alias sets, we can just check any pointer from each set // for aliasing. AliasAnalysis &AA = AST.getAliasAnalysis(); PointerRec *L = getSomePointer(); PointerRec *R = AS.getSomePointer(); // If the pointers are not a must-alias pair, this set becomes a may alias. if (AA.alias(MemoryLocation(L->getValue(), L->getSize(), L->getAAInfo()), MemoryLocation(R->getValue(), R->getSize(), R->getAAInfo())) != MustAlias) Alias = SetMayAlias; } if (Alias == SetMayAlias) { if (WasMustAlias) AST.TotalMayAliasSetSize += size(); if (AS.Alias == SetMustAlias) AST.TotalMayAliasSetSize += AS.size(); } bool ASHadUnknownInsts = !AS.UnknownInsts.empty(); if (UnknownInsts.empty()) { // Merge call sites... if (ASHadUnknownInsts) { std::swap(UnknownInsts, AS.UnknownInsts); addRef(); } } else if (ASHadUnknownInsts) { UnknownInsts.insert(UnknownInsts.end(), AS.UnknownInsts.begin(), AS.UnknownInsts.end()); AS.UnknownInsts.clear(); } AS.Forward = this; // Forward across AS now... addRef(); // AS is now pointing to us... // Merge the list of constituent pointers... if (AS.PtrList) { SetSize += AS.size(); AS.SetSize = 0; *PtrListEnd = AS.PtrList; AS.PtrList->setPrevInList(PtrListEnd); PtrListEnd = AS.PtrListEnd; AS.PtrList = nullptr; AS.PtrListEnd = &AS.PtrList; assert(*AS.PtrListEnd == nullptr && "End of list is not null?"); } if (ASHadUnknownInsts) AS.dropRef(AST); } void AliasSetTracker::removeAliasSet(AliasSet *AS) { if (AliasSet *Fwd = AS->Forward) { Fwd->dropRef(*this); AS->Forward = nullptr; } else // Update TotalMayAliasSetSize only if not forwarding. if (AS->Alias == AliasSet::SetMayAlias) TotalMayAliasSetSize -= AS->size(); AliasSets.erase(AS); // If we've removed the saturated alias set, set saturated marker back to // nullptr and ensure this tracker is empty. if (AS == AliasAnyAS) { AliasAnyAS = nullptr; assert(AliasSets.empty() && "Tracker not empty"); } } void AliasSet::removeFromTracker(AliasSetTracker &AST) { assert(RefCount == 0 && "Cannot remove non-dead alias set from tracker!"); AST.removeAliasSet(this); } void AliasSet::addPointer(AliasSetTracker &AST, PointerRec &Entry, LocationSize Size, const AAMDNodes &AAInfo, bool KnownMustAlias, bool SkipSizeUpdate) { assert(!Entry.hasAliasSet() && "Entry already in set!"); // Check to see if we have to downgrade to _may_ alias. if (isMustAlias()) if (PointerRec *P = getSomePointer()) { if (!KnownMustAlias) { AliasAnalysis &AA = AST.getAliasAnalysis(); AliasResult Result = AA.alias( MemoryLocation(P->getValue(), P->getSize(), P->getAAInfo()), MemoryLocation(Entry.getValue(), Size, AAInfo)); if (Result != MustAlias) { Alias = SetMayAlias; AST.TotalMayAliasSetSize += size(); } assert(Result != NoAlias && "Cannot be part of must set!"); } else if (!SkipSizeUpdate) P->updateSizeAndAAInfo(Size, AAInfo); } Entry.setAliasSet(this); Entry.updateSizeAndAAInfo(Size, AAInfo); // Add it to the end of the list... ++SetSize; assert(*PtrListEnd == nullptr && "End of list is not null?"); *PtrListEnd = &Entry; PtrListEnd = Entry.setPrevInList(PtrListEnd); assert(*PtrListEnd == nullptr && "End of list is not null?"); // Entry points to alias set. addRef(); if (Alias == SetMayAlias) AST.TotalMayAliasSetSize++; } void AliasSet::addUnknownInst(Instruction *I, AliasAnalysis &AA) { if (UnknownInsts.empty()) addRef(); UnknownInsts.emplace_back(I); // Guards are marked as modifying memory for control flow modelling purposes, // but don't actually modify any specific memory location. using namespace PatternMatch; bool MayWriteMemory = I->mayWriteToMemory() && !isGuard(I) && !(I->use_empty() && match(I, m_Intrinsic<Intrinsic::invariant_start>())); if (!MayWriteMemory) { Alias = SetMayAlias; Access |= RefAccess; return; } // FIXME: This should use mod/ref information to make this not suck so bad Alias = SetMayAlias; Access = ModRefAccess; } /// aliasesPointer - If the specified pointer "may" (or must) alias one of the /// members in the set return the appropriate AliasResult. Otherwise return /// NoAlias. /// AliasResult AliasSet::aliasesPointer(const Value *Ptr, LocationSize Size, const AAMDNodes &AAInfo, AliasAnalysis &AA) const { if (AliasAny) return MayAlias; if (Alias == SetMustAlias) { assert(UnknownInsts.empty() && "Illegal must alias set!"); // If this is a set of MustAliases, only check to see if the pointer aliases // SOME value in the set. PointerRec *SomePtr = getSomePointer(); assert(SomePtr && "Empty must-alias set??"); return AA.alias(MemoryLocation(SomePtr->getValue(), SomePtr->getSize(), SomePtr->getAAInfo()), MemoryLocation(Ptr, Size, AAInfo)); } // If this is a may-alias set, we have to check all of the pointers in the set // to be sure it doesn't alias the set... for (iterator I = begin(), E = end(); I != E; ++I) if (AliasResult AR = AA.alias( MemoryLocation(Ptr, Size, AAInfo), MemoryLocation(I.getPointer(), I.getSize(), I.getAAInfo()))) return AR; // Check the unknown instructions... if (!UnknownInsts.empty()) { for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) if (auto *Inst = getUnknownInst(i)) if (isModOrRefSet( AA.getModRefInfo(Inst, MemoryLocation(Ptr, Size, AAInfo)))) return MayAlias; } return NoAlias; } bool AliasSet::aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const { if (AliasAny) return true; assert(Inst->mayReadOrWriteMemory() && "Instruction must either read or write memory."); for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) { if (auto *UnknownInst = getUnknownInst(i)) { const auto *C1 = dyn_cast<CallBase>(UnknownInst); const auto *C2 = dyn_cast<CallBase>(Inst); if (!C1 || !C2 || isModOrRefSet(AA.getModRefInfo(C1, C2)) || isModOrRefSet(AA.getModRefInfo(C2, C1))) return true; } } for (iterator I = begin(), E = end(); I != E; ++I) if (isModOrRefSet(AA.getModRefInfo( Inst, MemoryLocation(I.getPointer(), I.getSize(), I.getAAInfo())))) return true; return false; } Instruction* AliasSet::getUniqueInstruction() { if (AliasAny) // May have collapses alias set return nullptr; if (begin() != end()) { if (!UnknownInsts.empty()) // Another instruction found return nullptr; if (std::next(begin()) != end()) // Another instruction found return nullptr; Value *Addr = begin()->getValue(); assert(!Addr->user_empty() && "where's the instruction which added this pointer?"); if (std::next(Addr->user_begin()) != Addr->user_end()) // Another instruction found -- this is really restrictive // TODO: generalize! return nullptr; return cast<Instruction>(*(Addr->user_begin())); } if (1 != UnknownInsts.size()) return nullptr; return cast<Instruction>(UnknownInsts[0]); } void AliasSetTracker::clear() { // Delete all the PointerRec entries. for (PointerMapType::iterator I = PointerMap.begin(), E = PointerMap.end(); I != E; ++I) I->second->eraseFromList(); PointerMap.clear(); // The alias sets should all be clear now. AliasSets.clear(); } /// mergeAliasSetsForPointer - Given a pointer, merge all alias sets that may /// alias the pointer. Return the unified set, or nullptr if no set that aliases /// the pointer was found. MustAliasAll is updated to true/false if the pointer /// is found to MustAlias all the sets it merged. AliasSet *AliasSetTracker::mergeAliasSetsForPointer(const Value *Ptr, LocationSize Size, const AAMDNodes &AAInfo, bool &MustAliasAll) { AliasSet *FoundSet = nullptr; AliasResult AllAR = MustAlias; for (iterator I = begin(), E = end(); I != E;) { iterator Cur = I++; if (Cur->Forward) continue; AliasResult AR = Cur->aliasesPointer(Ptr, Size, AAInfo, AA); if (AR == NoAlias) continue; AllAR = AliasResult(AllAR & AR); // Possible downgrade to May/Partial, even No if (!FoundSet) { // If this is the first alias set ptr can go into, remember it. FoundSet = &*Cur; } else { // Otherwise, we must merge the sets. FoundSet->mergeSetIn(*Cur, *this); } } MustAliasAll = (AllAR == MustAlias); return FoundSet; } AliasSet *AliasSetTracker::findAliasSetForUnknownInst(Instruction *Inst) { AliasSet *FoundSet = nullptr; for (iterator I = begin(), E = end(); I != E;) { iterator Cur = I++; if (Cur->Forward || !Cur->aliasesUnknownInst(Inst, AA)) continue; if (!FoundSet) { // If this is the first alias set ptr can go into, remember it. FoundSet = &*Cur; } else { // Otherwise, we must merge the sets. FoundSet->mergeSetIn(*Cur, *this); } } return FoundSet; } AliasSet &AliasSetTracker::getAliasSetFor(const MemoryLocation &MemLoc) { Value * const Pointer = const_cast<Value*>(MemLoc.Ptr); const LocationSize Size = MemLoc.Size; const AAMDNodes &AAInfo = MemLoc.AATags; AliasSet::PointerRec &Entry = getEntryFor(Pointer); if (AliasAnyAS) { // At this point, the AST is saturated, so we only have one active alias // set. That means we already know which alias set we want to return, and // just need to add the pointer to that set to keep the data structure // consistent. // This, of course, means that we will never need a merge here. if (Entry.hasAliasSet()) { Entry.updateSizeAndAAInfo(Size, AAInfo); assert(Entry.getAliasSet(*this) == AliasAnyAS && "Entry in saturated AST must belong to only alias set"); } else { AliasAnyAS->addPointer(*this, Entry, Size, AAInfo); } return *AliasAnyAS; } bool MustAliasAll = false; // Check to see if the pointer is already known. if (Entry.hasAliasSet()) { // If the size changed, we may need to merge several alias sets. // Note that we can *not* return the result of mergeAliasSetsForPointer // due to a quirk of alias analysis behavior. Since alias(undef, undef) // is NoAlias, mergeAliasSetsForPointer(undef, ...) will not find the // the right set for undef, even if it exists. if (Entry.updateSizeAndAAInfo(Size, AAInfo)) mergeAliasSetsForPointer(Pointer, Size, AAInfo, MustAliasAll); // Return the set! return *Entry.getAliasSet(*this)->getForwardedTarget(*this); } if (AliasSet *AS = mergeAliasSetsForPointer(Pointer, Size, AAInfo, MustAliasAll)) { // Add it to the alias set it aliases. AS->addPointer(*this, Entry, Size, AAInfo, MustAliasAll); return *AS; } // Otherwise create a new alias set to hold the loaded pointer. AliasSets.push_back(new AliasSet()); AliasSets.back().addPointer(*this, Entry, Size, AAInfo, true); return AliasSets.back(); } void AliasSetTracker::add(Value *Ptr, LocationSize Size, const AAMDNodes &AAInfo) { addPointer(MemoryLocation(Ptr, Size, AAInfo), AliasSet::NoAccess); } void AliasSetTracker::add(LoadInst *LI) { if (isStrongerThanMonotonic(LI->getOrdering())) return addUnknown(LI); addPointer(MemoryLocation::get(LI), AliasSet::RefAccess); } void AliasSetTracker::add(StoreInst *SI) { if (isStrongerThanMonotonic(SI->getOrdering())) return addUnknown(SI); addPointer(MemoryLocation::get(SI), AliasSet::ModAccess); } void AliasSetTracker::add(VAArgInst *VAAI) { addPointer(MemoryLocation::get(VAAI), AliasSet::ModRefAccess); } void AliasSetTracker::add(AnyMemSetInst *MSI) { addPointer(MemoryLocation::getForDest(MSI), AliasSet::ModAccess); } void AliasSetTracker::add(AnyMemTransferInst *MTI) { addPointer(MemoryLocation::getForDest(MTI), AliasSet::ModAccess); addPointer(MemoryLocation::getForSource(MTI), AliasSet::RefAccess); } void AliasSetTracker::addUnknown(Instruction *Inst) { if (isa<DbgInfoIntrinsic>(Inst)) return; // Ignore DbgInfo Intrinsics. if (auto *II = dyn_cast<IntrinsicInst>(Inst)) { // These intrinsics will show up as affecting memory, but they are just // markers. switch (II->getIntrinsicID()) { default: break; // FIXME: Add lifetime/invariant intrinsics (See: PR30807). case Intrinsic::assume: case Intrinsic::sideeffect: return; } } if (!Inst->mayReadOrWriteMemory()) return; // doesn't alias anything if (AliasSet *AS = findAliasSetForUnknownInst(Inst)) { AS->addUnknownInst(Inst, AA); return; } AliasSets.push_back(new AliasSet()); AliasSets.back().addUnknownInst(Inst, AA); } void AliasSetTracker::add(Instruction *I) { // Dispatch to one of the other add methods. if (LoadInst *LI = dyn_cast<LoadInst>(I)) return add(LI); if (StoreInst *SI = dyn_cast<StoreInst>(I)) return add(SI); if (VAArgInst *VAAI = dyn_cast<VAArgInst>(I)) return add(VAAI); if (AnyMemSetInst *MSI = dyn_cast<AnyMemSetInst>(I)) return add(MSI); if (AnyMemTransferInst *MTI = dyn_cast<AnyMemTransferInst>(I)) return add(MTI); // Handle all calls with known mod/ref sets genericall if (auto *Call = dyn_cast<CallBase>(I)) if (Call->onlyAccessesArgMemory()) { auto getAccessFromModRef = [](ModRefInfo MRI) { if (isRefSet(MRI) && isModSet(MRI)) return AliasSet::ModRefAccess; else if (isModSet(MRI)) return AliasSet::ModAccess; else if (isRefSet(MRI)) return AliasSet::RefAccess; else return AliasSet::NoAccess; }; ModRefInfo CallMask = createModRefInfo(AA.getModRefBehavior(Call)); // Some intrinsics are marked as modifying memory for control flow // modelling purposes, but don't actually modify any specific memory // location. using namespace PatternMatch; if (Call->use_empty() && match(Call, m_Intrinsic<Intrinsic::invariant_start>())) CallMask = clearMod(CallMask); for (auto IdxArgPair : enumerate(Call->args())) { int ArgIdx = IdxArgPair.index(); const Value *Arg = IdxArgPair.value(); if (!Arg->getType()->isPointerTy()) continue; MemoryLocation ArgLoc = MemoryLocation::getForArgument(Call, ArgIdx, nullptr); ModRefInfo ArgMask = AA.getArgModRefInfo(Call, ArgIdx); ArgMask = intersectModRef(CallMask, ArgMask); if (!isNoModRef(ArgMask)) addPointer(ArgLoc, getAccessFromModRef(ArgMask)); } return; } return addUnknown(I); } void AliasSetTracker::add(BasicBlock &BB) { for (auto &I : BB) add(&I); } void AliasSetTracker::add(const AliasSetTracker &AST) { assert(&AA == &AST.AA && "Merging AliasSetTracker objects with different Alias Analyses!"); // Loop over all of the alias sets in AST, adding the pointers contained // therein into the current alias sets. This can cause alias sets to be // merged together in the current AST. for (const AliasSet &AS : AST) { if (AS.Forward) continue; // Ignore forwarding alias sets // If there are any call sites in the alias set, add them to this AST. for (unsigned i = 0, e = AS.UnknownInsts.size(); i != e; ++i) if (auto *Inst = AS.getUnknownInst(i)) add(Inst); // Loop over all of the pointers in this alias set. for (AliasSet::iterator ASI = AS.begin(), E = AS.end(); ASI != E; ++ASI) addPointer( MemoryLocation(ASI.getPointer(), ASI.getSize(), ASI.getAAInfo()), (AliasSet::AccessLattice)AS.Access); } } void AliasSetTracker::addAllInstructionsInLoopUsingMSSA() { assert(MSSA && L && "MSSA and L must be available"); for (const BasicBlock *BB : L->blocks()) if (auto *Accesses = MSSA->getBlockAccesses(BB)) for (auto &Access : *Accesses) if (auto *MUD = dyn_cast<MemoryUseOrDef>(&Access)) add(MUD->getMemoryInst()); } // deleteValue method - This method is used to remove a pointer value from the // AliasSetTracker entirely. It should be used when an instruction is deleted // from the program to update the AST. If you don't use this, you would have // dangling pointers to deleted instructions. // void AliasSetTracker::deleteValue(Value *PtrVal) { // First, look up the PointerRec for this pointer. PointerMapType::iterator I = PointerMap.find_as(PtrVal); if (I == PointerMap.end()) return; // Noop // If we found one, remove the pointer from the alias set it is in. AliasSet::PointerRec *PtrValEnt = I->second; AliasSet *AS = PtrValEnt->getAliasSet(*this); // Unlink and delete from the list of values. PtrValEnt->eraseFromList(); if (AS->Alias == AliasSet::SetMayAlias) { AS->SetSize--; TotalMayAliasSetSize--; } // Stop using the alias set. AS->dropRef(*this); PointerMap.erase(I); } // copyValue - This method should be used whenever a preexisting value in the // program is copied or cloned, introducing a new value. Note that it is ok for // clients that use this method to introduce the same value multiple times: if // the tracker already knows about a value, it will ignore the request. // void AliasSetTracker::copyValue(Value *From, Value *To) { // First, look up the PointerRec for this pointer. PointerMapType::iterator I = PointerMap.find_as(From); if (I == PointerMap.end()) return; // Noop assert(I->second->hasAliasSet() && "Dead entry?"); AliasSet::PointerRec &Entry = getEntryFor(To); if (Entry.hasAliasSet()) return; // Already in the tracker! // getEntryFor above may invalidate iterator \c I, so reinitialize it. I = PointerMap.find_as(From); // Add it to the alias set it aliases... AliasSet *AS = I->second->getAliasSet(*this); AS->addPointer(*this, Entry, I->second->getSize(), I->second->getAAInfo(), true, true); } AliasSet &AliasSetTracker::mergeAllAliasSets() { assert(!AliasAnyAS && (TotalMayAliasSetSize > SaturationThreshold) && "Full merge should happen once, when the saturation threshold is " "reached"); // Collect all alias sets, so that we can drop references with impunity // without worrying about iterator invalidation. std::vector<AliasSet *> ASVector; ASVector.reserve(SaturationThreshold); for (iterator I = begin(), E = end(); I != E; I++) ASVector.push_back(&*I); // Copy all instructions and pointers into a new set, and forward all other // sets to it. AliasSets.push_back(new AliasSet()); AliasAnyAS = &AliasSets.back(); AliasAnyAS->Alias = AliasSet::SetMayAlias; AliasAnyAS->Access = AliasSet::ModRefAccess; AliasAnyAS->AliasAny = true; for (auto Cur : ASVector) { // If Cur was already forwarding, just forward to the new AS instead. AliasSet *FwdTo = Cur->Forward; if (FwdTo) { Cur->Forward = AliasAnyAS; AliasAnyAS->addRef(); FwdTo->dropRef(*this); continue; } // Otherwise, perform the actual merge. AliasAnyAS->mergeSetIn(*Cur, *this); } return *AliasAnyAS; } AliasSet &AliasSetTracker::addPointer(MemoryLocation Loc, AliasSet::AccessLattice E) { AliasSet &AS = getAliasSetFor(Loc); AS.Access |= E; if (!AliasAnyAS && (TotalMayAliasSetSize > SaturationThreshold)) { // The AST is now saturated. From here on, we conservatively consider all // pointers to alias each-other. return mergeAllAliasSets(); } return AS; } //===----------------------------------------------------------------------===// // AliasSet/AliasSetTracker Printing Support //===----------------------------------------------------------------------===// void AliasSet::print(raw_ostream &OS) const { OS << " AliasSet[" << (const void*)this << ", " << RefCount << "] "; OS << (Alias == SetMustAlias ? "must" : "may") << " alias, "; switch (Access) { case NoAccess: OS << "No access "; break; case RefAccess: OS << "Ref "; break; case ModAccess: OS << "Mod "; break; case ModRefAccess: OS << "Mod/Ref "; break; default: llvm_unreachable("Bad value for Access!"); } if (Forward) OS << " forwarding to " << (void*)Forward; if (!empty()) { OS << "Pointers: "; for (iterator I = begin(), E = end(); I != E; ++I) { if (I != begin()) OS << ", "; I.getPointer()->printAsOperand(OS << "("); if (I.getSize() == LocationSize::unknown()) OS << ", unknown)"; else OS << ", " << I.getSize() << ")"; } } if (!UnknownInsts.empty()) { OS << "\n " << UnknownInsts.size() << " Unknown instructions: "; for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) { if (i) OS << ", "; if (auto *I = getUnknownInst(i)) { if (I->hasName()) I->printAsOperand(OS); else I->print(OS); } } } OS << "\n"; } void AliasSetTracker::print(raw_ostream &OS) const { OS << "Alias Set Tracker: " << AliasSets.size(); if (AliasAnyAS) OS << " (Saturated)"; OS << " alias sets for " << PointerMap.size() << " pointer values.\n"; for (const AliasSet &AS : *this) AS.print(OS); OS << "\n"; } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void AliasSet::dump() const { print(dbgs()); } LLVM_DUMP_METHOD void AliasSetTracker::dump() const { print(dbgs()); } #endif //===----------------------------------------------------------------------===// // ASTCallbackVH Class Implementation //===----------------------------------------------------------------------===// void AliasSetTracker::ASTCallbackVH::deleted() { assert(AST && "ASTCallbackVH called with a null AliasSetTracker!"); AST->deleteValue(getValPtr()); // this now dangles! } void AliasSetTracker::ASTCallbackVH::allUsesReplacedWith(Value *V) { AST->copyValue(getValPtr(), V); } AliasSetTracker::ASTCallbackVH::ASTCallbackVH(Value *V, AliasSetTracker *ast) : CallbackVH(V), AST(ast) {} AliasSetTracker::ASTCallbackVH & AliasSetTracker::ASTCallbackVH::operator=(Value *V) { return *this = ASTCallbackVH(V, AST); } //===----------------------------------------------------------------------===// // AliasSetPrinter Pass //===----------------------------------------------------------------------===// namespace { class AliasSetPrinter : public FunctionPass { AliasSetTracker *Tracker; public: static char ID; // Pass identification, replacement for typeid AliasSetPrinter() : FunctionPass(ID) { initializeAliasSetPrinterPass(*PassRegistry::getPassRegistry()); } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); AU.addRequired<AAResultsWrapperPass>(); } bool runOnFunction(Function &F) override { auto &AAWP = getAnalysis<AAResultsWrapperPass>(); Tracker = new AliasSetTracker(AAWP.getAAResults()); errs() << "Alias sets for function '" << F.getName() << "':\n"; for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) Tracker->add(&*I); Tracker->print(errs()); delete Tracker; return false; } }; } // end anonymous namespace char AliasSetPrinter::ID = 0; INITIALIZE_PASS_BEGIN(AliasSetPrinter, "print-alias-sets", "Alias Set Printer", false, true) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) INITIALIZE_PASS_END(AliasSetPrinter, "print-alias-sets", "Alias Set Printer", false, true)
Upload File
Create Folder