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()) {  | 
