diff options
Diffstat (limited to 'lib/Analysis/AliasSetTracker.cpp')
-rw-r--r-- | lib/Analysis/AliasSetTracker.cpp | 204 |
1 files changed, 108 insertions, 96 deletions
diff --git a/lib/Analysis/AliasSetTracker.cpp b/lib/Analysis/AliasSetTracker.cpp index 8f903fa4f1e8..f6ad704cc914 100644 --- a/lib/Analysis/AliasSetTracker.cpp +++ b/lib/Analysis/AliasSetTracker.cpp @@ -13,9 +13,9 @@ #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/GuardUtils.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Config/llvm-config.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" @@ -24,6 +24,7 @@ #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/Pass.h" #include "llvm/Support/AtomicOrdering.h" @@ -55,7 +56,6 @@ void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST) { // Update the alias and access types of this set... Access |= AS.Access; Alias |= AS.Alias; - Volatile |= AS.Volatile; if (Alias == SetMustAlias) { // Check that these two merged sets really are must aliases. Since both @@ -113,10 +113,9 @@ void AliasSetTracker::removeAliasSet(AliasSet *AS) { if (AliasSet *Fwd = AS->Forward) { Fwd->dropRef(*this); AS->Forward = nullptr; - } - - if (AS->Alias == AliasSet::SetMayAlias) - TotalMayAliasSetSize -= AS->size(); + } else // Update TotalMayAliasSetSize only if not forwarding. + if (AS->Alias == AliasSet::SetMayAlias) + TotalMayAliasSetSize -= AS->size(); AliasSets.erase(AS); } @@ -169,7 +168,12 @@ void AliasSet::addUnknownInst(Instruction *I, AliasAnalysis &AA) { addRef(); UnknownInsts.emplace_back(I); - if (!I->mayWriteToMemory()) { + // 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; @@ -226,12 +230,13 @@ bool AliasSet::aliasesUnknownInst(const Instruction *Inst, if (AliasAny) return true; - if (!Inst->mayReadOrWriteMemory()) - return false; + 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)) { - ImmutableCallSite C1(UnknownInst), C2(Inst); + 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; @@ -246,6 +251,31 @@ bool AliasSet::aliasesUnknownInst(const Instruction *Inst, 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(); @@ -280,13 +310,6 @@ AliasSet *AliasSetTracker::mergeAliasSetsForPointer(const Value *Ptr, return FoundSet; } -bool AliasSetTracker::containsUnknown(const Instruction *Inst) const { - for (const AliasSet &AS : *this) - if (!AS.Forward && AS.aliasesUnknownInst(Inst, AA)) - return true; - return false; -} - AliasSet *AliasSetTracker::findAliasSetForUnknownInst(Instruction *Inst) { AliasSet *FoundSet = nullptr; for (iterator I = begin(), E = end(); I != E;) { @@ -295,17 +318,18 @@ AliasSet *AliasSetTracker::findAliasSetForUnknownInst(Instruction *Inst) { continue; if (!FoundSet) // If this is the first alias set ptr can go into. FoundSet = &*Cur; // Remember it. - else if (!Cur->Forward) // Otherwise, we must merge the sets. + else // Otherwise, we must merge the sets. FoundSet->mergeSetIn(*Cur, *this); // Merge in contents. } return FoundSet; } -/// getAliasSetForPointer - Return the alias set that the specified pointer -/// lives in. -AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer, - LocationSize Size, - const AAMDNodes &AAInfo) { +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) { @@ -351,83 +375,32 @@ AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer, void AliasSetTracker::add(Value *Ptr, LocationSize Size, const AAMDNodes &AAInfo) { - addPointer(Ptr, Size, AAInfo, AliasSet::NoAccess); + addPointer(MemoryLocation(Ptr, Size, AAInfo), AliasSet::NoAccess); } void AliasSetTracker::add(LoadInst *LI) { - if (isStrongerThanMonotonic(LI->getOrdering())) return addUnknown(LI); - - AAMDNodes AAInfo; - LI->getAAMetadata(AAInfo); - - AliasSet::AccessLattice Access = AliasSet::RefAccess; - const DataLayout &DL = LI->getModule()->getDataLayout(); - AliasSet &AS = addPointer(LI->getOperand(0), - DL.getTypeStoreSize(LI->getType()), AAInfo, Access); - if (LI->isVolatile()) AS.setVolatile(); + 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); - - AAMDNodes AAInfo; - SI->getAAMetadata(AAInfo); - - AliasSet::AccessLattice Access = AliasSet::ModAccess; - const DataLayout &DL = SI->getModule()->getDataLayout(); - Value *Val = SI->getOperand(0); - AliasSet &AS = addPointer( - SI->getOperand(1), DL.getTypeStoreSize(Val->getType()), AAInfo, Access); - if (SI->isVolatile()) AS.setVolatile(); + if (isStrongerThanMonotonic(SI->getOrdering())) + return addUnknown(SI); + addPointer(MemoryLocation::get(SI), AliasSet::ModAccess); } void AliasSetTracker::add(VAArgInst *VAAI) { - AAMDNodes AAInfo; - VAAI->getAAMetadata(AAInfo); - - addPointer(VAAI->getOperand(0), MemoryLocation::UnknownSize, AAInfo, - AliasSet::ModRefAccess); + addPointer(MemoryLocation::get(VAAI), AliasSet::ModRefAccess); } void AliasSetTracker::add(AnyMemSetInst *MSI) { - AAMDNodes AAInfo; - MSI->getAAMetadata(AAInfo); - - uint64_t Len; - - if (ConstantInt *C = dyn_cast<ConstantInt>(MSI->getLength())) - Len = C->getZExtValue(); - else - Len = MemoryLocation::UnknownSize; - - AliasSet &AS = - addPointer(MSI->getRawDest(), Len, AAInfo, AliasSet::ModAccess); - auto *MS = dyn_cast<MemSetInst>(MSI); - if (MS && MS->isVolatile()) - AS.setVolatile(); + addPointer(MemoryLocation::getForDest(MSI), AliasSet::ModAccess); } void AliasSetTracker::add(AnyMemTransferInst *MTI) { - AAMDNodes AAInfo; - MTI->getAAMetadata(AAInfo); - - uint64_t Len; - if (ConstantInt *C = dyn_cast<ConstantInt>(MTI->getLength())) - Len = C->getZExtValue(); - else - Len = MemoryLocation::UnknownSize; - - AliasSet &ASSrc = - addPointer(MTI->getRawSource(), Len, AAInfo, AliasSet::RefAccess); - - AliasSet &ASDst = - addPointer(MTI->getRawDest(), Len, AAInfo, AliasSet::ModAccess); - - auto* MT = dyn_cast<MemTransferInst>(MTI); - if (MT && MT->isVolatile()) { - ASSrc.setVolatile(); - ASDst.setVolatile(); - } + addPointer(MemoryLocation::getForDest(MTI), AliasSet::ModAccess); + addPointer(MemoryLocation::getForSource(MTI), AliasSet::RefAccess); } void AliasSetTracker::addUnknown(Instruction *Inst) { @@ -471,6 +444,46 @@ void AliasSetTracker::add(Instruction *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); } @@ -496,12 +509,10 @@ void AliasSetTracker::add(const AliasSetTracker &AST) { add(Inst); // Loop over all of the pointers in this alias set. - for (AliasSet::iterator ASI = AS.begin(), E = AS.end(); ASI != E; ++ASI) { - AliasSet &NewAS = - addPointer(ASI.getPointer(), ASI.getSize(), ASI.getAAInfo(), - (AliasSet::AccessLattice)AS.Access); - if (AS.isVolatile()) NewAS.setVolatile(); - } + for (AliasSet::iterator ASI = AS.begin(), E = AS.end(); ASI != E; ++ASI) + addPointer( + MemoryLocation(ASI.getPointer(), ASI.getSize(), ASI.getAAInfo()), + (AliasSet::AccessLattice)AS.Access); } } @@ -594,10 +605,9 @@ AliasSet &AliasSetTracker::mergeAllAliasSets() { return *AliasAnyAS; } -AliasSet &AliasSetTracker::addPointer(Value *P, LocationSize Size, - const AAMDNodes &AAInfo, +AliasSet &AliasSetTracker::addPointer(MemoryLocation Loc, AliasSet::AccessLattice E) { - AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo); + AliasSet &AS = getAliasSetFor(Loc); AS.Access |= E; if (!AliasAnyAS && (TotalMayAliasSetSize > SaturationThreshold)) { @@ -623,7 +633,6 @@ void AliasSet::print(raw_ostream &OS) const { case ModRefAccess: OS << "Mod/Ref "; break; default: llvm_unreachable("Bad value for Access!"); } - if (isVolatile()) OS << "[volatile] "; if (Forward) OS << " forwarding to " << (void*)Forward; @@ -632,7 +641,10 @@ void AliasSet::print(raw_ostream &OS) const { for (iterator I = begin(), E = end(); I != E; ++I) { if (I != begin()) OS << ", "; I.getPointer()->printAsOperand(OS << "("); - OS << ", " << I.getSize() << ")"; + if (I.getSize() == LocationSize::unknown()) + OS << ", unknown)"; + else + OS << ", " << I.getSize() << ")"; } } if (!UnknownInsts.empty()) { |