summaryrefslogtreecommitdiff
path: root/lib/Analysis/AliasSetTracker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/AliasSetTracker.cpp')
-rw-r--r--lib/Analysis/AliasSetTracker.cpp204
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()) {