mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-24 14:20:17 +00:00
[PM/AA] Rebuild LLVM's alias analysis infrastructure in a way compatible
with the new pass manager, and no longer relying on analysis groups. This builds essentially a ground-up new AA infrastructure stack for LLVM. The core ideas are the same that are used throughout the new pass manager: type erased polymorphism and direct composition. The design is as follows: - FunctionAAResults is a type-erasing alias analysis results aggregation interface to walk a single query across a range of results from different alias analyses. Currently this is function-specific as we always assume that aliasing queries are *within* a function. - AAResultBase is a CRTP utility providing stub implementations of various parts of the alias analysis result concept, notably in several cases in terms of other more general parts of the interface. This can be used to implement only a narrow part of the interface rather than the entire interface. This isn't really ideal, this logic should be hoisted into FunctionAAResults as currently it will cause a significant amount of redundant work, but it faithfully models the behavior of the prior infrastructure. - All the alias analysis passes are ported to be wrapper passes for the legacy PM and new-style analysis passes for the new PM with a shared result object. In some cases (most notably CFL), this is an extremely naive approach that we should revisit when we can specialize for the new pass manager. - BasicAA has been restructured to reflect that it is much more fundamentally a function analysis because it uses dominator trees and loop info that need to be constructed for each function. All of the references to getting alias analysis results have been updated to use the new aggregation interface. All the preservation and other pass management code has been updated accordingly. The way the FunctionAAResultsWrapperPass works is to detect the available alias analyses when run, and add them to the results object. This means that we should be able to continue to respect when various passes are added to the pipeline, for example adding CFL or adding TBAA passes should just cause their results to be available and to get folded into this. The exception to this rule is BasicAA which really needs to be a function pass due to using dominator trees and loop info. As a consequence, the FunctionAAResultsWrapperPass directly depends on BasicAA and always includes it in the aggregation. This has significant implications for preserving analyses. Generally, most passes shouldn't bother preserving FunctionAAResultsWrapperPass because rebuilding the results just updates the set of known AA passes. The exception to this rule are LoopPass instances which need to preserve all the function analyses that the loop pass manager will end up needing. This means preserving both BasicAAWrapperPass and the aggregating FunctionAAResultsWrapperPass. Now, when preserving an alias analysis, you do so by directly preserving that analysis. This is only necessary for non-immutable-pass-provided alias analyses though, and there are only three of interest: BasicAA, GlobalsAA (formerly GlobalsModRef), and SCEVAA. Usually BasicAA is preserved when needed because it (like DominatorTree and LoopInfo) is marked as a CFG-only pass. I've expanded GlobalsAA into the preserved set everywhere we previously were preserving all of AliasAnalysis, and I've added SCEVAA in the intersection of that with where we preserve SCEV itself. One significant challenge to all of this is that the CGSCC passes were actually using the alias analysis implementations by taking advantage of a pretty amazing set of loop holes in the old pass manager's analysis management code which allowed analysis groups to slide through in many cases. Moving away from analysis groups makes this problem much more obvious. To fix it, I've leveraged the flexibility the design of the new PM components provides to just directly construct the relevant alias analyses for the relevant functions in the IPO passes that need them. This is a bit hacky, but should go away with the new pass manager, and is already in many ways cleaner than the prior state. Another significant challenge is that various facilities of the old alias analysis infrastructure just don't fit any more. The most significant of these is the alias analysis 'counter' pass. That pass relied on the ability to snoop on AA queries at different points in the analysis group chain. Instead, I'm planning to build printing functionality directly into the aggregation layer. I've not included that in this patch merely to keep it smaller. Note that all of this needs a nearly complete rewrite of the AA documentation. I'm planning to do that, but I'd like to make sure the new design settles, and to flesh out a bit more of what it looks like in the new pass manager first. Differential Revision: http://reviews.llvm.org/D12080 llvm-svn: 247167
This commit is contained in:
parent
80595460d8
commit
7b560d40bd
@ -1,5 +1,4 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
@ -534,8 +533,6 @@ static void InitializeModuleAndPassManager() {
|
||||
// Create a new pass manager attached to it.
|
||||
TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
|
||||
|
||||
// Provide basic AliasAnalysis support for GVN.
|
||||
TheFPM->add(createBasicAliasAnalysisPass());
|
||||
// Do simple "peephole" optimizations and bit-twiddling optzns.
|
||||
TheFPM->add(createInstructionCombiningPass());
|
||||
// Reassociate expressions.
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
@ -808,8 +807,6 @@ static void InitializeModuleAndPassManager() {
|
||||
// Create a new pass manager attached to it.
|
||||
TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
|
||||
|
||||
// Provide basic AliasAnalysis support for GVN.
|
||||
TheFPM->add(createBasicAliasAnalysisPass());
|
||||
// Do simple "peephole" optimizations and bit-twiddling optzns.
|
||||
TheFPM->add(createInstructionCombiningPass());
|
||||
// Reassociate expressions.
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
@ -926,8 +925,6 @@ static void InitializeModuleAndPassManager() {
|
||||
// Create a new pass manager attached to it.
|
||||
TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
|
||||
|
||||
// Provide basic AliasAnalysis support for GVN.
|
||||
TheFPM->add(createBasicAliasAnalysisPass());
|
||||
// Do simple "peephole" optimizations and bit-twiddling optzns.
|
||||
TheFPM->add(createInstructionCombiningPass());
|
||||
// Reassociate expressions.
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
@ -1092,8 +1091,6 @@ static void InitializeModuleAndPassManager() {
|
||||
// Create a new pass manager attached to it.
|
||||
TheFPM = llvm::make_unique<legacy::FunctionPassManager>(TheModule.get());
|
||||
|
||||
// Provide basic AliasAnalysis support for GVN.
|
||||
TheFPM->add(createBasicAliasAnalysisPass());
|
||||
// Do simple "peephole" optimizations and bit-twiddling optzns.
|
||||
TheFPM->add(createInstructionCombiningPass());
|
||||
// Reassociate expressions.
|
||||
|
@ -41,10 +41,11 @@
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Analysis/MemoryLocation.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class BasicAAResult;
|
||||
class LoadInst;
|
||||
class StoreInst;
|
||||
class VAArgInst;
|
||||
@ -156,35 +157,22 @@ enum FunctionModRefBehavior {
|
||||
FMRB_UnknownModRefBehavior = FMRL_Anywhere | MRI_ModRef
|
||||
};
|
||||
|
||||
class AliasAnalysis {
|
||||
protected:
|
||||
const DataLayout *DL;
|
||||
const TargetLibraryInfo *TLI;
|
||||
|
||||
private:
|
||||
AliasAnalysis *AA; // Previous Alias Analysis to chain to.
|
||||
|
||||
protected:
|
||||
/// InitializeAliasAnalysis - Subclasses must call this method to initialize
|
||||
/// the AliasAnalysis interface before any other methods are called. This is
|
||||
/// typically called by the run* methods of these subclasses. This may be
|
||||
/// called multiple times.
|
||||
///
|
||||
void InitializeAliasAnalysis(Pass *P, const DataLayout *DL);
|
||||
|
||||
/// getAnalysisUsage - All alias analysis implementations should invoke this
|
||||
/// directly (using AliasAnalysis::getAnalysisUsage(AU)).
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
class AAResults {
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
AliasAnalysis() : DL(nullptr), TLI(nullptr), AA(nullptr) {}
|
||||
virtual ~AliasAnalysis(); // We want to be subclassed
|
||||
// Make these results default constructable and movable. We have to spell
|
||||
// these out because MSVC won't synthesize them.
|
||||
AAResults() {}
|
||||
AAResults(AAResults &&Arg);
|
||||
AAResults &operator=(AAResults &&Arg);
|
||||
~AAResults();
|
||||
|
||||
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
|
||||
/// object, or null if no TargetLibraryInfo object is available.
|
||||
///
|
||||
const TargetLibraryInfo *getTargetLibraryInfo() const { return TLI; }
|
||||
/// Register a specific AA result.
|
||||
template <typename AAResultT> void addAAResult(AAResultT &AAResult) {
|
||||
// FIXME: We should use a much lighter weight system than the usual
|
||||
// polymorphic pattern because we don't own AAResult. It should
|
||||
// ideally involve two pointers and no separate allocation.
|
||||
AAs.emplace_back(new Model<AAResultT>(AAResult, *this));
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// \name Alias Queries
|
||||
@ -194,8 +182,7 @@ public:
|
||||
/// Returns an AliasResult indicating whether the two pointers are aliased to
|
||||
/// each other. This is the interface that must be implemented by specific
|
||||
/// alias analysis implementations.
|
||||
virtual AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB);
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
|
||||
|
||||
/// A convenience wrapper around the primary \c alias interface.
|
||||
AliasResult alias(const Value *V1, uint64_t V1Size, const Value *V2,
|
||||
@ -239,8 +226,7 @@ public:
|
||||
|
||||
/// Checks whether the given location points to constant memory, or if
|
||||
/// \p OrLocal is true whether it points to a local alloca.
|
||||
virtual bool pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal = false);
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal = false);
|
||||
|
||||
/// A convenience wrapper around the primary \c pointsToConstantMemory
|
||||
/// interface.
|
||||
@ -258,13 +244,13 @@ public:
|
||||
/// that these bits do not necessarily account for the overall behavior of
|
||||
/// the function, but rather only provide additional per-argument
|
||||
/// information.
|
||||
virtual ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
|
||||
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
|
||||
|
||||
/// Return the behavior of the given call site.
|
||||
virtual FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||
|
||||
/// Return the behavior when calling the given function.
|
||||
virtual FunctionModRefBehavior getModRefBehavior(const Function *F);
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F);
|
||||
|
||||
/// Checks if the specified call is known to never read or write memory.
|
||||
///
|
||||
@ -344,8 +330,7 @@ public:
|
||||
|
||||
/// getModRefInfo (for call sites) - Return information about whether
|
||||
/// a particular call site modifies or reads the specified memory location.
|
||||
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc);
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
|
||||
|
||||
/// getModRefInfo (for call sites) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const Value *P,
|
||||
@ -494,8 +479,7 @@ public:
|
||||
/// Return information about whether two call sites may refer to the same set
|
||||
/// of memory locations. See the AA documentation for details:
|
||||
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
|
||||
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2);
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
|
||||
|
||||
/// \brief Return information about whether a particular call site modifies
|
||||
/// or reads the specified memory location \p MemLoc before instruction \p I
|
||||
@ -542,8 +526,403 @@ public:
|
||||
const ModRefInfo Mode) {
|
||||
return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode);
|
||||
}
|
||||
|
||||
private:
|
||||
class Concept;
|
||||
template <typename T> class Model;
|
||||
|
||||
template <typename T> friend class AAResultBase;
|
||||
|
||||
std::vector<std::unique_ptr<Concept>> AAs;
|
||||
};
|
||||
|
||||
/// Temporary typedef for legacy code that uses a generic \c AliasAnalysis
|
||||
/// pointer or reference.
|
||||
typedef AAResults AliasAnalysis;
|
||||
|
||||
/// A private abstract base class describing the concept of an individual alias
|
||||
/// analysis implementation.
|
||||
///
|
||||
/// This interface is implemented by any \c Model instantiation. It is also the
|
||||
/// interface which a type used to instantiate the model must provide.
|
||||
///
|
||||
/// All of these methods model methods by the same name in the \c
|
||||
/// AAResults class. Only differences and specifics to how the
|
||||
/// implementations are called are documented here.
|
||||
class AAResults::Concept {
|
||||
public:
|
||||
virtual ~Concept() = 0;
|
||||
|
||||
/// An update API used internally by the AAResults to provide
|
||||
/// a handle back to the top level aggregation.
|
||||
virtual void setAAResults(AAResults *NewAAR) = 0;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// \name Alias Queries
|
||||
/// @{
|
||||
|
||||
/// The main low level interface to the alias analysis implementation.
|
||||
/// Returns an AliasResult indicating whether the two pointers are aliased to
|
||||
/// each other. This is the interface that must be implemented by specific
|
||||
/// alias analysis implementations.
|
||||
virtual AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) = 0;
|
||||
|
||||
/// Checks whether the given location points to constant memory, or if
|
||||
/// \p OrLocal is true whether it points to a local alloca.
|
||||
virtual bool pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) = 0;
|
||||
|
||||
/// @}
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// \name Simple mod/ref information
|
||||
/// @{
|
||||
|
||||
/// Get the ModRef info associated with a pointer argument of a callsite. The
|
||||
/// result's bits are set to indicate the allowed aliasing ModRef kinds. Note
|
||||
/// that these bits do not necessarily account for the overall behavior of
|
||||
/// the function, but rather only provide additional per-argument
|
||||
/// information.
|
||||
virtual ModRefInfo getArgModRefInfo(ImmutableCallSite CS,
|
||||
unsigned ArgIdx) = 0;
|
||||
|
||||
/// Return the behavior of the given call site.
|
||||
virtual FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) = 0;
|
||||
|
||||
/// Return the behavior when calling the given function.
|
||||
virtual FunctionModRefBehavior getModRefBehavior(const Function *F) = 0;
|
||||
|
||||
/// getModRefInfo (for call sites) - Return information about whether
|
||||
/// a particular call site modifies or reads the specified memory location.
|
||||
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) = 0;
|
||||
|
||||
/// Return information about whether two call sites may refer to the same set
|
||||
/// of memory locations. See the AA documentation for details:
|
||||
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
|
||||
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) = 0;
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// A private class template which derives from \c Concept and wraps some other
|
||||
/// type.
|
||||
///
|
||||
/// This models the concept by directly forwarding each interface point to the
|
||||
/// wrapped type which must implement a compatible interface. This provides
|
||||
/// a type erased binding.
|
||||
template <typename AAResultT> class AAResults::Model final : public Concept {
|
||||
AAResultT &Result;
|
||||
|
||||
public:
|
||||
explicit Model(AAResultT &Result, AAResults &AAR) : Result(Result) {
|
||||
Result.setAAResults(&AAR);
|
||||
}
|
||||
~Model() override {}
|
||||
|
||||
void setAAResults(AAResults *NewAAR) override { Result.setAAResults(NewAAR); }
|
||||
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override {
|
||||
return Result.alias(LocA, LocB);
|
||||
}
|
||||
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) override {
|
||||
return Result.pointsToConstantMemory(Loc, OrLocal);
|
||||
}
|
||||
|
||||
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) override {
|
||||
return Result.getArgModRefInfo(CS, ArgIdx);
|
||||
}
|
||||
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override {
|
||||
return Result.getModRefBehavior(CS);
|
||||
}
|
||||
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F) override {
|
||||
return Result.getModRefBehavior(F);
|
||||
}
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) override {
|
||||
return Result.getModRefInfo(CS, Loc);
|
||||
}
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) override {
|
||||
return Result.getModRefInfo(CS1, CS2);
|
||||
}
|
||||
};
|
||||
|
||||
/// A CRTP-driven "mixin" base class to help implement the function alias
|
||||
/// analysis results concept.
|
||||
///
|
||||
/// Because of the nature of many alias analysis implementations, they often
|
||||
/// only implement a subset of the interface. This base class will attempt to
|
||||
/// implement the remaining portions of the interface in terms of simpler forms
|
||||
/// of the interface where possible, and otherwise provide conservatively
|
||||
/// correct fallback implementations.
|
||||
///
|
||||
/// Implementors of an alias analysis should derive from this CRTP, and then
|
||||
/// override specific methods that they wish to customize. There is no need to
|
||||
/// use virtual anywhere, the CRTP base class does static dispatch to the
|
||||
/// derived type passed into it.
|
||||
template <typename DerivedT> class AAResultBase {
|
||||
// Expose some parts of the interface only to the AAResults::Model
|
||||
// for wrapping. Specifically, this allows the model to call our
|
||||
// setAAResults method without exposing it as a fully public API.
|
||||
friend class AAResults::Model<DerivedT>;
|
||||
|
||||
/// A pointer to the AAResults object that this AAResult is
|
||||
/// aggregated within. May be null if not aggregated.
|
||||
AAResults *AAR;
|
||||
|
||||
/// Helper to dispatch calls back through the derived type.
|
||||
DerivedT &derived() { return static_cast<DerivedT &>(*this); }
|
||||
|
||||
/// A setter for the AAResults pointer, which is used to satisfy the
|
||||
/// AAResults::Model contract.
|
||||
void setAAResults(AAResults *NewAAR) { AAR = NewAAR; }
|
||||
|
||||
protected:
|
||||
/// This proxy class models a common pattern where we delegate to either the
|
||||
/// top-level \c AAResults aggregation if one is registered, or to the
|
||||
/// current result if none are registered.
|
||||
class AAResultsProxy {
|
||||
AAResults *AAR;
|
||||
DerivedT &CurrentResult;
|
||||
|
||||
public:
|
||||
AAResultsProxy(AAResults *AAR, DerivedT &CurrentResult)
|
||||
: AAR(AAR), CurrentResult(CurrentResult) {}
|
||||
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
|
||||
return AAR ? AAR->alias(LocA, LocB) : CurrentResult.alias(LocA, LocB);
|
||||
}
|
||||
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) {
|
||||
return AAR ? AAR->pointsToConstantMemory(Loc, OrLocal)
|
||||
: CurrentResult.pointsToConstantMemory(Loc, OrLocal);
|
||||
}
|
||||
|
||||
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) {
|
||||
return AAR ? AAR->getArgModRefInfo(CS, ArgIdx) : CurrentResult.getArgModRefInfo(CS, ArgIdx);
|
||||
}
|
||||
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) {
|
||||
return AAR ? AAR->getModRefBehavior(CS) : CurrentResult.getModRefBehavior(CS);
|
||||
}
|
||||
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F) {
|
||||
return AAR ? AAR->getModRefBehavior(F) : CurrentResult.getModRefBehavior(F);
|
||||
}
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc) {
|
||||
return AAR ? AAR->getModRefInfo(CS, Loc)
|
||||
: CurrentResult.getModRefInfo(CS, Loc);
|
||||
}
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2) {
|
||||
return AAR ? AAR->getModRefInfo(CS1, CS2) : CurrentResult.getModRefInfo(CS1, CS2);
|
||||
}
|
||||
};
|
||||
|
||||
const TargetLibraryInfo &TLI;
|
||||
|
||||
explicit AAResultBase(const TargetLibraryInfo &TLI) : TLI(TLI) {}
|
||||
|
||||
// Provide all the copy and move constructors so that derived types aren't
|
||||
// constrained.
|
||||
AAResultBase(const AAResultBase &Arg) : TLI(Arg.TLI) {}
|
||||
AAResultBase(AAResultBase &&Arg) : TLI(Arg.TLI) {}
|
||||
|
||||
/// Get a proxy for the best AA result set to query at this time.
|
||||
///
|
||||
/// When this result is part of a larger aggregation, this will proxy to that
|
||||
/// aggregation. When this result is used in isolation, it will just delegate
|
||||
/// back to the derived class's implementation.
|
||||
AAResultsProxy getBestAAResults() { return AAResultsProxy(AAR, derived()); }
|
||||
|
||||
public:
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
|
||||
return MayAlias;
|
||||
}
|
||||
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) {
|
||||
return MRI_ModRef;
|
||||
}
|
||||
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) {
|
||||
if (const Function *F = CS.getCalledFunction())
|
||||
return getBestAAResults().getModRefBehavior(F);
|
||||
|
||||
return FMRB_UnknownModRefBehavior;
|
||||
}
|
||||
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F) {
|
||||
return FMRB_UnknownModRefBehavior;
|
||||
}
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
|
||||
};
|
||||
|
||||
/// Synthesize \c ModRefInfo for a call site and memory location by examining
|
||||
/// the general behavior of the call site and any specific information for its
|
||||
/// arguments.
|
||||
///
|
||||
/// This essentially, delegates across the alias analysis interface to collect
|
||||
/// information which may be enough to (conservatively) fulfill the query.
|
||||
template <typename DerivedT>
|
||||
ModRefInfo AAResultBase<DerivedT>::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
auto MRB = getBestAAResults().getModRefBehavior(CS);
|
||||
if (MRB == FMRB_DoesNotAccessMemory)
|
||||
return MRI_NoModRef;
|
||||
|
||||
ModRefInfo Mask = MRI_ModRef;
|
||||
if (AAResults::onlyReadsMemory(MRB))
|
||||
Mask = MRI_Ref;
|
||||
|
||||
if (AAResults::onlyAccessesArgPointees(MRB)) {
|
||||
bool DoesAlias = false;
|
||||
ModRefInfo AllArgsMask = MRI_NoModRef;
|
||||
if (AAResults::doesAccessArgPointees(MRB)) {
|
||||
for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(),
|
||||
AE = CS.arg_end();
|
||||
AI != AE; ++AI) {
|
||||
const Value *Arg = *AI;
|
||||
if (!Arg->getType()->isPointerTy())
|
||||
continue;
|
||||
unsigned ArgIdx = std::distance(CS.arg_begin(), AI);
|
||||
MemoryLocation ArgLoc = MemoryLocation::getForArgument(CS, ArgIdx, TLI);
|
||||
AliasResult ArgAlias = getBestAAResults().alias(ArgLoc, Loc);
|
||||
if (ArgAlias != NoAlias) {
|
||||
ModRefInfo ArgMask = getBestAAResults().getArgModRefInfo(CS, ArgIdx);
|
||||
DoesAlias = true;
|
||||
AllArgsMask = ModRefInfo(AllArgsMask | ArgMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!DoesAlias)
|
||||
return MRI_NoModRef;
|
||||
Mask = ModRefInfo(Mask & AllArgsMask);
|
||||
}
|
||||
|
||||
// If Loc is a constant memory location, the call definitely could not
|
||||
// modify the memory location.
|
||||
if ((Mask & MRI_Mod) &&
|
||||
getBestAAResults().pointsToConstantMemory(Loc, /*OrLocal*/ false))
|
||||
Mask = ModRefInfo(Mask & ~MRI_Mod);
|
||||
|
||||
return Mask;
|
||||
}
|
||||
|
||||
/// Synthesize \c ModRefInfo for two call sites by examining the general
|
||||
/// behavior of the call site and any specific information for its arguments.
|
||||
///
|
||||
/// This essentially, delegates across the alias analysis interface to collect
|
||||
/// information which may be enough to (conservatively) fulfill the query.
|
||||
template <typename DerivedT>
|
||||
ModRefInfo AAResultBase<DerivedT>::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
// If CS1 or CS2 are readnone, they don't interact.
|
||||
auto CS1B = getBestAAResults().getModRefBehavior(CS1);
|
||||
if (CS1B == FMRB_DoesNotAccessMemory)
|
||||
return MRI_NoModRef;
|
||||
|
||||
auto CS2B = getBestAAResults().getModRefBehavior(CS2);
|
||||
if (CS2B == FMRB_DoesNotAccessMemory)
|
||||
return MRI_NoModRef;
|
||||
|
||||
// If they both only read from memory, there is no dependence.
|
||||
if (AAResults::onlyReadsMemory(CS1B) && AAResults::onlyReadsMemory(CS2B))
|
||||
return MRI_NoModRef;
|
||||
|
||||
ModRefInfo Mask = MRI_ModRef;
|
||||
|
||||
// If CS1 only reads memory, the only dependence on CS2 can be
|
||||
// from CS1 reading memory written by CS2.
|
||||
if (AAResults::onlyReadsMemory(CS1B))
|
||||
Mask = ModRefInfo(Mask & MRI_Ref);
|
||||
|
||||
// If CS2 only access memory through arguments, accumulate the mod/ref
|
||||
// information from CS1's references to the memory referenced by
|
||||
// CS2's arguments.
|
||||
if (AAResults::onlyAccessesArgPointees(CS2B)) {
|
||||
ModRefInfo R = MRI_NoModRef;
|
||||
if (AAResults::doesAccessArgPointees(CS2B)) {
|
||||
for (ImmutableCallSite::arg_iterator I = CS2.arg_begin(),
|
||||
E = CS2.arg_end();
|
||||
I != E; ++I) {
|
||||
const Value *Arg = *I;
|
||||
if (!Arg->getType()->isPointerTy())
|
||||
continue;
|
||||
unsigned CS2ArgIdx = std::distance(CS2.arg_begin(), I);
|
||||
auto CS2ArgLoc = MemoryLocation::getForArgument(CS2, CS2ArgIdx, TLI);
|
||||
|
||||
// ArgMask indicates what CS2 might do to CS2ArgLoc, and the dependence
|
||||
// of CS1 on that location is the inverse.
|
||||
ModRefInfo ArgMask =
|
||||
getBestAAResults().getArgModRefInfo(CS2, CS2ArgIdx);
|
||||
if (ArgMask == MRI_Mod)
|
||||
ArgMask = MRI_ModRef;
|
||||
else if (ArgMask == MRI_Ref)
|
||||
ArgMask = MRI_Mod;
|
||||
|
||||
ArgMask = ModRefInfo(ArgMask &
|
||||
getBestAAResults().getModRefInfo(CS1, CS2ArgLoc));
|
||||
|
||||
R = ModRefInfo((R | ArgMask) & Mask);
|
||||
if (R == Mask)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return R;
|
||||
}
|
||||
|
||||
// If CS1 only accesses memory through arguments, check if CS2 references
|
||||
// any of the memory referenced by CS1's arguments. If not, return NoModRef.
|
||||
if (AAResults::onlyAccessesArgPointees(CS1B)) {
|
||||
ModRefInfo R = MRI_NoModRef;
|
||||
if (AAResults::doesAccessArgPointees(CS1B)) {
|
||||
for (ImmutableCallSite::arg_iterator I = CS1.arg_begin(),
|
||||
E = CS1.arg_end();
|
||||
I != E; ++I) {
|
||||
const Value *Arg = *I;
|
||||
if (!Arg->getType()->isPointerTy())
|
||||
continue;
|
||||
unsigned CS1ArgIdx = std::distance(CS1.arg_begin(), I);
|
||||
auto CS1ArgLoc = MemoryLocation::getForArgument(CS1, CS1ArgIdx, TLI);
|
||||
|
||||
// ArgMask indicates what CS1 might do to CS1ArgLoc; if CS1 might Mod
|
||||
// CS1ArgLoc, then we care about either a Mod or a Ref by CS2. If CS1
|
||||
// might Ref, then we care only about a Mod by CS2.
|
||||
ModRefInfo ArgMask = getBestAAResults().getArgModRefInfo(CS1, CS1ArgIdx);
|
||||
ModRefInfo ArgR = getBestAAResults().getModRefInfo(CS2, CS1ArgLoc);
|
||||
if (((ArgMask & MRI_Mod) != MRI_NoModRef &&
|
||||
(ArgR & MRI_ModRef) != MRI_NoModRef) ||
|
||||
((ArgMask & MRI_Ref) != MRI_NoModRef &&
|
||||
(ArgR & MRI_Mod) != MRI_NoModRef))
|
||||
R = ModRefInfo((R | ArgMask) & Mask);
|
||||
|
||||
if (R == Mask)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return R;
|
||||
}
|
||||
|
||||
return Mask;
|
||||
}
|
||||
|
||||
/// isNoAliasCall - Return true if this pointer is returned by a noalias
|
||||
/// function.
|
||||
bool isNoAliasCall(const Value *V);
|
||||
@ -568,6 +947,88 @@ bool isIdentifiedObject(const Value *V);
|
||||
/// IdentifiedObjects.
|
||||
bool isIdentifiedFunctionLocal(const Value *V);
|
||||
|
||||
/// A manager for alias analyses.
|
||||
///
|
||||
/// This class can have analyses registered with it and when run, it will run
|
||||
/// all of them and aggregate their results into single AA results interface
|
||||
/// that dispatches across all of the alias analysis results available.
|
||||
///
|
||||
/// Note that the order in which analyses are registered is very significant.
|
||||
/// That is the order in which the results will be aggregated and queried.
|
||||
///
|
||||
/// This manager effectively wraps the AnalysisManager for registering alias
|
||||
/// analyses. When you register your alias analysis with this manager, it will
|
||||
/// ensure the analysis itself is registered with its AnalysisManager.
|
||||
class AAManager {
|
||||
public:
|
||||
typedef AAResults Result;
|
||||
|
||||
// This type hase value semantics. We have to spell these out because MSVC
|
||||
// won't synthesize them.
|
||||
AAManager() {}
|
||||
AAManager(AAManager &&Arg)
|
||||
: FunctionResultGetters(std::move(Arg.FunctionResultGetters)) {}
|
||||
AAManager(const AAManager &Arg)
|
||||
: FunctionResultGetters(Arg.FunctionResultGetters) {}
|
||||
AAManager &operator=(AAManager &&RHS) {
|
||||
FunctionResultGetters = std::move(RHS.FunctionResultGetters);
|
||||
return *this;
|
||||
}
|
||||
AAManager &operator=(const AAManager &RHS) {
|
||||
FunctionResultGetters = RHS.FunctionResultGetters;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Register a specific AA result.
|
||||
template <typename AnalysisT> void registerFunctionAnalysis() {
|
||||
FunctionResultGetters.push_back(&getFunctionAAResultImpl<AnalysisT>);
|
||||
}
|
||||
|
||||
Result run(Function &F, AnalysisManager<Function> &AM) {
|
||||
Result R;
|
||||
for (auto &Getter : FunctionResultGetters)
|
||||
(*Getter)(F, AM, R);
|
||||
return R;
|
||||
}
|
||||
|
||||
private:
|
||||
SmallVector<void (*)(Function &F, AnalysisManager<Function> &AM,
|
||||
AAResults &AAResults),
|
||||
4> FunctionResultGetters;
|
||||
|
||||
template <typename AnalysisT>
|
||||
static void getFunctionAAResultImpl(Function &F,
|
||||
AnalysisManager<Function> &AM,
|
||||
AAResults &AAResults) {
|
||||
AAResults.addAAResult(AM.template getResult<AnalysisT>(F));
|
||||
}
|
||||
};
|
||||
|
||||
/// A wrapper pass to provide the legacy pass manager access to a suitably
|
||||
/// prepared AAResults object.
|
||||
class AAResultsWrapperPass : public FunctionPass {
|
||||
std::unique_ptr<AAResults> AAR;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
AAResultsWrapperPass();
|
||||
|
||||
AAResults &getAAResults() { return *AAR; }
|
||||
const AAResults &getAAResults() const { return *AAR; }
|
||||
|
||||
bool runOnFunction(Function &F) override;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
};
|
||||
|
||||
FunctionPass *createAAResultsWrapperPass();
|
||||
|
||||
/// A helper for the legacy pass manager to create a \c AAResults
|
||||
/// object populated to the best of our ability for a particular function when
|
||||
/// inside of a \c ModulePass or a \c CallGraphSCCPass.
|
||||
AAResults createLegacyPMAAResults(Pass &P, Function &F, BasicAAResult &BAR);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -1,65 +0,0 @@
|
||||
//===- AliasAnalysisCounter.h - Alias Analysis Query Counter ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// This declares an alias analysis which counts and prints queries made
|
||||
/// through it. By inserting this between other AAs you can track when specific
|
||||
/// layers of LLVM's AA get queried.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_ALIASANALYSISCOUNTER_H
|
||||
#define LLVM_ANALYSIS_ALIASANALYSISCOUNTER_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysisCounter : public ModulePass, public AliasAnalysis {
|
||||
unsigned No, May, Partial, Must;
|
||||
unsigned NoMR, JustRef, JustMod, MR;
|
||||
Module *M;
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
|
||||
AliasAnalysisCounter();
|
||||
~AliasAnalysisCounter() override;
|
||||
|
||||
bool runOnModule(Module &M) override;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
|
||||
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
||||
/// an analysis interface through multiple inheritance. If needed, it
|
||||
/// should override this to adjust the this pointer as needed for the
|
||||
/// specified pass info.
|
||||
void *getAdjustedAnalysisPointer(AnalysisID PI) override;
|
||||
|
||||
// Forwarding functions: just delegate to a real AA implementation, counting
|
||||
// the number of responses...
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override;
|
||||
|
||||
using AliasAnalysis::getModRefInfo;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) override;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createAliasAnalysisCounterPass - This pass counts alias queries and how the
|
||||
// alias analysis implementation responds.
|
||||
//
|
||||
ModulePass *createAliasAnalysisCounterPass();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -20,13 +20,13 @@
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/ValueHandle.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class LoadInst;
|
||||
class StoreInst;
|
||||
class VAArgInst;
|
||||
|
@ -23,14 +23,26 @@
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
namespace llvm {
|
||||
class AssumptionCache;
|
||||
class DominatorTree;
|
||||
class LoopInfo;
|
||||
|
||||
/// This is the primary alias analysis implementation.
|
||||
struct BasicAliasAnalysis : public ImmutablePass, public AliasAnalysis {
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
/// This is the AA result object for the basic, local, and stateless alias
|
||||
/// analysis. It implements the AA query interface in an entirely stateless
|
||||
/// manner. As one consequence, it is never invalidated. While it does retain
|
||||
/// some storage, that is used as an optimization and not to preserve
|
||||
/// information from query to query.
|
||||
class BasicAAResult : public AAResultBase<BasicAAResult> {
|
||||
friend AAResultBase<BasicAAResult>;
|
||||
|
||||
const DataLayout &DL;
|
||||
AssumptionCache &AC;
|
||||
DominatorTree *DT;
|
||||
LoopInfo *LI;
|
||||
|
||||
#ifndef NDEBUG
|
||||
static const Function *getParent(const Value *V) {
|
||||
@ -52,23 +64,34 @@ struct BasicAliasAnalysis : public ImmutablePass, public AliasAnalysis {
|
||||
}
|
||||
#endif
|
||||
|
||||
BasicAliasAnalysis() : ImmutablePass(ID) {
|
||||
initializeBasicAliasAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
public:
|
||||
BasicAAResult(const DataLayout &DL, const TargetLibraryInfo &TLI,
|
||||
AssumptionCache &AC, DominatorTree *DT = nullptr,
|
||||
LoopInfo *LI = nullptr)
|
||||
: AAResultBase(TLI), DL(DL), AC(AC), DT(DT), LI(LI) {}
|
||||
|
||||
bool doInitialization(Module &M) override;
|
||||
BasicAAResult(const BasicAAResult &Arg)
|
||||
: AAResultBase(Arg), DL(Arg.DL), AC(Arg.AC), DT(Arg.DT), LI(Arg.LI) {}
|
||||
BasicAAResult(BasicAAResult &&Arg)
|
||||
: AAResultBase(std::move(Arg)), DL(Arg.DL), AC(Arg.AC), DT(Arg.DT),
|
||||
LI(Arg.LI) {}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
/// Handle invalidation events from the new pass manager.
|
||||
///
|
||||
/// By definition, this result is stateless and so remains valid.
|
||||
bool invalidate(Function &, const PreservedAnalyses &) { return false; }
|
||||
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override {
|
||||
assert(AliasCache.empty() && "AliasCache must be cleared after use!");
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
|
||||
assert(notDifferentParent(LocA.Ptr, LocB.Ptr) &&
|
||||
"BasicAliasAnalysis doesn't support interprocedural queries.");
|
||||
|
||||
// If we have a directly cached entry for these locations, we have recursed
|
||||
// through this once, so just return the cached results. Notably, when this
|
||||
// happens, we don't clear the cache.
|
||||
auto CacheIt = AliasCache.find(LocPair(LocA, LocB));
|
||||
if (CacheIt != AliasCache.end())
|
||||
return CacheIt->second;
|
||||
|
||||
AliasResult Alias = aliasCheck(LocA.Ptr, LocA.Size, LocA.AATags, LocB.Ptr,
|
||||
LocB.Size, LocB.AATags);
|
||||
// AliasCache rarely has more than 1 or 2 elements, always use
|
||||
@ -80,33 +103,22 @@ struct BasicAliasAnalysis : public ImmutablePass, public AliasAnalysis {
|
||||
return Alias;
|
||||
}
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) override;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) override;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
|
||||
|
||||
/// Chases pointers until we find a (constant global) or not.
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) override;
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal);
|
||||
|
||||
/// Get the location associated with a pointer argument of a callsite.
|
||||
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) override;
|
||||
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
|
||||
|
||||
/// Returns the behavior when calling the given call site.
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override;
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||
|
||||
/// Returns the behavior when calling the given function. For use when the
|
||||
/// call site is not known.
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F) override;
|
||||
|
||||
/// This method is used when a pass implements an analysis interface through
|
||||
/// multiple inheritance. If needed, it should override this to adjust the
|
||||
/// this pointer as needed for the specified pass info.
|
||||
void *getAdjustedAnalysisPointer(const void *ID) override {
|
||||
if (ID == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis *)this;
|
||||
return this;
|
||||
}
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F);
|
||||
|
||||
private:
|
||||
// A linear transformation of a Value; this class represents ZExt(SExt(V,
|
||||
@ -181,8 +193,7 @@ private:
|
||||
bool
|
||||
constantOffsetHeuristic(const SmallVectorImpl<VariableGEPIndex> &VarIndices,
|
||||
uint64_t V1Size, uint64_t V2Size, int64_t BaseOffset,
|
||||
const DataLayout *DL, AssumptionCache *AC,
|
||||
DominatorTree *DT);
|
||||
AssumptionCache *AC, DominatorTree *DT);
|
||||
|
||||
bool isValueEqualInPotentialCycles(const Value *V1, const Value *V2);
|
||||
|
||||
@ -206,13 +217,47 @@ private:
|
||||
const Value *V2, uint64_t V2Size, AAMDNodes V2AATag);
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createBasicAliasAnalysisPass - This pass implements the stateless alias
|
||||
// analysis.
|
||||
//
|
||||
ImmutablePass *createBasicAliasAnalysisPass();
|
||||
/// Analysis pass providing a never-invalidated alias analysis result.
|
||||
class BasicAA {
|
||||
public:
|
||||
typedef BasicAAResult Result;
|
||||
|
||||
/// \brief Opaque, unique identifier for this analysis pass.
|
||||
static void *ID() { return (void *)&PassID; }
|
||||
|
||||
BasicAAResult run(Function &F, AnalysisManager<Function> *AM);
|
||||
|
||||
/// \brief Provide access to a name for this pass for debugging purposes.
|
||||
static StringRef name() { return "BasicAliasAnalysis"; }
|
||||
|
||||
private:
|
||||
static char PassID;
|
||||
};
|
||||
|
||||
/// Legacy wrapper pass to provide the BasicAAResult object.
|
||||
class BasicAAWrapperPass : public FunctionPass {
|
||||
std::unique_ptr<BasicAAResult> Result;
|
||||
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BasicAAWrapperPass() : FunctionPass(ID) {}
|
||||
|
||||
BasicAAResult &getResult() { return *Result; }
|
||||
const BasicAAResult &getResult() const { return *Result; }
|
||||
|
||||
bool runOnFunction(Function &F) override;
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
};
|
||||
|
||||
FunctionPass *createBasicAAWrapperPass();
|
||||
|
||||
/// A helper for the legacy pass manager to create a \c BasicAAResult object
|
||||
/// populated to the best of our ability for a particular function when inside
|
||||
/// of a \c ModulePass or a \c CallGraphSCCPass.
|
||||
BasicAAResult createLegacyPMBasicAAResult(Pass &P, Function &F);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -26,47 +26,19 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class CFLAliasAnalysis : public ImmutablePass, public AliasAnalysis {
|
||||
class CFLAAResult : public AAResultBase<CFLAAResult> {
|
||||
friend AAResultBase<CFLAAResult>;
|
||||
|
||||
struct FunctionInfo;
|
||||
|
||||
struct FunctionHandle final : public CallbackVH {
|
||||
FunctionHandle(Function *Fn, CFLAliasAnalysis *CFLAA)
|
||||
: CallbackVH(Fn), CFLAA(CFLAA) {
|
||||
assert(Fn != nullptr);
|
||||
assert(CFLAA != nullptr);
|
||||
}
|
||||
|
||||
void deleted() override { removeSelfFromCache(); }
|
||||
void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
|
||||
|
||||
private:
|
||||
CFLAliasAnalysis *CFLAA;
|
||||
|
||||
void removeSelfFromCache() {
|
||||
assert(CFLAA != nullptr);
|
||||
auto *Val = getValPtr();
|
||||
CFLAA->evict(cast<Function>(Val));
|
||||
setValPtr(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Cached mapping of Functions to their StratifiedSets.
|
||||
/// If a function's sets are currently being built, it is marked
|
||||
/// in the cache as an Optional without a value. This way, if we
|
||||
/// have any kind of recursion, it is discernable from a function
|
||||
/// that simply has empty sets.
|
||||
DenseMap<Function *, Optional<FunctionInfo>> Cache;
|
||||
std::forward_list<FunctionHandle> Handles;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
explicit CFLAAResult(const TargetLibraryInfo &TLI);
|
||||
CFLAAResult(CFLAAResult &&Arg);
|
||||
|
||||
CFLAliasAnalysis();
|
||||
~CFLAliasAnalysis() override;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
|
||||
void *getAdjustedAnalysisPointer(const void *ID) override;
|
||||
/// Handle invalidation events from the new pass manager.
|
||||
///
|
||||
/// By definition, this result is stateless and so remains valid.
|
||||
bool invalidate(Function &, const PreservedAnalyses &) { return false; }
|
||||
|
||||
/// \brief Inserts the given Function into the cache.
|
||||
void scan(Function *Fn);
|
||||
@ -79,8 +51,7 @@ public:
|
||||
|
||||
AliasResult query(const MemoryLocation &LocA, const MemoryLocation &LocB);
|
||||
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override {
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
|
||||
if (LocA.Ptr == LocB.Ptr) {
|
||||
if (LocA.Size == LocB.Size) {
|
||||
return MustAlias;
|
||||
@ -96,29 +67,92 @@ public:
|
||||
// one Value tied to a Function, and neither GlobalValues nor ConstantExprs
|
||||
// are.
|
||||
if (isa<Constant>(LocA.Ptr) && isa<Constant>(LocB.Ptr)) {
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
}
|
||||
|
||||
AliasResult QueryResult = query(LocA, LocB);
|
||||
if (QueryResult == MayAlias)
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
|
||||
return QueryResult;
|
||||
}
|
||||
|
||||
bool doInitialization(Module &M) override;
|
||||
private:
|
||||
struct FunctionHandle final : public CallbackVH {
|
||||
FunctionHandle(Function *Fn, CFLAAResult *Result)
|
||||
: CallbackVH(Fn), Result(Result) {
|
||||
assert(Fn != nullptr);
|
||||
assert(Result != nullptr);
|
||||
}
|
||||
|
||||
void deleted() override { removeSelfFromCache(); }
|
||||
void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
|
||||
|
||||
private:
|
||||
CFLAAResult *Result;
|
||||
|
||||
void removeSelfFromCache() {
|
||||
assert(Result != nullptr);
|
||||
auto *Val = getValPtr();
|
||||
Result->evict(cast<Function>(Val));
|
||||
setValPtr(nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
/// \brief Cached mapping of Functions to their StratifiedSets.
|
||||
/// If a function's sets are currently being built, it is marked
|
||||
/// in the cache as an Optional without a value. This way, if we
|
||||
/// have any kind of recursion, it is discernable from a function
|
||||
/// that simply has empty sets.
|
||||
DenseMap<Function *, Optional<FunctionInfo>> Cache;
|
||||
std::forward_list<FunctionHandle> Handles;
|
||||
|
||||
FunctionInfo buildSetsFrom(Function *F);
|
||||
};
|
||||
|
||||
/// Analysis pass providing a never-invalidated alias analysis result.
|
||||
///
|
||||
/// FIXME: We really should refactor CFL to use the analysis more heavily, and
|
||||
/// in particular to leverage invalidation to trigger re-computation of sets.
|
||||
class CFLAA {
|
||||
public:
|
||||
typedef CFLAAResult Result;
|
||||
|
||||
/// \brief Opaque, unique identifier for this analysis pass.
|
||||
static void *ID() { return (void *)&PassID; }
|
||||
|
||||
CFLAAResult run(Function &F, AnalysisManager<Function> *AM);
|
||||
|
||||
/// \brief Provide access to a name for this pass for debugging purposes.
|
||||
static StringRef name() { return "CFLAA"; }
|
||||
|
||||
private:
|
||||
FunctionInfo buildSetsFrom(Function *F);
|
||||
static char PassID;
|
||||
};
|
||||
|
||||
/// Legacy wrapper pass to provide the CFLAAResult object.
|
||||
class CFLAAWrapperPass : public ImmutablePass {
|
||||
std::unique_ptr<CFLAAResult> Result;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
CFLAAWrapperPass();
|
||||
|
||||
CFLAAResult &getResult() { return *Result; }
|
||||
const CFLAAResult &getResult() const { return *Result; }
|
||||
|
||||
bool doInitialization(Module &M) override;
|
||||
bool doFinalization(Module &M) override;
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createCFLAliasAnalysisPass - This pass implements a set-based approach to
|
||||
// createCFLAAWrapperPass - This pass implements a set-based approach to
|
||||
// alias analysis.
|
||||
//
|
||||
ImmutablePass *createCFLAliasAnalysisPass();
|
||||
|
||||
ImmutablePass *createCFLAAWrapperPass();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -42,11 +42,11 @@
|
||||
|
||||
#include "llvm/ADT/SmallBitVector.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
class AliasAnalysis;
|
||||
class Loop;
|
||||
class LoopInfo;
|
||||
class ScalarEvolution;
|
||||
|
@ -25,10 +25,17 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// GlobalsModRef - The actual analysis pass.
|
||||
class GlobalsModRef : public ModulePass, public AliasAnalysis {
|
||||
/// An alias analysis result set for globals.
|
||||
///
|
||||
/// This focuses on handling aliasing properties of globals and interprocedural
|
||||
/// function call mod/ref information.
|
||||
class GlobalsAAResult : public AAResultBase<GlobalsAAResult> {
|
||||
friend AAResultBase<GlobalsAAResult>;
|
||||
|
||||
class FunctionInfo;
|
||||
|
||||
const DataLayout &DL;
|
||||
|
||||
/// The globals that do not have their addresses taken.
|
||||
SmallPtrSet<const GlobalValue *, 8> NonAddressTakenGlobals;
|
||||
|
||||
@ -45,11 +52,11 @@ class GlobalsModRef : public ModulePass, public AliasAnalysis {
|
||||
|
||||
/// Handle to clear this analysis on deletion of values.
|
||||
struct DeletionCallbackHandle final : CallbackVH {
|
||||
GlobalsModRef &GMR;
|
||||
GlobalsAAResult &GAR;
|
||||
std::list<DeletionCallbackHandle>::iterator I;
|
||||
|
||||
DeletionCallbackHandle(GlobalsModRef &GMR, Value *V)
|
||||
: CallbackVH(V), GMR(GMR) {}
|
||||
DeletionCallbackHandle(GlobalsAAResult &GAR, Value *V)
|
||||
: CallbackVH(V), GAR(GAR) {}
|
||||
|
||||
void deleted() override;
|
||||
};
|
||||
@ -60,56 +67,31 @@ class GlobalsModRef : public ModulePass, public AliasAnalysis {
|
||||
/// could perform to the memory utilization here if this becomes a problem.
|
||||
std::list<DeletionCallbackHandle> Handles;
|
||||
|
||||
explicit GlobalsAAResult(const DataLayout &DL, const TargetLibraryInfo &TLI);
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
GlobalsModRef();
|
||||
GlobalsAAResult(GlobalsAAResult &&Arg);
|
||||
|
||||
bool runOnModule(Module &M) override {
|
||||
InitializeAliasAnalysis(this, &M.getDataLayout());
|
||||
|
||||
// Find non-addr taken globals.
|
||||
AnalyzeGlobals(M);
|
||||
|
||||
// Propagate on CG.
|
||||
AnalyzeCallGraph(getAnalysis<CallGraphWrapperPass>().getCallGraph(), M);
|
||||
return false;
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AliasAnalysis::getAnalysisUsage(AU);
|
||||
AU.addRequired<CallGraphWrapperPass>();
|
||||
AU.setPreservesAll(); // Does not transform code
|
||||
}
|
||||
|
||||
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
||||
/// an analysis interface through multiple inheritance. If needed, it
|
||||
/// should override this to adjust the this pointer as needed for the
|
||||
/// specified pass info.
|
||||
void *getAdjustedAnalysisPointer(AnalysisID PI) override {
|
||||
if (PI == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis *)this;
|
||||
return this;
|
||||
}
|
||||
static GlobalsAAResult analyzeModule(Module &M, const TargetLibraryInfo &TLI,
|
||||
CallGraph &CG);
|
||||
|
||||
//------------------------------------------------
|
||||
// Implement the AliasAnalysis API
|
||||
//
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override;
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
|
||||
|
||||
using AliasAnalysis::getModRefInfo;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) override;
|
||||
using AAResultBase::getModRefInfo;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
|
||||
|
||||
/// getModRefBehavior - Return the behavior of the specified function if
|
||||
/// called from the specified call site. The call site may be null in which
|
||||
/// case the most generic behavior of this function should be returned.
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F) override;
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F);
|
||||
|
||||
/// getModRefBehavior - Return the behavior of the specified function if
|
||||
/// called from the specified call site. The call site may be null in which
|
||||
/// case the most generic behavior of this function should be returned.
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override;
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||
|
||||
private:
|
||||
FunctionInfo *getFunctionInfo(const Function *F);
|
||||
@ -125,13 +107,46 @@ private:
|
||||
bool isNonEscapingGlobalNoAlias(const GlobalValue *GV, const Value *V);
|
||||
};
|
||||
|
||||
/// Analysis pass providing a never-invalidated alias analysis result.
|
||||
class GlobalsAA {
|
||||
public:
|
||||
typedef GlobalsAAResult Result;
|
||||
|
||||
/// \brief Opaque, unique identifier for this analysis pass.
|
||||
static void *ID() { return (void *)&PassID; }
|
||||
|
||||
GlobalsAAResult run(Module &M, AnalysisManager<Module> *AM);
|
||||
|
||||
/// \brief Provide access to a name for this pass for debugging purposes.
|
||||
static StringRef name() { return "GlobalsAA"; }
|
||||
|
||||
private:
|
||||
static char PassID;
|
||||
};
|
||||
|
||||
/// Legacy wrapper pass to provide the GlobalsAAResult object.
|
||||
class GlobalsAAWrapperPass : public ModulePass {
|
||||
std::unique_ptr<GlobalsAAResult> Result;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
GlobalsAAWrapperPass();
|
||||
|
||||
GlobalsAAResult &getResult() { return *Result; }
|
||||
const GlobalsAAResult &getResult() const { return *Result; }
|
||||
|
||||
bool runOnModule(Module &M) override;
|
||||
bool doFinalization(Module &M) override;
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createGlobalsModRefPass - This pass provides alias and mod/ref info for
|
||||
// createGlobalsAAWrapperPass - This pass provides alias and mod/ref info for
|
||||
// global values that do not have their addresses taken.
|
||||
//
|
||||
Pass *createGlobalsModRefPass();
|
||||
|
||||
ModulePass *createGlobalsAAWrapperPass();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -14,11 +14,11 @@
|
||||
#ifndef LLVM_ANALYSIS_LOADS_H
|
||||
#define LLVM_ANALYSIS_LOADS_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class DataLayout;
|
||||
class MDNode;
|
||||
|
||||
|
@ -29,7 +29,6 @@ namespace llvm {
|
||||
|
||||
class Value;
|
||||
class DataLayout;
|
||||
class AliasAnalysis;
|
||||
class ScalarEvolution;
|
||||
class Loop;
|
||||
class SCEV;
|
||||
|
@ -28,7 +28,6 @@ namespace llvm {
|
||||
class FunctionPass;
|
||||
class Instruction;
|
||||
class CallSite;
|
||||
class AliasAnalysis;
|
||||
class AssumptionCache;
|
||||
class MemoryDependenceAnalysis;
|
||||
class PredIteratorCache;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define LLVM_ANALYSIS_OBJCARCALIASANALYSIS_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Pass.h"
|
||||
|
||||
namespace llvm {
|
||||
@ -35,35 +36,64 @@ namespace objcarc {
|
||||
/// TODO: This class could be generalized to know about other ObjC-specific
|
||||
/// tricks. Such as knowing that ivars in the non-fragile ABI are non-aliasing
|
||||
/// even though their offsets are dynamic.
|
||||
class ObjCARCAliasAnalysis : public ImmutablePass, public AliasAnalysis {
|
||||
class ObjCARCAAResult : public AAResultBase<ObjCARCAAResult> {
|
||||
friend AAResultBase<ObjCARCAAResult>;
|
||||
|
||||
const DataLayout &DL;
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
ObjCARCAliasAnalysis() : ImmutablePass(ID) {
|
||||
initializeObjCARCAliasAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
explicit ObjCARCAAResult(const DataLayout &DL, const TargetLibraryInfo &TLI)
|
||||
: AAResultBase(TLI), DL(DL) {}
|
||||
ObjCARCAAResult(ObjCARCAAResult &&Arg)
|
||||
: AAResultBase(std::move(Arg)), DL(Arg.DL) {}
|
||||
|
||||
/// Handle invalidation events from the new pass manager.
|
||||
///
|
||||
/// By definition, this result is stateless and so remains valid.
|
||||
bool invalidate(Function &, const PreservedAnalyses &) { return false; }
|
||||
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal);
|
||||
|
||||
using AAResultBase::getModRefBehavior;
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F);
|
||||
|
||||
using AAResultBase::getModRefInfo;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
|
||||
};
|
||||
|
||||
/// Analysis pass providing a never-invalidated alias analysis result.
|
||||
class ObjCARCAA {
|
||||
public:
|
||||
typedef ObjCARCAAResult Result;
|
||||
|
||||
/// \brief Opaque, unique identifier for this analysis pass.
|
||||
static void *ID() { return (void *)&PassID; }
|
||||
|
||||
ObjCARCAAResult run(Function &F, AnalysisManager<Function> *AM);
|
||||
|
||||
/// \brief Provide access to a name for this pass for debugging purposes.
|
||||
static StringRef name() { return "ObjCARCAA"; }
|
||||
|
||||
private:
|
||||
static char PassID;
|
||||
};
|
||||
|
||||
/// Legacy wrapper pass to provide the ObjCARCAAResult object.
|
||||
class ObjCARCAAWrapperPass : public ImmutablePass {
|
||||
std::unique_ptr<ObjCARCAAResult> Result;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
ObjCARCAAWrapperPass();
|
||||
|
||||
ObjCARCAAResult &getResult() { return *Result; }
|
||||
const ObjCARCAAResult &getResult() const { return *Result; }
|
||||
|
||||
bool doInitialization(Module &M) override;
|
||||
|
||||
/// This method is used when a pass implements an analysis interface through
|
||||
/// multiple inheritance. If needed, it should override this to adjust the
|
||||
/// this pointer as needed for the specified pass info.
|
||||
void *getAdjustedAnalysisPointer(const void *PI) override {
|
||||
if (PI == &AliasAnalysis::ID)
|
||||
return static_cast<AliasAnalysis *>(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
bool doFinalization(Module &M) override;
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override;
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) override;
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override;
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F) override;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) override;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) override;
|
||||
};
|
||||
|
||||
} // namespace objcarc
|
||||
|
@ -32,16 +32,10 @@ namespace llvm {
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createNoAAPass - This pass implements a "I don't know" alias analysis.
|
||||
//
|
||||
ImmutablePass *createNoAAPass();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createObjCARCAliasAnalysisPass - This pass implements ObjC-ARC-based
|
||||
// createObjCARCAAWrapperPass - This pass implements ObjC-ARC-based
|
||||
// alias analysis.
|
||||
//
|
||||
ImmutablePass *createObjCARCAliasAnalysisPass();
|
||||
ImmutablePass *createObjCARCAAWrapperPass();
|
||||
|
||||
FunctionPass *createPAEvalPass();
|
||||
|
||||
|
@ -24,38 +24,55 @@ namespace llvm {
|
||||
|
||||
/// A simple alias analysis implementation that uses ScalarEvolution to answer
|
||||
/// queries.
|
||||
class ScalarEvolutionAliasAnalysis : public FunctionPass, public AliasAnalysis {
|
||||
ScalarEvolution *SE;
|
||||
class SCEVAAResult : public AAResultBase<SCEVAAResult> {
|
||||
ScalarEvolution &SE;
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
ScalarEvolutionAliasAnalysis() : FunctionPass(ID), SE(nullptr) {
|
||||
initializeScalarEvolutionAliasAnalysisPass(
|
||||
*PassRegistry::getPassRegistry());
|
||||
}
|
||||
explicit SCEVAAResult(const TargetLibraryInfo &TLI, ScalarEvolution &SE)
|
||||
: AAResultBase(TLI), SE(SE) {}
|
||||
SCEVAAResult(SCEVAAResult &&Arg) : AAResultBase(std::move(Arg)), SE(Arg.SE) {}
|
||||
|
||||
/// This method is used when a pass implements an analysis interface through
|
||||
/// multiple inheritance.
|
||||
///
|
||||
/// If needed, it should override this to adjust the this pointer as needed
|
||||
/// for the specified pass info.
|
||||
void *getAdjustedAnalysisPointer(AnalysisID PI) override {
|
||||
if (PI == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis *)this;
|
||||
return this;
|
||||
}
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
|
||||
|
||||
private:
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
bool runOnFunction(Function &F) override;
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override;
|
||||
|
||||
Value *GetBaseValue(const SCEV *S);
|
||||
};
|
||||
|
||||
/// Creates an instance of \c ScalarEvolutionAliasAnalysis.
|
||||
FunctionPass *createScalarEvolutionAliasAnalysisPass();
|
||||
/// Analysis pass providing a never-invalidated alias analysis result.
|
||||
class SCEVAA {
|
||||
public:
|
||||
typedef SCEVAAResult Result;
|
||||
|
||||
/// \brief Opaque, unique identifier for this analysis pass.
|
||||
static void *ID() { return (void *)&PassID; }
|
||||
|
||||
SCEVAAResult run(Function &F, AnalysisManager<Function> *AM);
|
||||
|
||||
/// \brief Provide access to a name for this pass for debugging purposes.
|
||||
static StringRef name() { return "SCEVAA"; }
|
||||
|
||||
private:
|
||||
static char PassID;
|
||||
};
|
||||
|
||||
/// Legacy wrapper pass to provide the SCEVAAResult object.
|
||||
class SCEVAAWrapperPass : public FunctionPass {
|
||||
std::unique_ptr<SCEVAAResult> Result;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
SCEVAAWrapperPass();
|
||||
|
||||
SCEVAAResult &getResult() { return *Result; }
|
||||
const SCEVAAResult &getResult() const { return *Result; }
|
||||
|
||||
bool runOnFunction(Function &F) override;
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
};
|
||||
|
||||
/// Creates an instance of \c SCEVAAWrapperPass.
|
||||
FunctionPass *createSCEVAAWrapperPass();
|
||||
|
||||
}
|
||||
|
||||
|
@ -22,52 +22,71 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// ScopedNoAliasAA - This is a simple alias analysis
|
||||
/// implementation that uses scoped-noalias metadata to answer queries.
|
||||
class ScopedNoAliasAA : public ImmutablePass, public AliasAnalysis {
|
||||
/// A simple AA result which uses scoped-noalias metadata to answer queries.
|
||||
class ScopedNoAliasAAResult : public AAResultBase<ScopedNoAliasAAResult> {
|
||||
friend AAResultBase<ScopedNoAliasAAResult>;
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
ScopedNoAliasAA() : ImmutablePass(ID) {
|
||||
initializeScopedNoAliasAAPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
explicit ScopedNoAliasAAResult(const TargetLibraryInfo &TLI)
|
||||
: AAResultBase(TLI) {}
|
||||
ScopedNoAliasAAResult(ScopedNoAliasAAResult &&Arg)
|
||||
: AAResultBase(std::move(Arg)) {}
|
||||
|
||||
bool doInitialization(Module &M) override;
|
||||
/// Handle invalidation events from the new pass manager.
|
||||
///
|
||||
/// By definition, this result is stateless and so remains valid.
|
||||
bool invalidate(Function &, const PreservedAnalyses &) { return false; }
|
||||
|
||||
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
||||
/// an analysis interface through multiple inheritance. If needed, it
|
||||
/// should override this to adjust the this pointer as needed for the
|
||||
/// specified pass info.
|
||||
void *getAdjustedAnalysisPointer(const void *PI) override {
|
||||
if (PI == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis *)this;
|
||||
return this;
|
||||
}
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool mayAliasInScopes(const MDNode *Scopes, const MDNode *NoAlias) const;
|
||||
void collectMDInDomain(const MDNode *List, const MDNode *Domain,
|
||||
SmallPtrSetImpl<const MDNode *> &Nodes) const;
|
||||
};
|
||||
|
||||
/// Analysis pass providing a never-invalidated alias analysis result.
|
||||
class ScopedNoAliasAA {
|
||||
public:
|
||||
typedef ScopedNoAliasAAResult Result;
|
||||
|
||||
/// \brief Opaque, unique identifier for this analysis pass.
|
||||
static void *ID() { return (void *)&PassID; }
|
||||
|
||||
ScopedNoAliasAAResult run(Function &F, AnalysisManager<Function> *AM);
|
||||
|
||||
/// \brief Provide access to a name for this pass for debugging purposes.
|
||||
static StringRef name() { return "ScopedNoAliasAA"; }
|
||||
|
||||
private:
|
||||
static char PassID;
|
||||
};
|
||||
|
||||
/// Legacy wrapper pass to provide the ScopedNoAliasAAResult object.
|
||||
class ScopedNoAliasAAWrapperPass : public ImmutablePass {
|
||||
std::unique_ptr<ScopedNoAliasAAResult> Result;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
ScopedNoAliasAAWrapperPass();
|
||||
|
||||
ScopedNoAliasAAResult &getResult() { return *Result; }
|
||||
const ScopedNoAliasAAResult &getResult() const { return *Result; }
|
||||
|
||||
bool doInitialization(Module &M) override;
|
||||
bool doFinalization(Module &M) override;
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override;
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) override;
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override;
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F) override;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) override;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) override;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createScopedNoAliasAAPass - This pass implements metadata-based
|
||||
// createScopedNoAliasAAWrapperPass - This pass implements metadata-based
|
||||
// scoped noalias analysis.
|
||||
//
|
||||
ImmutablePass *createScopedNoAliasAAPass();
|
||||
|
||||
ImmutablePass *createScopedNoAliasAAWrapperPass();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -22,50 +22,72 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// TypeBasedAliasAnalysis - This is a simple alias analysis
|
||||
/// implementation that uses TypeBased to answer queries.
|
||||
class TypeBasedAliasAnalysis : public ImmutablePass, public AliasAnalysis {
|
||||
/// A simple AA result that uses TBAA metadata to answer queries.
|
||||
class TypeBasedAAResult : public AAResultBase<TypeBasedAAResult> {
|
||||
friend AAResultBase<TypeBasedAAResult>;
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
TypeBasedAliasAnalysis() : ImmutablePass(ID) {
|
||||
initializeTypeBasedAliasAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
explicit TypeBasedAAResult(const TargetLibraryInfo &TLI)
|
||||
: AAResultBase(TLI) {}
|
||||
TypeBasedAAResult(TypeBasedAAResult &&Arg) : AAResultBase(std::move(Arg)) {}
|
||||
|
||||
bool doInitialization(Module &M) override;
|
||||
/// Handle invalidation events from the new pass manager.
|
||||
///
|
||||
/// By definition, this result is stateless and so remains valid.
|
||||
bool invalidate(Function &, const PreservedAnalyses &) { return false; }
|
||||
|
||||
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
||||
/// an analysis interface through multiple inheritance. If needed, it
|
||||
/// should override this to adjust the this pointer as needed for the
|
||||
/// specified pass info.
|
||||
void *getAdjustedAnalysisPointer(const void *PI) override {
|
||||
if (PI == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis *)this;
|
||||
return this;
|
||||
}
|
||||
|
||||
bool Aliases(const MDNode *A, const MDNode *B) const;
|
||||
bool PathAliases(const MDNode *A, const MDNode *B) const;
|
||||
AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB);
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal);
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F);
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const MemoryLocation &Loc);
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1, ImmutableCallSite CS2);
|
||||
|
||||
private:
|
||||
bool Aliases(const MDNode *A, const MDNode *B) const;
|
||||
bool PathAliases(const MDNode *A, const MDNode *B) const;
|
||||
};
|
||||
|
||||
/// Analysis pass providing a never-invalidated alias analysis result.
|
||||
class TypeBasedAA {
|
||||
public:
|
||||
typedef TypeBasedAAResult Result;
|
||||
|
||||
/// \brief Opaque, unique identifier for this analysis pass.
|
||||
static void *ID() { return (void *)&PassID; }
|
||||
|
||||
TypeBasedAAResult run(Function &F, AnalysisManager<Function> *AM);
|
||||
|
||||
/// \brief Provide access to a name for this pass for debugging purposes.
|
||||
static StringRef name() { return "TypeBasedAA"; }
|
||||
|
||||
private:
|
||||
static char PassID;
|
||||
};
|
||||
|
||||
/// Legacy wrapper pass to provide the TypeBasedAAResult object.
|
||||
class TypeBasedAAWrapperPass : public ImmutablePass {
|
||||
std::unique_ptr<TypeBasedAAResult> Result;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
TypeBasedAAWrapperPass();
|
||||
|
||||
TypeBasedAAResult &getResult() { return *Result; }
|
||||
const TypeBasedAAResult &getResult() const { return *Result; }
|
||||
|
||||
bool doInitialization(Module &M) override;
|
||||
bool doFinalization(Module &M) override;
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override;
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal) override;
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override;
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F) override;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) override;
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) override;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
// createTypeBasedAliasAnalysisPass - This pass implements metadata-based
|
||||
// createTypeBasedAAWrapperPass - This pass implements metadata-based
|
||||
// type-based alias analysis.
|
||||
//
|
||||
ImmutablePass *createTypeBasedAliasAnalysisPass();
|
||||
|
||||
ImmutablePass *createTypeBasedAAWrapperPass();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "llvm/ADT/IndexedMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/CodeGen/LiveInterval.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
@ -36,7 +37,6 @@ namespace llvm {
|
||||
|
||||
extern cl::opt<bool> UseSegmentSetForPhysRegs;
|
||||
|
||||
class AliasAnalysis;
|
||||
class BitVector;
|
||||
class BlockFrequency;
|
||||
class LiveRangeCalc;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/CodeGen/LiveInterval.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
@ -28,7 +29,6 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class LiveIntervals;
|
||||
class MachineBlockFrequencyInfo;
|
||||
class MachineLoopInfo;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/CodeGen/MachineOperand.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/DebugLoc.h"
|
||||
@ -34,7 +35,6 @@
|
||||
namespace llvm {
|
||||
|
||||
template <typename T> class SmallVectorImpl;
|
||||
class AliasAnalysis;
|
||||
class TargetInstrInfo;
|
||||
class TargetRegisterClass;
|
||||
class TargetRegisterInfo;
|
||||
|
@ -77,6 +77,7 @@
|
||||
#ifndef LLVM_CODEGEN_MACHINESCHEDULER_H
|
||||
#define LLVM_CODEGEN_MACHINESCHEDULER_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/CodeGen/MachinePassRegistry.h"
|
||||
#include "llvm/CodeGen/RegisterPressure.h"
|
||||
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
|
||||
@ -87,7 +88,6 @@ namespace llvm {
|
||||
extern cl::opt<bool> ForceTopDown;
|
||||
extern cl::opt<bool> ForceBottomUp;
|
||||
|
||||
class AliasAnalysis;
|
||||
class LiveIntervals;
|
||||
class MachineDominatorTree;
|
||||
class MachineLoopInfo;
|
||||
|
@ -20,11 +20,11 @@
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
class AliasAnalysis;
|
||||
class SUnit;
|
||||
class MachineConstantPool;
|
||||
class MachineFunction;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/CodeGen/DAGCombine.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
||||
@ -31,7 +32,6 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class MachineConstantPoolValue;
|
||||
class MachineFunction;
|
||||
class MDNode;
|
||||
|
@ -63,8 +63,6 @@ void initializeAAEvalPass(PassRegistry&);
|
||||
void initializeAddDiscriminatorsPass(PassRegistry&);
|
||||
void initializeADCEPass(PassRegistry&);
|
||||
void initializeBDCEPass(PassRegistry&);
|
||||
void initializeAliasAnalysisAnalysisGroup(PassRegistry&);
|
||||
void initializeAliasAnalysisCounterPass(PassRegistry&);
|
||||
void initializeAliasSetPrinterPass(PassRegistry&);
|
||||
void initializeAlwaysInlinerPass(PassRegistry&);
|
||||
void initializeArgPromotionPass(PassRegistry&);
|
||||
@ -72,7 +70,7 @@ void initializeAtomicExpandPass(PassRegistry&);
|
||||
void initializeSampleProfileLoaderPass(PassRegistry&);
|
||||
void initializeAlignmentFromAssumptionsPass(PassRegistry&);
|
||||
void initializeBarrierNoopPass(PassRegistry&);
|
||||
void initializeBasicAliasAnalysisPass(PassRegistry&);
|
||||
void initializeBasicAAWrapperPassPass(PassRegistry&);
|
||||
void initializeCallGraphWrapperPassPass(PassRegistry &);
|
||||
void initializeBlockExtractorPassPass(PassRegistry&);
|
||||
void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&);
|
||||
@ -86,7 +84,7 @@ void initializeCFGOnlyPrinterPass(PassRegistry&);
|
||||
void initializeCFGOnlyViewerPass(PassRegistry&);
|
||||
void initializeCFGPrinterPass(PassRegistry&);
|
||||
void initializeCFGSimplifyPassPass(PassRegistry&);
|
||||
void initializeCFLAliasAnalysisPass(PassRegistry&);
|
||||
void initializeCFLAAWrapperPassPass(PassRegistry&);
|
||||
void initializeForwardControlFlowIntegrityPass(PassRegistry&);
|
||||
void initializeFlattenCFGPassPass(PassRegistry&);
|
||||
void initializeStructurizeCFGPass(PassRegistry&);
|
||||
@ -116,6 +114,7 @@ void initializeDominatorTreeWrapperPassPass(PassRegistry&);
|
||||
void initializeEarlyIfConverterPass(PassRegistry&);
|
||||
void initializeEdgeBundlesPass(PassRegistry&);
|
||||
void initializeExpandPostRAPass(PassRegistry&);
|
||||
void initializeAAResultsWrapperPassPass(PassRegistry &);
|
||||
void initializeGCOVProfilerPass(PassRegistry&);
|
||||
void initializeInstrProfilingPass(PassRegistry&);
|
||||
void initializeAddressSanitizerPass(PassRegistry&);
|
||||
@ -134,7 +133,7 @@ void initializeGCModuleInfoPass(PassRegistry&);
|
||||
void initializeGVNPass(PassRegistry&);
|
||||
void initializeGlobalDCEPass(PassRegistry&);
|
||||
void initializeGlobalOptPass(PassRegistry&);
|
||||
void initializeGlobalsModRefPass(PassRegistry&);
|
||||
void initializeGlobalsAAWrapperPassPass(PassRegistry&);
|
||||
void initializeIPCPPass(PassRegistry&);
|
||||
void initializeIPSCCPPass(PassRegistry&);
|
||||
void initializeIVUsersPass(PassRegistry&);
|
||||
@ -205,7 +204,7 @@ void initializeMergeFunctionsPass(PassRegistry&);
|
||||
void initializeModuleDebugInfoPrinterPass(PassRegistry&);
|
||||
void initializeNaryReassociatePass(PassRegistry&);
|
||||
void initializeNoAAPass(PassRegistry&);
|
||||
void initializeObjCARCAliasAnalysisPass(PassRegistry&);
|
||||
void initializeObjCARCAAWrapperPassPass(PassRegistry&);
|
||||
void initializeObjCARCAPElimPass(PassRegistry&);
|
||||
void initializeObjCARCExpandPass(PassRegistry&);
|
||||
void initializeObjCARCContractPass(PassRegistry&);
|
||||
@ -243,7 +242,7 @@ void initializeSCCPPass(PassRegistry&);
|
||||
void initializeSROAPass(PassRegistry&);
|
||||
void initializeSROA_DTPass(PassRegistry&);
|
||||
void initializeSROA_SSAUpPass(PassRegistry&);
|
||||
void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&);
|
||||
void initializeSCEVAAWrapperPassPass(PassRegistry&);
|
||||
void initializeScalarEvolutionWrapperPassPass(PassRegistry&);
|
||||
void initializeShrinkWrapPass(PassRegistry &);
|
||||
void initializeSimpleInlinerPass(PassRegistry&);
|
||||
@ -271,8 +270,8 @@ void initializeTargetTransformInfoWrapperPassPass(PassRegistry &);
|
||||
void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &);
|
||||
void initializeAssumptionCacheTrackerPass(PassRegistry &);
|
||||
void initializeTwoAddressInstructionPassPass(PassRegistry&);
|
||||
void initializeTypeBasedAliasAnalysisPass(PassRegistry&);
|
||||
void initializeScopedNoAliasAAPass(PassRegistry&);
|
||||
void initializeTypeBasedAAWrapperPassPass(PassRegistry&);
|
||||
void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&);
|
||||
void initializeUnifyFunctionExitNodesPass(PassRegistry&);
|
||||
void initializeUnreachableBlockElimPass(PassRegistry&);
|
||||
void initializeUnreachableMachineBlockElimPass(PassRegistry&);
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasSetTracker.h"
|
||||
#include "llvm/Analysis/AliasAnalysisCounter.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/CFLAliasAnalysis.h"
|
||||
#include "llvm/Analysis/CallPrinter.h"
|
||||
@ -59,19 +58,18 @@ namespace {
|
||||
(void) llvm::createAAEvalPass();
|
||||
(void) llvm::createAggressiveDCEPass();
|
||||
(void) llvm::createBitTrackingDCEPass();
|
||||
(void) llvm::createAliasAnalysisCounterPass();
|
||||
(void) llvm::createArgumentPromotionPass();
|
||||
(void) llvm::createAlignmentFromAssumptionsPass();
|
||||
(void) llvm::createBasicAliasAnalysisPass();
|
||||
(void) llvm::createScalarEvolutionAliasAnalysisPass();
|
||||
(void) llvm::createTypeBasedAliasAnalysisPass();
|
||||
(void) llvm::createScopedNoAliasAAPass();
|
||||
(void) llvm::createBasicAAWrapperPass();
|
||||
(void) llvm::createSCEVAAWrapperPass();
|
||||
(void) llvm::createTypeBasedAAWrapperPass();
|
||||
(void) llvm::createScopedNoAliasAAWrapperPass();
|
||||
(void) llvm::createBoundsCheckingPass();
|
||||
(void) llvm::createBreakCriticalEdgesPass();
|
||||
(void) llvm::createCallGraphPrinterPass();
|
||||
(void) llvm::createCallGraphViewerPass();
|
||||
(void) llvm::createCFGSimplificationPass();
|
||||
(void) llvm::createCFLAliasAnalysisPass();
|
||||
(void) llvm::createCFLAAWrapperPass();
|
||||
(void) llvm::createStructurizeCFGPass();
|
||||
(void) llvm::createConstantMergePass();
|
||||
(void) llvm::createConstantPropagationPass();
|
||||
@ -92,7 +90,7 @@ namespace {
|
||||
(void) llvm::createAlwaysInlinerPass();
|
||||
(void) llvm::createGlobalDCEPass();
|
||||
(void) llvm::createGlobalOptimizerPass();
|
||||
(void) llvm::createGlobalsModRefPass();
|
||||
(void) llvm::createGlobalsAAWrapperPass();
|
||||
(void) llvm::createIPConstantPropagationPass();
|
||||
(void) llvm::createIPSCCPPass();
|
||||
(void) llvm::createInductiveRangeCheckEliminationPass();
|
||||
@ -115,8 +113,7 @@ namespace {
|
||||
(void) llvm::createLowerInvokePass();
|
||||
(void) llvm::createLowerSwitchPass();
|
||||
(void) llvm::createNaryReassociatePass();
|
||||
(void) llvm::createNoAAPass();
|
||||
(void) llvm::createObjCARCAliasAnalysisPass();
|
||||
(void) llvm::createObjCARCAAWrapperPass();
|
||||
(void) llvm::createObjCARCAPElimPass();
|
||||
(void) llvm::createObjCARCExpandPass();
|
||||
(void) llvm::createObjCARCContractPass();
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/ValueHandle.h"
|
||||
#include "llvm/IR/ValueMap.h"
|
||||
#include "llvm/Transforms/Utils/ValueMapper.h"
|
||||
@ -44,7 +45,6 @@ class DataLayout;
|
||||
class Loop;
|
||||
class LoopInfo;
|
||||
class AllocaInst;
|
||||
class AliasAnalysis;
|
||||
class AssumptionCacheTracker;
|
||||
class DominatorTree;
|
||||
|
||||
@ -202,14 +202,12 @@ void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
|
||||
class InlineFunctionInfo {
|
||||
public:
|
||||
explicit InlineFunctionInfo(CallGraph *cg = nullptr,
|
||||
AliasAnalysis *AA = nullptr,
|
||||
AssumptionCacheTracker *ACT = nullptr)
|
||||
: CG(cg), AA(AA), ACT(ACT) {}
|
||||
: CG(cg), ACT(ACT) {}
|
||||
|
||||
/// CG - If non-null, InlineFunction will update the callgraph to reflect the
|
||||
/// changes it makes.
|
||||
CallGraph *CG;
|
||||
AliasAnalysis *AA;
|
||||
AssumptionCacheTracker *ACT;
|
||||
|
||||
/// StaticAllocas - InlineFunction fills this in with all static allocas that
|
||||
@ -237,11 +235,11 @@ public:
|
||||
/// function by one level.
|
||||
///
|
||||
bool InlineFunction(CallInst *C, InlineFunctionInfo &IFI,
|
||||
bool InsertLifetime = true);
|
||||
AAResults *CalleeAAR = nullptr, bool InsertLifetime = true);
|
||||
bool InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
|
||||
bool InsertLifetime = true);
|
||||
AAResults *CalleeAAR = nullptr, bool InsertLifetime = true);
|
||||
bool InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
bool InsertLifetime = true);
|
||||
AAResults *CalleeAAR = nullptr, bool InsertLifetime = true);
|
||||
|
||||
/// \brief Clones a loop \p OrigLoop. Returns the loop and the blocks in \p
|
||||
/// Blocks.
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef LLVM_TRANSFORMS_UTILS_LOCAL_H
|
||||
#define LLVM_TRANSFORMS_UTILS_LOCAL_H
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/GetElementPtrTypeIterator.h"
|
||||
@ -40,7 +41,6 @@ class DataLayout;
|
||||
class TargetLibraryInfo;
|
||||
class TargetTransformInfo;
|
||||
class DIBuilder;
|
||||
class AliasAnalysis;
|
||||
class DominatorTree;
|
||||
|
||||
template<typename T> class SmallVectorImpl;
|
||||
|
@ -15,11 +15,11 @@
|
||||
#define LLVM_TRANSFORMS_UTILS_LOOPUTILS_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
|
||||
namespace llvm {
|
||||
class AliasAnalysis;
|
||||
class AliasSet;
|
||||
class AliasSetTracker;
|
||||
class AssumptionCache;
|
||||
|
@ -25,9 +25,16 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/CFLAliasAnalysis.h"
|
||||
#include "llvm/Analysis/CaptureTracking.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/ObjCARCAliasAnalysis.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/Analysis/ScopedNoAliasAA.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
@ -40,34 +47,72 @@
|
||||
#include "llvm/Pass.h"
|
||||
using namespace llvm;
|
||||
|
||||
// Register the AliasAnalysis interface, providing a nice name to refer to.
|
||||
INITIALIZE_ANALYSIS_GROUP(AliasAnalysis, "Alias Analysis", NoAA)
|
||||
char AliasAnalysis::ID = 0;
|
||||
/// Allow disabling BasicAA from the AA results. This is particularly useful
|
||||
/// when testing to isolate a single AA implementation.
|
||||
static cl::opt<bool> DisableBasicAA("disable-basicaa", cl::Hidden,
|
||||
cl::init(false));
|
||||
|
||||
AAResults::AAResults(AAResults &&Arg) : AAs(std::move(Arg.AAs)) {
|
||||
for (auto &AA : AAs)
|
||||
AA->setAAResults(this);
|
||||
}
|
||||
|
||||
AAResults &AAResults::operator=(AAResults &&Arg) {
|
||||
AAs = std::move(Arg.AAs);
|
||||
for (auto &AA : AAs)
|
||||
AA->setAAResults(this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
AAResults::~AAResults() {
|
||||
// FIXME; It would be nice to at least clear out the pointers back to this
|
||||
// aggregation here, but we end up with non-nesting lifetimes in the legacy
|
||||
// pass manager that prevent this from working. In the legacy pass manager
|
||||
// we'll end up with dangling references here in some cases.
|
||||
#if 0
|
||||
for (auto &AA : AAs)
|
||||
AA->setAAResults(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Default chaining methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
AliasResult AliasAnalysis::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
|
||||
return AA->alias(LocA, LocB);
|
||||
AliasResult AAResults::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
for (const auto &AA : AAs) {
|
||||
auto Result = AA->alias(LocA, LocB);
|
||||
if (Result != MayAlias)
|
||||
return Result;
|
||||
}
|
||||
return MayAlias;
|
||||
}
|
||||
|
||||
bool AliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) {
|
||||
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
|
||||
return AA->pointsToConstantMemory(Loc, OrLocal);
|
||||
bool AAResults::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) {
|
||||
for (const auto &AA : AAs)
|
||||
if (AA->pointsToConstantMemory(Loc, OrLocal))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ModRefInfo AliasAnalysis::getArgModRefInfo(ImmutableCallSite CS,
|
||||
unsigned ArgIdx) {
|
||||
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
|
||||
return AA->getArgModRefInfo(CS, ArgIdx);
|
||||
ModRefInfo AAResults::getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx) {
|
||||
ModRefInfo Result = MRI_ModRef;
|
||||
|
||||
for (const auto &AA : AAs) {
|
||||
Result = ModRefInfo(Result & AA->getArgModRefInfo(CS, ArgIdx));
|
||||
|
||||
// Early-exit the moment we reach the bottom of the lattice.
|
||||
if (Result == MRI_NoModRef)
|
||||
return Result;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
ModRefInfo AliasAnalysis::getModRefInfo(Instruction *I,
|
||||
ImmutableCallSite Call) {
|
||||
ModRefInfo AAResults::getModRefInfo(Instruction *I, ImmutableCallSite Call) {
|
||||
// We may have two calls
|
||||
if (auto CS = ImmutableCallSite(I)) {
|
||||
// Check if the two calls modify the same memory
|
||||
@ -84,177 +129,70 @@ ModRefInfo AliasAnalysis::getModRefInfo(Instruction *I,
|
||||
return MRI_NoModRef;
|
||||
}
|
||||
|
||||
ModRefInfo AliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
|
||||
ModRefInfo AAResults::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo Result = MRI_ModRef;
|
||||
|
||||
auto MRB = getModRefBehavior(CS);
|
||||
if (MRB == FMRB_DoesNotAccessMemory)
|
||||
return MRI_NoModRef;
|
||||
for (const auto &AA : AAs) {
|
||||
Result = ModRefInfo(Result & AA->getModRefInfo(CS, Loc));
|
||||
|
||||
ModRefInfo Mask = MRI_ModRef;
|
||||
if (onlyReadsMemory(MRB))
|
||||
Mask = MRI_Ref;
|
||||
|
||||
if (onlyAccessesArgPointees(MRB)) {
|
||||
bool doesAlias = false;
|
||||
ModRefInfo AllArgsMask = MRI_NoModRef;
|
||||
if (doesAccessArgPointees(MRB)) {
|
||||
for (ImmutableCallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end();
|
||||
AI != AE; ++AI) {
|
||||
const Value *Arg = *AI;
|
||||
if (!Arg->getType()->isPointerTy())
|
||||
continue;
|
||||
unsigned ArgIdx = std::distance(CS.arg_begin(), AI);
|
||||
MemoryLocation ArgLoc =
|
||||
MemoryLocation::getForArgument(CS, ArgIdx, *TLI);
|
||||
if (!isNoAlias(ArgLoc, Loc)) {
|
||||
ModRefInfo ArgMask = getArgModRefInfo(CS, ArgIdx);
|
||||
doesAlias = true;
|
||||
AllArgsMask = ModRefInfo(AllArgsMask | ArgMask);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!doesAlias)
|
||||
return MRI_NoModRef;
|
||||
Mask = ModRefInfo(Mask & AllArgsMask);
|
||||
// Early-exit the moment we reach the bottom of the lattice.
|
||||
if (Result == MRI_NoModRef)
|
||||
return Result;
|
||||
}
|
||||
|
||||
// If Loc is a constant memory location, the call definitely could not
|
||||
// modify the memory location.
|
||||
if ((Mask & MRI_Mod) && pointsToConstantMemory(Loc))
|
||||
Mask = ModRefInfo(Mask & ~MRI_Mod);
|
||||
|
||||
// If this is the end of the chain, don't forward.
|
||||
if (!AA) return Mask;
|
||||
|
||||
// Otherwise, fall back to the next AA in the chain. But we can merge
|
||||
// in any mask we've managed to compute.
|
||||
return ModRefInfo(AA->getModRefInfo(CS, Loc) & Mask);
|
||||
return Result;
|
||||
}
|
||||
|
||||
ModRefInfo AliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
|
||||
ModRefInfo AAResults::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
ModRefInfo Result = MRI_ModRef;
|
||||
|
||||
// If CS1 or CS2 are readnone, they don't interact.
|
||||
auto CS1B = getModRefBehavior(CS1);
|
||||
if (CS1B == FMRB_DoesNotAccessMemory)
|
||||
return MRI_NoModRef;
|
||||
for (const auto &AA : AAs) {
|
||||
Result = ModRefInfo(Result & AA->getModRefInfo(CS1, CS2));
|
||||
|
||||
auto CS2B = getModRefBehavior(CS2);
|
||||
if (CS2B == FMRB_DoesNotAccessMemory)
|
||||
return MRI_NoModRef;
|
||||
|
||||
// If they both only read from memory, there is no dependence.
|
||||
if (onlyReadsMemory(CS1B) && onlyReadsMemory(CS2B))
|
||||
return MRI_NoModRef;
|
||||
|
||||
ModRefInfo Mask = MRI_ModRef;
|
||||
|
||||
// If CS1 only reads memory, the only dependence on CS2 can be
|
||||
// from CS1 reading memory written by CS2.
|
||||
if (onlyReadsMemory(CS1B))
|
||||
Mask = ModRefInfo(Mask & MRI_Ref);
|
||||
|
||||
// If CS2 only access memory through arguments, accumulate the mod/ref
|
||||
// information from CS1's references to the memory referenced by
|
||||
// CS2's arguments.
|
||||
if (onlyAccessesArgPointees(CS2B)) {
|
||||
ModRefInfo R = MRI_NoModRef;
|
||||
if (doesAccessArgPointees(CS2B)) {
|
||||
for (ImmutableCallSite::arg_iterator
|
||||
I = CS2.arg_begin(), E = CS2.arg_end(); I != E; ++I) {
|
||||
const Value *Arg = *I;
|
||||
if (!Arg->getType()->isPointerTy())
|
||||
continue;
|
||||
unsigned CS2ArgIdx = std::distance(CS2.arg_begin(), I);
|
||||
auto CS2ArgLoc = MemoryLocation::getForArgument(CS2, CS2ArgIdx, *TLI);
|
||||
|
||||
// ArgMask indicates what CS2 might do to CS2ArgLoc, and the dependence of
|
||||
// CS1 on that location is the inverse.
|
||||
ModRefInfo ArgMask = getArgModRefInfo(CS2, CS2ArgIdx);
|
||||
if (ArgMask == MRI_Mod)
|
||||
ArgMask = MRI_ModRef;
|
||||
else if (ArgMask == MRI_Ref)
|
||||
ArgMask = MRI_Mod;
|
||||
|
||||
R = ModRefInfo((R | (getModRefInfo(CS1, CS2ArgLoc) & ArgMask)) & Mask);
|
||||
if (R == Mask)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return R;
|
||||
// Early-exit the moment we reach the bottom of the lattice.
|
||||
if (Result == MRI_NoModRef)
|
||||
return Result;
|
||||
}
|
||||
|
||||
// If CS1 only accesses memory through arguments, check if CS2 references
|
||||
// any of the memory referenced by CS1's arguments. If not, return NoModRef.
|
||||
if (onlyAccessesArgPointees(CS1B)) {
|
||||
ModRefInfo R = MRI_NoModRef;
|
||||
if (doesAccessArgPointees(CS1B)) {
|
||||
for (ImmutableCallSite::arg_iterator
|
||||
I = CS1.arg_begin(), E = CS1.arg_end(); I != E; ++I) {
|
||||
const Value *Arg = *I;
|
||||
if (!Arg->getType()->isPointerTy())
|
||||
continue;
|
||||
unsigned CS1ArgIdx = std::distance(CS1.arg_begin(), I);
|
||||
auto CS1ArgLoc = MemoryLocation::getForArgument(CS1, CS1ArgIdx, *TLI);
|
||||
return Result;
|
||||
}
|
||||
|
||||
// ArgMask indicates what CS1 might do to CS1ArgLoc; if CS1 might Mod
|
||||
// CS1ArgLoc, then we care about either a Mod or a Ref by CS2. If CS1
|
||||
// might Ref, then we care only about a Mod by CS2.
|
||||
ModRefInfo ArgMask = getArgModRefInfo(CS1, CS1ArgIdx);
|
||||
ModRefInfo ArgR = getModRefInfo(CS2, CS1ArgLoc);
|
||||
if (((ArgMask & MRI_Mod) != MRI_NoModRef &&
|
||||
(ArgR & MRI_ModRef) != MRI_NoModRef) ||
|
||||
((ArgMask & MRI_Ref) != MRI_NoModRef &&
|
||||
(ArgR & MRI_Mod) != MRI_NoModRef))
|
||||
R = ModRefInfo((R | ArgMask) & Mask);
|
||||
FunctionModRefBehavior AAResults::getModRefBehavior(ImmutableCallSite CS) {
|
||||
FunctionModRefBehavior Result = FMRB_UnknownModRefBehavior;
|
||||
|
||||
if (R == Mask)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return R;
|
||||
for (const auto &AA : AAs) {
|
||||
Result = FunctionModRefBehavior(Result & AA->getModRefBehavior(CS));
|
||||
|
||||
// Early-exit the moment we reach the bottom of the lattice.
|
||||
if (Result == FMRB_DoesNotAccessMemory)
|
||||
return Result;
|
||||
}
|
||||
|
||||
// If this is the end of the chain, don't forward.
|
||||
if (!AA) return Mask;
|
||||
|
||||
// Otherwise, fall back to the next AA in the chain. But we can merge
|
||||
// in any mask we've managed to compute.
|
||||
return ModRefInfo(AA->getModRefInfo(CS1, CS2) & Mask);
|
||||
return Result;
|
||||
}
|
||||
|
||||
FunctionModRefBehavior AliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
||||
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
|
||||
FunctionModRefBehavior AAResults::getModRefBehavior(const Function *F) {
|
||||
FunctionModRefBehavior Result = FMRB_UnknownModRefBehavior;
|
||||
|
||||
auto Min = FMRB_UnknownModRefBehavior;
|
||||
for (const auto &AA : AAs) {
|
||||
Result = FunctionModRefBehavior(Result & AA->getModRefBehavior(F));
|
||||
|
||||
// Call back into the alias analysis with the other form of getModRefBehavior
|
||||
// to see if it can give a better response.
|
||||
if (const Function *F = CS.getCalledFunction())
|
||||
Min = getModRefBehavior(F);
|
||||
// Early-exit the moment we reach the bottom of the lattice.
|
||||
if (Result == FMRB_DoesNotAccessMemory)
|
||||
return Result;
|
||||
}
|
||||
|
||||
// If this is the end of the chain, don't forward.
|
||||
if (!AA) return Min;
|
||||
|
||||
// Otherwise, fall back to the next AA in the chain. But we can merge
|
||||
// in any result we've managed to compute.
|
||||
return FunctionModRefBehavior(AA->getModRefBehavior(CS) & Min);
|
||||
}
|
||||
|
||||
FunctionModRefBehavior AliasAnalysis::getModRefBehavior(const Function *F) {
|
||||
assert(AA && "AA didn't call InitializeAliasAnalysis in its run method!");
|
||||
return AA->getModRefBehavior(F);
|
||||
return Result;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AliasAnalysis non-virtual helper method implementation
|
||||
// Helper method implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ModRefInfo AliasAnalysis::getModRefInfo(const LoadInst *L,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo AAResults::getModRefInfo(const LoadInst *L,
|
||||
const MemoryLocation &Loc) {
|
||||
// Be conservative in the face of volatile/atomic.
|
||||
if (!L->isUnordered())
|
||||
return MRI_ModRef;
|
||||
@ -268,8 +206,8 @@ ModRefInfo AliasAnalysis::getModRefInfo(const LoadInst *L,
|
||||
return MRI_Ref;
|
||||
}
|
||||
|
||||
ModRefInfo AliasAnalysis::getModRefInfo(const StoreInst *S,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo AAResults::getModRefInfo(const StoreInst *S,
|
||||
const MemoryLocation &Loc) {
|
||||
// Be conservative in the face of volatile/atomic.
|
||||
if (!S->isUnordered())
|
||||
return MRI_ModRef;
|
||||
@ -290,8 +228,8 @@ ModRefInfo AliasAnalysis::getModRefInfo(const StoreInst *S,
|
||||
return MRI_Mod;
|
||||
}
|
||||
|
||||
ModRefInfo AliasAnalysis::getModRefInfo(const VAArgInst *V,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo AAResults::getModRefInfo(const VAArgInst *V,
|
||||
const MemoryLocation &Loc) {
|
||||
|
||||
if (Loc.Ptr) {
|
||||
// If the va_arg address cannot alias the pointer in question, then the
|
||||
@ -309,8 +247,8 @@ ModRefInfo AliasAnalysis::getModRefInfo(const VAArgInst *V,
|
||||
return MRI_ModRef;
|
||||
}
|
||||
|
||||
ModRefInfo AliasAnalysis::getModRefInfo(const AtomicCmpXchgInst *CX,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX,
|
||||
const MemoryLocation &Loc) {
|
||||
// Acquire/Release cmpxchg has properties that matter for arbitrary addresses.
|
||||
if (CX->getSuccessOrdering() > Monotonic)
|
||||
return MRI_ModRef;
|
||||
@ -322,8 +260,8 @@ ModRefInfo AliasAnalysis::getModRefInfo(const AtomicCmpXchgInst *CX,
|
||||
return MRI_ModRef;
|
||||
}
|
||||
|
||||
ModRefInfo AliasAnalysis::getModRefInfo(const AtomicRMWInst *RMW,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo AAResults::getModRefInfo(const AtomicRMWInst *RMW,
|
||||
const MemoryLocation &Loc) {
|
||||
// Acquire/Release atomicrmw has properties that matter for arbitrary addresses.
|
||||
if (RMW->getOrdering() > Monotonic)
|
||||
return MRI_ModRef;
|
||||
@ -343,14 +281,15 @@ ModRefInfo AliasAnalysis::getModRefInfo(const AtomicRMWInst *RMW,
|
||||
/// BasicAA isn't willing to spend linear time determining whether an alloca
|
||||
/// was captured before or after this particular call, while we are. However,
|
||||
/// with a smarter AA in place, this test is just wasting compile time.
|
||||
ModRefInfo AliasAnalysis::callCapturesBefore(const Instruction *I,
|
||||
const MemoryLocation &MemLoc,
|
||||
DominatorTree *DT,
|
||||
OrderedBasicBlock *OBB) {
|
||||
ModRefInfo AAResults::callCapturesBefore(const Instruction *I,
|
||||
const MemoryLocation &MemLoc,
|
||||
DominatorTree *DT,
|
||||
OrderedBasicBlock *OBB) {
|
||||
if (!DT)
|
||||
return MRI_ModRef;
|
||||
|
||||
const Value *Object = GetUnderlyingObject(MemLoc.Ptr, *DL);
|
||||
const Value *Object =
|
||||
GetUnderlyingObject(MemLoc.Ptr, I->getModule()->getDataLayout());
|
||||
if (!isIdentifiedObject(Object) || isa<GlobalValue>(Object) ||
|
||||
isa<Constant>(Object))
|
||||
return MRI_ModRef;
|
||||
@ -393,34 +332,11 @@ ModRefInfo AliasAnalysis::callCapturesBefore(const Instruction *I,
|
||||
return R;
|
||||
}
|
||||
|
||||
// AliasAnalysis destructor: DO NOT move this to the header file for
|
||||
// AliasAnalysis or else clients of the AliasAnalysis class may not depend on
|
||||
// the AliasAnalysis.o file in the current .a file, causing alias analysis
|
||||
// support to not be included in the tool correctly!
|
||||
//
|
||||
AliasAnalysis::~AliasAnalysis() {}
|
||||
|
||||
/// InitializeAliasAnalysis - Subclasses must call this method to initialize the
|
||||
/// AliasAnalysis interface before any other methods are called.
|
||||
///
|
||||
void AliasAnalysis::InitializeAliasAnalysis(Pass *P, const DataLayout *NewDL) {
|
||||
DL = NewDL;
|
||||
auto *TLIP = P->getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
|
||||
TLI = TLIP ? &TLIP->getTLI() : nullptr;
|
||||
AA = &P->getAnalysis<AliasAnalysis>();
|
||||
}
|
||||
|
||||
// getAnalysisUsage - All alias analysis implementations should invoke this
|
||||
// directly (using AliasAnalysis::getAnalysisUsage(AU)).
|
||||
void AliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<AliasAnalysis>(); // All AA's chain
|
||||
}
|
||||
|
||||
/// canBasicBlockModify - Return true if it is possible for execution of the
|
||||
/// specified basic block to modify the location Loc.
|
||||
///
|
||||
bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB,
|
||||
const MemoryLocation &Loc) {
|
||||
bool AAResults::canBasicBlockModify(const BasicBlock &BB,
|
||||
const MemoryLocation &Loc) {
|
||||
return canInstructionRangeModRef(BB.front(), BB.back(), Loc, MRI_Mod);
|
||||
}
|
||||
|
||||
@ -429,10 +345,10 @@ bool AliasAnalysis::canBasicBlockModify(const BasicBlock &BB,
|
||||
/// mode) the location Loc. The instructions to consider are all
|
||||
/// of the instructions in the range of [I1,I2] INCLUSIVE.
|
||||
/// I1 and I2 must be in the same basic block.
|
||||
bool AliasAnalysis::canInstructionRangeModRef(const Instruction &I1,
|
||||
const Instruction &I2,
|
||||
const MemoryLocation &Loc,
|
||||
const ModRefInfo Mode) {
|
||||
bool AAResults::canInstructionRangeModRef(const Instruction &I1,
|
||||
const Instruction &I2,
|
||||
const MemoryLocation &Loc,
|
||||
const ModRefInfo Mode) {
|
||||
assert(I1.getParent() == I2.getParent() &&
|
||||
"Instructions not in same basic block!");
|
||||
BasicBlock::const_iterator I = &I1;
|
||||
@ -445,6 +361,117 @@ bool AliasAnalysis::canInstructionRangeModRef(const Instruction &I1,
|
||||
return false;
|
||||
}
|
||||
|
||||
// Provide a definition for the root virtual destructor.
|
||||
AAResults::Concept::~Concept() {}
|
||||
|
||||
AAResultsWrapperPass::AAResultsWrapperPass() : FunctionPass(ID) {
|
||||
initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
char AAResultsWrapperPass::ID = 0;
|
||||
|
||||
INITIALIZE_PASS_BEGIN(AAResultsWrapperPass, "aa",
|
||||
"Function Alias Analysis Results", false, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(CFLAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(ScopedNoAliasAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TypeBasedAAWrapperPass)
|
||||
INITIALIZE_PASS_END(AAResultsWrapperPass, "aa",
|
||||
"Function Alias Analysis Results", false, true)
|
||||
|
||||
FunctionPass *llvm::createAAResultsWrapperPass() {
|
||||
return new AAResultsWrapperPass();
|
||||
}
|
||||
|
||||
/// Run the wrapper pass to rebuild an aggregation over known AA passes.
|
||||
///
|
||||
/// This is the legacy pass manager's interface to the new-style AA results
|
||||
/// aggregation object. Because this is somewhat shoe-horned into the legacy
|
||||
/// pass manager, we hard code all the specific alias analyses available into
|
||||
/// it. While the particular set enabled is configured via commandline flags,
|
||||
/// adding a new alias analysis to LLVM will require adding support for it to
|
||||
/// this list.
|
||||
bool AAResultsWrapperPass::runOnFunction(Function &F) {
|
||||
// NB! This *must* be reset before adding new AA results to the new
|
||||
// AAResults object because in the legacy pass manager, each instance
|
||||
// of these will refer to the *same* immutable analyses, registering and
|
||||
// unregistering themselves with them. We need to carefully tear down the
|
||||
// previous object first, in this case replacing it with an empty one, before
|
||||
// registering new results.
|
||||
AAR.reset(new AAResults());
|
||||
|
||||
// BasicAA is always available for function analyses. Also, we add it first
|
||||
// so that it can trump TBAA results when it proves MustAlias.
|
||||
// FIXME: TBAA should have an explicit mode to support this and then we
|
||||
// should reconsider the ordering here.
|
||||
if (!DisableBasicAA)
|
||||
AAR->addAAResult(getAnalysis<BasicAAWrapperPass>().getResult());
|
||||
|
||||
// Populate the results with the currently available AAs.
|
||||
if (auto *WrapperPass = getAnalysisIfAvailable<ScopedNoAliasAAWrapperPass>())
|
||||
AAR->addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass = getAnalysisIfAvailable<TypeBasedAAWrapperPass>())
|
||||
AAR->addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass =
|
||||
getAnalysisIfAvailable<objcarc::ObjCARCAAWrapperPass>())
|
||||
AAR->addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass = getAnalysisIfAvailable<GlobalsAAWrapperPass>())
|
||||
AAR->addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass = getAnalysisIfAvailable<SCEVAAWrapperPass>())
|
||||
AAR->addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass = getAnalysisIfAvailable<CFLAAWrapperPass>())
|
||||
AAR->addAAResult(WrapperPass->getResult());
|
||||
|
||||
// Analyses don't mutate the IR, so return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
void AAResultsWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<BasicAAWrapperPass>();
|
||||
|
||||
// We also need to mark all the alias analysis passes we will potentially
|
||||
// probe in runOnFunction as used here to ensure the legacy pass manager
|
||||
// preserves them. This hard coding of lists of alias analyses is specific to
|
||||
// the legacy pass manager.
|
||||
AU.addUsedIfAvailable<ScopedNoAliasAAWrapperPass>();
|
||||
AU.addUsedIfAvailable<TypeBasedAAWrapperPass>();
|
||||
AU.addUsedIfAvailable<objcarc::ObjCARCAAWrapperPass>();
|
||||
AU.addUsedIfAvailable<GlobalsAAWrapperPass>();
|
||||
AU.addUsedIfAvailable<SCEVAAWrapperPass>();
|
||||
AU.addUsedIfAvailable<CFLAAWrapperPass>();
|
||||
}
|
||||
|
||||
AAResults llvm::createLegacyPMAAResults(Pass &P, Function &F,
|
||||
BasicAAResult &BAR) {
|
||||
AAResults AAR;
|
||||
|
||||
// Add in our explicitly constructed BasicAA results.
|
||||
if (!DisableBasicAA)
|
||||
AAR.addAAResult(BAR);
|
||||
|
||||
// Populate the results with the other currently available AAs.
|
||||
if (auto *WrapperPass =
|
||||
P.getAnalysisIfAvailable<ScopedNoAliasAAWrapperPass>())
|
||||
AAR.addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass = P.getAnalysisIfAvailable<TypeBasedAAWrapperPass>())
|
||||
AAR.addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass =
|
||||
P.getAnalysisIfAvailable<objcarc::ObjCARCAAWrapperPass>())
|
||||
AAR.addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass = P.getAnalysisIfAvailable<GlobalsAAWrapperPass>())
|
||||
AAR.addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass = P.getAnalysisIfAvailable<SCEVAAWrapperPass>())
|
||||
AAR.addAAResult(WrapperPass->getResult());
|
||||
if (auto *WrapperPass = P.getAnalysisIfAvailable<CFLAAWrapperPass>())
|
||||
AAR.addAAResult(WrapperPass->getResult());
|
||||
|
||||
return AAR;
|
||||
}
|
||||
|
||||
/// isNoAliasCall - Return true if this pointer is returned by a noalias
|
||||
/// function.
|
||||
bool llvm::isNoAliasCall(const Value *V) {
|
||||
|
@ -1,165 +0,0 @@
|
||||
//===- AliasAnalysisCounter.cpp - Alias Analysis Query Counter ------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a pass which can be used to count how many alias queries
|
||||
// are being made and how the alias analysis implementation being used responds.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/AliasAnalysisCounter.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool> PrintAll("count-aa-print-all-queries", cl::ReallyHidden,
|
||||
cl::init(true));
|
||||
static cl::opt<bool> PrintAllFailures("count-aa-print-all-failed-queries",
|
||||
cl::ReallyHidden);
|
||||
|
||||
char AliasAnalysisCounter::ID = 0;
|
||||
INITIALIZE_AG_PASS(AliasAnalysisCounter, AliasAnalysis, "count-aa",
|
||||
"Count Alias Analysis Query Responses", false, true, false)
|
||||
|
||||
ModulePass *llvm::createAliasAnalysisCounterPass() {
|
||||
return new AliasAnalysisCounter();
|
||||
}
|
||||
|
||||
AliasAnalysisCounter::AliasAnalysisCounter() : ModulePass(ID) {
|
||||
initializeAliasAnalysisCounterPass(*PassRegistry::getPassRegistry());
|
||||
No = May = Partial = Must = 0;
|
||||
NoMR = JustRef = JustMod = MR = 0;
|
||||
}
|
||||
|
||||
static void printLine(const char *Desc, unsigned Val, unsigned Sum) {
|
||||
errs() << " " << Val << " " << Desc << " responses (" << Val * 100 / Sum
|
||||
<< "%)\n";
|
||||
}
|
||||
|
||||
AliasAnalysisCounter::~AliasAnalysisCounter() {
|
||||
unsigned AASum = No + May + Partial + Must;
|
||||
unsigned MRSum = NoMR + JustRef + JustMod + MR;
|
||||
if (AASum + MRSum) { // Print a report if any counted queries occurred...
|
||||
errs() << "\n===== Alias Analysis Counter Report =====\n"
|
||||
<< " Analysis counted:\n"
|
||||
<< " " << AASum << " Total Alias Queries Performed\n";
|
||||
if (AASum) {
|
||||
printLine("no alias", No, AASum);
|
||||
printLine("may alias", May, AASum);
|
||||
printLine("partial alias", Partial, AASum);
|
||||
printLine("must alias", Must, AASum);
|
||||
errs() << " Alias Analysis Counter Summary: " << No * 100 / AASum << "%/"
|
||||
<< May * 100 / AASum << "%/" << Partial * 100 / AASum << "%/"
|
||||
<< Must * 100 / AASum << "%\n\n";
|
||||
}
|
||||
|
||||
errs() << " " << MRSum << " Total MRI_Mod/MRI_Ref Queries Performed\n";
|
||||
if (MRSum) {
|
||||
printLine("no mod/ref", NoMR, MRSum);
|
||||
printLine("ref", JustRef, MRSum);
|
||||
printLine("mod", JustMod, MRSum);
|
||||
printLine("mod/ref", MR, MRSum);
|
||||
errs() << " MRI_Mod/MRI_Ref Analysis Counter Summary: "
|
||||
<< NoMR * 100 / MRSum << "%/" << JustRef * 100 / MRSum << "%/"
|
||||
<< JustMod * 100 / MRSum << "%/" << MR * 100 / MRSum << "%\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AliasAnalysisCounter::runOnModule(Module &M) {
|
||||
this->M = &M;
|
||||
InitializeAliasAnalysis(this, &M.getDataLayout());
|
||||
return false;
|
||||
}
|
||||
|
||||
void AliasAnalysisCounter::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AliasAnalysis::getAnalysisUsage(AU);
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
void *AliasAnalysisCounter::getAdjustedAnalysisPointer(AnalysisID PI) {
|
||||
if (PI == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis *)this;
|
||||
return this;
|
||||
}
|
||||
|
||||
AliasResult AliasAnalysisCounter::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
AliasResult R = getAnalysis<AliasAnalysis>().alias(LocA, LocB);
|
||||
|
||||
const char *AliasString = nullptr;
|
||||
switch (R) {
|
||||
case NoAlias:
|
||||
No++;
|
||||
AliasString = "No alias";
|
||||
break;
|
||||
case MayAlias:
|
||||
May++;
|
||||
AliasString = "May alias";
|
||||
break;
|
||||
case PartialAlias:
|
||||
Partial++;
|
||||
AliasString = "Partial alias";
|
||||
break;
|
||||
case MustAlias:
|
||||
Must++;
|
||||
AliasString = "Must alias";
|
||||
break;
|
||||
}
|
||||
|
||||
if (PrintAll || (PrintAllFailures && R == MayAlias)) {
|
||||
errs() << AliasString << ":\t";
|
||||
errs() << "[" << LocA.Size << "B] ";
|
||||
LocA.Ptr->printAsOperand(errs(), true, M);
|
||||
errs() << ", ";
|
||||
errs() << "[" << LocB.Size << "B] ";
|
||||
LocB.Ptr->printAsOperand(errs(), true, M);
|
||||
errs() << "\n";
|
||||
}
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
ModRefInfo AliasAnalysisCounter::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo R = getAnalysis<AliasAnalysis>().getModRefInfo(CS, Loc);
|
||||
|
||||
const char *MRString = nullptr;
|
||||
switch (R) {
|
||||
case MRI_NoModRef:
|
||||
NoMR++;
|
||||
MRString = "MRI_NoModRef";
|
||||
break;
|
||||
case MRI_Ref:
|
||||
JustRef++;
|
||||
MRString = "JustRef";
|
||||
break;
|
||||
case MRI_Mod:
|
||||
JustMod++;
|
||||
MRString = "JustMod";
|
||||
break;
|
||||
case MRI_ModRef:
|
||||
MR++;
|
||||
MRString = "MRI_ModRef";
|
||||
break;
|
||||
}
|
||||
|
||||
if (PrintAll || (PrintAllFailures && R == MRI_ModRef)) {
|
||||
errs() << MRString << ": Ptr: ";
|
||||
errs() << "[" << Loc.Size << "B] ";
|
||||
Loc.Ptr->printAsOperand(errs(), true, M);
|
||||
errs() << "\t<->" << *CS.getInstruction() << '\n';
|
||||
}
|
||||
return R;
|
||||
}
|
@ -59,7 +59,7 @@ namespace {
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ namespace {
|
||||
char AAEval::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(AAEval, "aa-eval",
|
||||
"Exhaustive Alias Analysis Precision Evaluator", false, true)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(AAEval, "aa-eval",
|
||||
"Exhaustive Alias Analysis Precision Evaluator", false, true)
|
||||
|
||||
@ -142,7 +142,7 @@ static inline bool isInterestingPointer(Value *V) {
|
||||
|
||||
bool AAEval::runOnFunction(Function &F) {
|
||||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
SetVector<Value *> Pointers;
|
||||
SetVector<CallSite> CallSites;
|
||||
|
@ -649,11 +649,12 @@ namespace {
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F) override {
|
||||
Tracker = new AliasSetTracker(getAnalysis<AliasAnalysis>());
|
||||
auto &AAWP = getAnalysis<AAResultsWrapperPass>();
|
||||
Tracker = new AliasSetTracker(AAWP.getAAResults());
|
||||
|
||||
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
|
||||
Tracker->add(&*I);
|
||||
@ -667,6 +668,6 @@ namespace {
|
||||
char AliasSetPrinter::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(AliasSetPrinter, "print-alias-sets",
|
||||
"Alias Set Printer", false, true)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(AliasSetPrinter, "print-alias-sets",
|
||||
"Alias Set Printer", false, true)
|
||||
|
@ -20,12 +20,9 @@ using namespace llvm;
|
||||
|
||||
/// initializeAnalysis - Initialize all passes linked into the Analysis library.
|
||||
void llvm::initializeAnalysis(PassRegistry &Registry) {
|
||||
initializeAliasAnalysisAnalysisGroup(Registry);
|
||||
initializeAliasAnalysisCounterPass(Registry);
|
||||
initializeAAEvalPass(Registry);
|
||||
initializeAliasSetPrinterPass(Registry);
|
||||
initializeNoAAPass(Registry);
|
||||
initializeBasicAliasAnalysisPass(Registry);
|
||||
initializeBasicAAWrapperPassPass(Registry);
|
||||
initializeBlockFrequencyInfoWrapperPassPass(Registry);
|
||||
initializeBranchProbabilityInfoWrapperPassPass(Registry);
|
||||
initializeCallGraphWrapperPassPass(Registry);
|
||||
@ -36,7 +33,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
|
||||
initializeCFGPrinterPass(Registry);
|
||||
initializeCFGOnlyViewerPass(Registry);
|
||||
initializeCFGOnlyPrinterPass(Registry);
|
||||
initializeCFLAliasAnalysisPass(Registry);
|
||||
initializeCFLAAWrapperPassPass(Registry);
|
||||
initializeDependenceAnalysisPass(Registry);
|
||||
initializeDelinearizationPass(Registry);
|
||||
initializeDemandedBitsPass(Registry);
|
||||
@ -50,7 +47,8 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
|
||||
initializePostDomPrinterPass(Registry);
|
||||
initializePostDomOnlyViewerPass(Registry);
|
||||
initializePostDomOnlyPrinterPass(Registry);
|
||||
initializeGlobalsModRefPass(Registry);
|
||||
initializeAAResultsWrapperPassPass(Registry);
|
||||
initializeGlobalsAAWrapperPassPass(Registry);
|
||||
initializeIVUsersPass(Registry);
|
||||
initializeInstCountPass(Registry);
|
||||
initializeIntervalPartitionPass(Registry);
|
||||
@ -61,18 +59,18 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
|
||||
initializeMemDerefPrinterPass(Registry);
|
||||
initializeMemoryDependenceAnalysisPass(Registry);
|
||||
initializeModuleDebugInfoPrinterPass(Registry);
|
||||
initializeObjCARCAliasAnalysisPass(Registry);
|
||||
initializeObjCARCAAWrapperPassPass(Registry);
|
||||
initializePostDominatorTreePass(Registry);
|
||||
initializeRegionInfoPassPass(Registry);
|
||||
initializeRegionViewerPass(Registry);
|
||||
initializeRegionPrinterPass(Registry);
|
||||
initializeRegionOnlyViewerPass(Registry);
|
||||
initializeRegionOnlyPrinterPass(Registry);
|
||||
initializeSCEVAAWrapperPassPass(Registry);
|
||||
initializeScalarEvolutionWrapperPassPass(Registry);
|
||||
initializeScalarEvolutionAliasAnalysisPass(Registry);
|
||||
initializeTargetTransformInfoWrapperPassPass(Registry);
|
||||
initializeTypeBasedAliasAnalysisPass(Registry);
|
||||
initializeScopedNoAliasAAPass(Registry);
|
||||
initializeTypeBasedAAWrapperPassPass(Registry);
|
||||
initializeScopedNoAliasAAWrapperPassPass(Registry);
|
||||
}
|
||||
|
||||
void LLVMInitializeAnalysis(LLVMPassRegistryRef R) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
@ -177,7 +178,7 @@ static bool isObjectSize(const Value *V, uint64_t Size, const DataLayout &DL,
|
||||
///
|
||||
/// Note that this looks through extends, so the high bits may not be
|
||||
/// represented in the result.
|
||||
/*static*/ const Value *BasicAliasAnalysis::GetLinearExpression(
|
||||
/*static*/ const Value *BasicAAResult::GetLinearExpression(
|
||||
const Value *V, APInt &Scale, APInt &Offset, unsigned &ZExtBits,
|
||||
unsigned &SExtBits, const DataLayout &DL, unsigned Depth,
|
||||
AssumptionCache *AC, DominatorTree *DT, bool &NSW, bool &NUW) {
|
||||
@ -331,7 +332,7 @@ static bool isObjectSize(const Value *V, uint64_t Size, const DataLayout &DL,
|
||||
/// GetUnderlyingObject and DecomposeGEPExpression must use the same search
|
||||
/// depth (MaxLookupSearchDepth). When DataLayout not is around, it just looks
|
||||
/// through pointer casts.
|
||||
/*static*/ const Value *BasicAliasAnalysis::DecomposeGEPExpression(
|
||||
/*static*/ const Value *BasicAAResult::DecomposeGEPExpression(
|
||||
const Value *V, int64_t &BaseOffs,
|
||||
SmallVectorImpl<VariableGEPIndex> &VarIndices, bool &MaxLookupReached,
|
||||
const DataLayout &DL, AssumptionCache *AC, DominatorTree *DT) {
|
||||
@ -466,40 +467,21 @@ static bool isObjectSize(const Value *V, uint64_t Size, const DataLayout &DL,
|
||||
return V;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BasicAliasAnalysis Pass
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Register the pass...
|
||||
char BasicAliasAnalysis::ID = 0;
|
||||
INITIALIZE_AG_PASS_BEGIN(BasicAliasAnalysis, AliasAnalysis, "basicaa",
|
||||
"Basic Alias Analysis (stateless AA impl)", false,
|
||||
true, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_AG_PASS_END(BasicAliasAnalysis, AliasAnalysis, "basicaa",
|
||||
"Basic Alias Analysis (stateless AA impl)", false, true,
|
||||
false)
|
||||
|
||||
ImmutablePass *llvm::createBasicAliasAnalysisPass() {
|
||||
return new BasicAliasAnalysis();
|
||||
}
|
||||
|
||||
/// Returns whether the given pointer value points to memory that is local to
|
||||
/// the function, with global constants being considered local to all
|
||||
/// functions.
|
||||
bool BasicAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) {
|
||||
bool BasicAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) {
|
||||
assert(Visited.empty() && "Visited must be cleared after use!");
|
||||
|
||||
unsigned MaxLookup = 8;
|
||||
SmallVector<const Value *, 16> Worklist;
|
||||
Worklist.push_back(Loc.Ptr);
|
||||
do {
|
||||
const Value *V = GetUnderlyingObject(Worklist.pop_back_val(), *DL);
|
||||
const Value *V = GetUnderlyingObject(Worklist.pop_back_val(), DL);
|
||||
if (!Visited.insert(V).second) {
|
||||
Visited.clear();
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
|
||||
}
|
||||
|
||||
// An alloca instruction defines local memory.
|
||||
@ -513,7 +495,7 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
// others. GV may even be a declaration, not a definition.
|
||||
if (!GV->isConstant()) {
|
||||
Visited.clear();
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -531,7 +513,7 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
// Don't bother inspecting phi nodes with many operands.
|
||||
if (PN->getNumIncomingValues() > MaxLookup) {
|
||||
Visited.clear();
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
|
||||
}
|
||||
for (Value *IncValue : PN->incoming_values())
|
||||
Worklist.push_back(IncValue);
|
||||
@ -540,7 +522,7 @@ bool BasicAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
|
||||
// Otherwise be conservative.
|
||||
Visited.clear();
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
|
||||
|
||||
} while (!Worklist.empty() && --MaxLookup);
|
||||
|
||||
@ -566,8 +548,7 @@ static bool isMemsetPattern16(const Function *MS,
|
||||
}
|
||||
|
||||
/// Returns the behavior when calling the given call site.
|
||||
FunctionModRefBehavior
|
||||
BasicAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
||||
FunctionModRefBehavior BasicAAResult::getModRefBehavior(ImmutableCallSite CS) {
|
||||
if (CS.doesNotAccessMemory())
|
||||
// Can't do better than this.
|
||||
return FMRB_DoesNotAccessMemory;
|
||||
@ -582,14 +563,13 @@ BasicAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
||||
if (CS.onlyAccessesArgMemory())
|
||||
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
|
||||
|
||||
// The AliasAnalysis base class has some smarts, lets use them.
|
||||
return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
|
||||
// The AAResultBase base class has some smarts, lets use them.
|
||||
return FunctionModRefBehavior(AAResultBase::getModRefBehavior(CS) & Min);
|
||||
}
|
||||
|
||||
/// Returns the behavior when calling the given function. For use when the call
|
||||
/// site is not known.
|
||||
FunctionModRefBehavior
|
||||
BasicAliasAnalysis::getModRefBehavior(const Function *F) {
|
||||
FunctionModRefBehavior BasicAAResult::getModRefBehavior(const Function *F) {
|
||||
// If the function declares it doesn't access memory, we can't do better.
|
||||
if (F->doesNotAccessMemory())
|
||||
return FMRB_DoesNotAccessMemory;
|
||||
@ -603,17 +583,15 @@ BasicAliasAnalysis::getModRefBehavior(const Function *F) {
|
||||
if (F->onlyAccessesArgMemory())
|
||||
Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
|
||||
|
||||
const TargetLibraryInfo &TLI =
|
||||
getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
if (isMemsetPattern16(F, TLI))
|
||||
Min = FMRB_OnlyAccessesArgumentPointees;
|
||||
|
||||
// Otherwise be conservative.
|
||||
return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min);
|
||||
return FunctionModRefBehavior(AAResultBase::getModRefBehavior(F) & Min);
|
||||
}
|
||||
|
||||
ModRefInfo BasicAliasAnalysis::getArgModRefInfo(ImmutableCallSite CS,
|
||||
unsigned ArgIdx) {
|
||||
ModRefInfo BasicAAResult::getArgModRefInfo(ImmutableCallSite CS,
|
||||
unsigned ArgIdx) {
|
||||
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction()))
|
||||
switch (II->getIntrinsicID()) {
|
||||
default:
|
||||
@ -631,14 +609,14 @@ ModRefInfo BasicAliasAnalysis::getArgModRefInfo(ImmutableCallSite CS,
|
||||
// LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
|
||||
// whenever possible.
|
||||
if (CS.getCalledFunction() &&
|
||||
isMemsetPattern16(CS.getCalledFunction(), *TLI)) {
|
||||
isMemsetPattern16(CS.getCalledFunction(), TLI)) {
|
||||
assert((ArgIdx == 0 || ArgIdx == 1) &&
|
||||
"Invalid argument index for memset_pattern16");
|
||||
return ArgIdx ? MRI_Ref : MRI_Mod;
|
||||
}
|
||||
// FIXME: Handle memset_pattern4 and memset_pattern8 also.
|
||||
|
||||
return AliasAnalysis::getArgModRefInfo(CS, ArgIdx);
|
||||
return AAResultBase::getArgModRefInfo(CS, ArgIdx);
|
||||
}
|
||||
|
||||
static bool isAssumeIntrinsic(ImmutableCallSite CS) {
|
||||
@ -649,23 +627,18 @@ static bool isAssumeIntrinsic(ImmutableCallSite CS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BasicAliasAnalysis::doInitialization(Module &M) {
|
||||
InitializeAliasAnalysis(this, &M.getDataLayout());
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Checks to see if the specified callsite can clobber the specified memory
|
||||
/// object.
|
||||
///
|
||||
/// Since we only look at local properties of this function, we really can't
|
||||
/// say much about this query. We do, however, use simple "address taken"
|
||||
/// analysis on local objects.
|
||||
ModRefInfo BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
assert(notDifferentParent(CS.getInstruction(), Loc.Ptr) &&
|
||||
"AliasAnalysis query involving multiple functions!");
|
||||
|
||||
const Value *Object = GetUnderlyingObject(Loc.Ptr, *DL);
|
||||
const Value *Object = GetUnderlyingObject(Loc.Ptr, DL);
|
||||
|
||||
// If this is a tail call and Loc.Ptr points to a stack location, we know that
|
||||
// the tail call cannot access or modify the local stack.
|
||||
@ -697,7 +670,9 @@ ModRefInfo BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
// is impossible to alias the pointer we're checking. If not, we have to
|
||||
// assume that the call could touch the pointer, even though it doesn't
|
||||
// escape.
|
||||
if (!isNoAlias(MemoryLocation(*CI), MemoryLocation(Object))) {
|
||||
AliasResult AR =
|
||||
getBestAAResults().alias(MemoryLocation(*CI), MemoryLocation(Object));
|
||||
if (AR) {
|
||||
PassedAsArg = true;
|
||||
break;
|
||||
}
|
||||
@ -713,20 +688,20 @@ ModRefInfo BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
if (isAssumeIntrinsic(CS))
|
||||
return MRI_NoModRef;
|
||||
|
||||
// The AliasAnalysis base class has some smarts, lets use them.
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
// The AAResultBase base class has some smarts, lets use them.
|
||||
return AAResultBase::getModRefInfo(CS, Loc);
|
||||
}
|
||||
|
||||
ModRefInfo BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
ModRefInfo BasicAAResult::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
// While the assume intrinsic is marked as arbitrarily writing so that
|
||||
// proper control dependencies will be maintained, it never aliases any
|
||||
// particular memory location.
|
||||
if (isAssumeIntrinsic(CS1) || isAssumeIntrinsic(CS2))
|
||||
return MRI_NoModRef;
|
||||
|
||||
// The AliasAnalysis base class has some smarts, lets use them.
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
// The AAResultBase base class has some smarts, lets use them.
|
||||
return AAResultBase::getModRefInfo(CS1, CS2);
|
||||
}
|
||||
|
||||
/// Provide ad-hoc rules to disambiguate accesses through two GEP operators,
|
||||
@ -829,34 +804,15 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
|
||||
/// We know that V1 is a GEP, but we don't know anything about V2.
|
||||
/// UnderlyingV1 is GetUnderlyingObject(GEP1, DL), UnderlyingV2 is the same for
|
||||
/// V2.
|
||||
AliasResult BasicAliasAnalysis::aliasGEP(
|
||||
const GEPOperator *GEP1, uint64_t V1Size, const AAMDNodes &V1AAInfo,
|
||||
const Value *V2, uint64_t V2Size, const AAMDNodes &V2AAInfo,
|
||||
const Value *UnderlyingV1, const Value *UnderlyingV2) {
|
||||
AliasResult BasicAAResult::aliasGEP(const GEPOperator *GEP1, uint64_t V1Size,
|
||||
const AAMDNodes &V1AAInfo, const Value *V2,
|
||||
uint64_t V2Size, const AAMDNodes &V2AAInfo,
|
||||
const Value *UnderlyingV1,
|
||||
const Value *UnderlyingV2) {
|
||||
int64_t GEP1BaseOffset;
|
||||
bool GEP1MaxLookupReached;
|
||||
SmallVector<VariableGEPIndex, 4> GEP1VariableIndices;
|
||||
|
||||
// We have to get two AssumptionCaches here because GEP1 and V2 may be from
|
||||
// different functions.
|
||||
// FIXME: This really doesn't make any sense. We get a dominator tree below
|
||||
// that can only refer to a single function. But this function (aliasGEP) is
|
||||
// a method on an immutable pass that can be called when there *isn't*
|
||||
// a single function. The old pass management layer makes this "work", but
|
||||
// this isn't really a clean solution.
|
||||
AssumptionCacheTracker &ACT = getAnalysis<AssumptionCacheTracker>();
|
||||
AssumptionCache *AC1 = nullptr, *AC2 = nullptr;
|
||||
if (auto *GEP1I = dyn_cast<Instruction>(GEP1))
|
||||
AC1 = &ACT.getAssumptionCache(
|
||||
const_cast<Function &>(*GEP1I->getParent()->getParent()));
|
||||
if (auto *I2 = dyn_cast<Instruction>(V2))
|
||||
AC2 = &ACT.getAssumptionCache(
|
||||
const_cast<Function &>(*I2->getParent()->getParent()));
|
||||
|
||||
DominatorTreeWrapperPass *DTWP =
|
||||
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
|
||||
DominatorTree *DT = DTWP ? &DTWP->getDomTree() : nullptr;
|
||||
|
||||
// If we have two gep instructions with must-alias or not-alias'ing base
|
||||
// pointers, figure out if the indexes to the GEP tell us anything about the
|
||||
// derived pointer.
|
||||
@ -880,15 +836,15 @@ AliasResult BasicAliasAnalysis::aliasGEP(
|
||||
SmallVector<VariableGEPIndex, 4> GEP2VariableIndices;
|
||||
const Value *GEP2BasePtr =
|
||||
DecomposeGEPExpression(GEP2, GEP2BaseOffset, GEP2VariableIndices,
|
||||
GEP2MaxLookupReached, *DL, AC2, DT);
|
||||
GEP2MaxLookupReached, DL, &AC, DT);
|
||||
const Value *GEP1BasePtr =
|
||||
DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices,
|
||||
GEP1MaxLookupReached, *DL, AC1, DT);
|
||||
GEP1MaxLookupReached, DL, &AC, DT);
|
||||
// DecomposeGEPExpression and GetUnderlyingObject should return the
|
||||
// same result except when DecomposeGEPExpression has no DataLayout.
|
||||
// FIXME: They always have a DataLayout so this should become an
|
||||
// assert.
|
||||
if (GEP1BasePtr != UnderlyingV1 || GEP2BasePtr != UnderlyingV2) {
|
||||
assert(!DL &&
|
||||
"DecomposeGEPExpression and GetUnderlyingObject disagree!");
|
||||
return MayAlias;
|
||||
}
|
||||
// If the max search depth is reached the result is undefined
|
||||
@ -913,27 +869,27 @@ AliasResult BasicAliasAnalysis::aliasGEP(
|
||||
// about the relation of the resulting pointer.
|
||||
const Value *GEP1BasePtr =
|
||||
DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices,
|
||||
GEP1MaxLookupReached, *DL, AC1, DT);
|
||||
GEP1MaxLookupReached, DL, &AC, DT);
|
||||
|
||||
int64_t GEP2BaseOffset;
|
||||
bool GEP2MaxLookupReached;
|
||||
SmallVector<VariableGEPIndex, 4> GEP2VariableIndices;
|
||||
const Value *GEP2BasePtr =
|
||||
DecomposeGEPExpression(GEP2, GEP2BaseOffset, GEP2VariableIndices,
|
||||
GEP2MaxLookupReached, *DL, AC2, DT);
|
||||
GEP2MaxLookupReached, DL, &AC, DT);
|
||||
|
||||
// DecomposeGEPExpression and GetUnderlyingObject should return the
|
||||
// same result except when DecomposeGEPExpression has no DataLayout.
|
||||
// FIXME: They always have a DataLayout so this should become an assert.
|
||||
if (GEP1BasePtr != UnderlyingV1 || GEP2BasePtr != UnderlyingV2) {
|
||||
assert(!DL && "DecomposeGEPExpression and GetUnderlyingObject disagree!");
|
||||
return MayAlias;
|
||||
}
|
||||
|
||||
// If we know the two GEPs are based off of the exact same pointer (and not
|
||||
// just the same underlying object), see if that tells us anything about
|
||||
// the resulting pointers.
|
||||
if (DL && GEP1->getPointerOperand() == GEP2->getPointerOperand()) {
|
||||
AliasResult R = aliasSameBasePointerGEPs(GEP1, V1Size, GEP2, V2Size, *DL);
|
||||
if (GEP1->getPointerOperand() == GEP2->getPointerOperand()) {
|
||||
AliasResult R = aliasSameBasePointerGEPs(GEP1, V1Size, GEP2, V2Size, DL);
|
||||
// If we couldn't find anything interesting, don't abandon just yet.
|
||||
if (R != MayAlias)
|
||||
return R;
|
||||
@ -970,12 +926,12 @@ AliasResult BasicAliasAnalysis::aliasGEP(
|
||||
|
||||
const Value *GEP1BasePtr =
|
||||
DecomposeGEPExpression(GEP1, GEP1BaseOffset, GEP1VariableIndices,
|
||||
GEP1MaxLookupReached, *DL, AC1, DT);
|
||||
GEP1MaxLookupReached, DL, &AC, DT);
|
||||
|
||||
// DecomposeGEPExpression and GetUnderlyingObject should return the
|
||||
// same result except when DecomposeGEPExpression has no DataLayout.
|
||||
// FIXME: They always have a DataLayout so this should become an assert.
|
||||
if (GEP1BasePtr != UnderlyingV1) {
|
||||
assert(!DL && "DecomposeGEPExpression and GetUnderlyingObject disagree!");
|
||||
return MayAlias;
|
||||
}
|
||||
// If the max search depth is reached the result is undefined
|
||||
@ -1039,8 +995,8 @@ AliasResult BasicAliasAnalysis::aliasGEP(
|
||||
const Value *V = GEP1VariableIndices[i].V;
|
||||
|
||||
bool SignKnownZero, SignKnownOne;
|
||||
ComputeSignBit(const_cast<Value *>(V), SignKnownZero, SignKnownOne, *DL,
|
||||
0, AC1, nullptr, DT);
|
||||
ComputeSignBit(const_cast<Value *>(V), SignKnownZero, SignKnownOne, DL,
|
||||
0, &AC, nullptr, DT);
|
||||
|
||||
// Zero-extension widens the variable, and so forces the sign
|
||||
// bit to zero.
|
||||
@ -1075,7 +1031,7 @@ AliasResult BasicAliasAnalysis::aliasGEP(
|
||||
return NoAlias;
|
||||
|
||||
if (constantOffsetHeuristic(GEP1VariableIndices, V1Size, V2Size,
|
||||
GEP1BaseOffset, DL, AC1, DT))
|
||||
GEP1BaseOffset, &AC, DT))
|
||||
return NoAlias;
|
||||
}
|
||||
|
||||
@ -1103,11 +1059,10 @@ static AliasResult MergeAliasResults(AliasResult A, AliasResult B) {
|
||||
|
||||
/// Provides a bunch of ad-hoc rules to disambiguate a Select instruction
|
||||
/// against another.
|
||||
AliasResult BasicAliasAnalysis::aliasSelect(const SelectInst *SI,
|
||||
uint64_t SISize,
|
||||
const AAMDNodes &SIAAInfo,
|
||||
const Value *V2, uint64_t V2Size,
|
||||
const AAMDNodes &V2AAInfo) {
|
||||
AliasResult BasicAAResult::aliasSelect(const SelectInst *SI, uint64_t SISize,
|
||||
const AAMDNodes &SIAAInfo,
|
||||
const Value *V2, uint64_t V2Size,
|
||||
const AAMDNodes &V2AAInfo) {
|
||||
// If the values are Selects with the same condition, we can do a more precise
|
||||
// check: just check for aliases between the values on corresponding arms.
|
||||
if (const SelectInst *SI2 = dyn_cast<SelectInst>(V2))
|
||||
@ -1136,10 +1091,10 @@ AliasResult BasicAliasAnalysis::aliasSelect(const SelectInst *SI,
|
||||
|
||||
/// Provide a bunch of ad-hoc rules to disambiguate a PHI instruction against
|
||||
/// another.
|
||||
AliasResult BasicAliasAnalysis::aliasPHI(const PHINode *PN, uint64_t PNSize,
|
||||
const AAMDNodes &PNAAInfo,
|
||||
const Value *V2, uint64_t V2Size,
|
||||
const AAMDNodes &V2AAInfo) {
|
||||
AliasResult BasicAAResult::aliasPHI(const PHINode *PN, uint64_t PNSize,
|
||||
const AAMDNodes &PNAAInfo, const Value *V2,
|
||||
uint64_t V2Size,
|
||||
const AAMDNodes &V2AAInfo) {
|
||||
// Track phi nodes we have visited. We use this information when we determine
|
||||
// value equivalence.
|
||||
VisitedPhiBBs.insert(PN->getParent());
|
||||
@ -1242,10 +1197,9 @@ AliasResult BasicAliasAnalysis::aliasPHI(const PHINode *PN, uint64_t PNSize,
|
||||
|
||||
/// Provideis a bunch of ad-hoc rules to disambiguate in common cases, such as
|
||||
/// array references.
|
||||
AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
|
||||
AAMDNodes V1AAInfo, const Value *V2,
|
||||
uint64_t V2Size,
|
||||
AAMDNodes V2AAInfo) {
|
||||
AliasResult BasicAAResult::aliasCheck(const Value *V1, uint64_t V1Size,
|
||||
AAMDNodes V1AAInfo, const Value *V2,
|
||||
uint64_t V2Size, AAMDNodes V2AAInfo) {
|
||||
// If either of the memory references is empty, it doesn't matter what the
|
||||
// pointer values are.
|
||||
if (V1Size == 0 || V2Size == 0)
|
||||
@ -1273,8 +1227,8 @@ AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
|
||||
return NoAlias; // Scalars cannot alias each other
|
||||
|
||||
// Figure out what objects these things are pointing to if we can.
|
||||
const Value *O1 = GetUnderlyingObject(V1, *DL, MaxLookupSearchDepth);
|
||||
const Value *O2 = GetUnderlyingObject(V2, *DL, MaxLookupSearchDepth);
|
||||
const Value *O1 = GetUnderlyingObject(V1, DL, MaxLookupSearchDepth);
|
||||
const Value *O2 = GetUnderlyingObject(V2, DL, MaxLookupSearchDepth);
|
||||
|
||||
// Null values in the default address space don't point to any object, so they
|
||||
// don't alias any other pointer.
|
||||
@ -1323,12 +1277,11 @@ AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
|
||||
|
||||
// If the size of one access is larger than the entire object on the other
|
||||
// side, then we know such behavior is undefined and can assume no alias.
|
||||
if (DL)
|
||||
if ((V1Size != MemoryLocation::UnknownSize &&
|
||||
isObjectSmallerThan(O2, V1Size, *DL, *TLI)) ||
|
||||
(V2Size != MemoryLocation::UnknownSize &&
|
||||
isObjectSmallerThan(O1, V2Size, *DL, *TLI)))
|
||||
return NoAlias;
|
||||
if ((V1Size != MemoryLocation::UnknownSize &&
|
||||
isObjectSmallerThan(O2, V1Size, DL, TLI)) ||
|
||||
(V2Size != MemoryLocation::UnknownSize &&
|
||||
isObjectSmallerThan(O1, V2Size, DL, TLI)))
|
||||
return NoAlias;
|
||||
|
||||
// Check the cache before climbing up use-def chains. This also terminates
|
||||
// otherwise infinitely recursive queries.
|
||||
@ -1382,16 +1335,17 @@ AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
|
||||
// If both pointers are pointing into the same object and one of them
|
||||
// accesses is accessing the entire object, then the accesses must
|
||||
// overlap in some way.
|
||||
if (DL && O1 == O2)
|
||||
if (O1 == O2)
|
||||
if ((V1Size != MemoryLocation::UnknownSize &&
|
||||
isObjectSize(O1, V1Size, *DL, *TLI)) ||
|
||||
isObjectSize(O1, V1Size, DL, TLI)) ||
|
||||
(V2Size != MemoryLocation::UnknownSize &&
|
||||
isObjectSize(O2, V2Size, *DL, *TLI)))
|
||||
isObjectSize(O2, V2Size, DL, TLI)))
|
||||
return AliasCache[Locs] = PartialAlias;
|
||||
|
||||
AliasResult Result =
|
||||
AliasAnalysis::alias(MemoryLocation(V1, V1Size, V1AAInfo),
|
||||
MemoryLocation(V2, V2Size, V2AAInfo));
|
||||
// Recurse back into the best AA results we have, potentially with refined
|
||||
// memory locations. We have already ensured that BasicAA has a MayAlias
|
||||
// cache result for these, so any recursion back into BasicAA won't loop.
|
||||
AliasResult Result = getBestAAResults().alias(Locs.first, Locs.second);
|
||||
return AliasCache[Locs] = Result;
|
||||
}
|
||||
|
||||
@ -1402,8 +1356,8 @@ AliasResult BasicAliasAnalysis::aliasCheck(const Value *V1, uint64_t V1Size,
|
||||
/// visited phi nodes an making sure that the phis cannot reach the value. We
|
||||
/// have to do this because we are looking through phi nodes (That is we say
|
||||
/// noalias(V, phi(VA, VB)) if noalias(V, VA) and noalias(V, VB).
|
||||
bool BasicAliasAnalysis::isValueEqualInPotentialCycles(const Value *V,
|
||||
const Value *V2) {
|
||||
bool BasicAAResult::isValueEqualInPotentialCycles(const Value *V,
|
||||
const Value *V2) {
|
||||
if (V != V2)
|
||||
return false;
|
||||
|
||||
@ -1417,13 +1371,6 @@ bool BasicAliasAnalysis::isValueEqualInPotentialCycles(const Value *V,
|
||||
if (VisitedPhiBBs.size() > MaxNumPhiBBsValueReachabilityCheck)
|
||||
return false;
|
||||
|
||||
// Use dominance or loop info if available.
|
||||
DominatorTreeWrapperPass *DTWP =
|
||||
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
|
||||
DominatorTree *DT = DTWP ? &DTWP->getDomTree() : nullptr;
|
||||
auto *LIWP = getAnalysisIfAvailable<LoopInfoWrapperPass>();
|
||||
LoopInfo *LI = LIWP ? &LIWP->getLoopInfo() : nullptr;
|
||||
|
||||
// Make sure that the visited phis cannot reach the Value. This ensures that
|
||||
// the Values cannot come from different iterations of a potential cycle the
|
||||
// phi nodes could be involved in.
|
||||
@ -1438,7 +1385,7 @@ bool BasicAliasAnalysis::isValueEqualInPotentialCycles(const Value *V,
|
||||
///
|
||||
/// Dest and Src are the variable indices from two decomposed GetElementPtr
|
||||
/// instructions GEP1 and GEP2 which have common base pointers.
|
||||
void BasicAliasAnalysis::GetIndexDifference(
|
||||
void BasicAAResult::GetIndexDifference(
|
||||
SmallVectorImpl<VariableGEPIndex> &Dest,
|
||||
const SmallVectorImpl<VariableGEPIndex> &Src) {
|
||||
if (Src.empty())
|
||||
@ -1474,12 +1421,12 @@ void BasicAliasAnalysis::GetIndexDifference(
|
||||
}
|
||||
}
|
||||
|
||||
bool BasicAliasAnalysis::constantOffsetHeuristic(
|
||||
bool BasicAAResult::constantOffsetHeuristic(
|
||||
const SmallVectorImpl<VariableGEPIndex> &VarIndices, uint64_t V1Size,
|
||||
uint64_t V2Size, int64_t BaseOffset, const DataLayout *DL,
|
||||
AssumptionCache *AC, DominatorTree *DT) {
|
||||
uint64_t V2Size, int64_t BaseOffset, AssumptionCache *AC,
|
||||
DominatorTree *DT) {
|
||||
if (VarIndices.size() != 2 || V1Size == MemoryLocation::UnknownSize ||
|
||||
V2Size == MemoryLocation::UnknownSize || !DL)
|
||||
V2Size == MemoryLocation::UnknownSize)
|
||||
return false;
|
||||
|
||||
const VariableGEPIndex &Var0 = VarIndices[0], &Var1 = VarIndices[1];
|
||||
@ -1499,10 +1446,10 @@ bool BasicAliasAnalysis::constantOffsetHeuristic(
|
||||
bool NSW = true, NUW = true;
|
||||
unsigned V0ZExtBits = 0, V0SExtBits = 0, V1ZExtBits = 0, V1SExtBits = 0;
|
||||
const Value *V0 = GetLinearExpression(Var0.V, V0Scale, V0Offset, V0ZExtBits,
|
||||
V0SExtBits, *DL, 0, AC, DT, NSW, NUW);
|
||||
V0SExtBits, DL, 0, AC, DT, NSW, NUW);
|
||||
NSW = true, NUW = true;
|
||||
const Value *V1 = GetLinearExpression(Var1.V, V1Scale, V1Offset, V1ZExtBits,
|
||||
V1SExtBits, *DL, 0, AC, DT, NSW, NUW);
|
||||
V1SExtBits, DL, 0, AC, DT, NSW, NUW);
|
||||
|
||||
if (V0Scale != V1Scale || V0ZExtBits != V1ZExtBits ||
|
||||
V0SExtBits != V1SExtBits || !isValueEqualInPotentialCycles(V0, V1))
|
||||
@ -1527,3 +1474,58 @@ bool BasicAliasAnalysis::constantOffsetHeuristic(
|
||||
return V1Size + std::abs(BaseOffset) <= MinDiffBytes &&
|
||||
V2Size + std::abs(BaseOffset) <= MinDiffBytes;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// BasicAliasAnalysis Pass
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
char BasicAA::PassID;
|
||||
|
||||
BasicAAResult BasicAA::run(Function &F, AnalysisManager<Function> *AM) {
|
||||
return BasicAAResult(F.getParent()->getDataLayout(),
|
||||
AM->getResult<TargetLibraryAnalysis>(F),
|
||||
AM->getResult<AssumptionAnalysis>(F),
|
||||
AM->getCachedResult<DominatorTreeAnalysis>(F),
|
||||
AM->getCachedResult<LoopAnalysis>(F));
|
||||
}
|
||||
|
||||
char BasicAAWrapperPass::ID = 0;
|
||||
void BasicAAWrapperPass::anchor() {}
|
||||
|
||||
INITIALIZE_PASS_BEGIN(BasicAAWrapperPass, "basicaa",
|
||||
"Basic Alias Analysis (stateless AA impl)", true, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(BasicAAWrapperPass, "basicaa",
|
||||
"Basic Alias Analysis (stateless AA impl)", true, true)
|
||||
|
||||
FunctionPass *llvm::createBasicAAWrapperPass() {
|
||||
return new BasicAAWrapperPass();
|
||||
}
|
||||
|
||||
bool BasicAAWrapperPass::runOnFunction(Function &F) {
|
||||
auto &ACT = getAnalysis<AssumptionCacheTracker>();
|
||||
auto &TLIWP = getAnalysis<TargetLibraryInfoWrapperPass>();
|
||||
auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
|
||||
auto *LIWP = getAnalysisIfAvailable<LoopInfoWrapperPass>();
|
||||
|
||||
Result.reset(new BasicAAResult(F.getParent()->getDataLayout(), TLIWP.getTLI(),
|
||||
ACT.getAssumptionCache(F),
|
||||
DTWP ? &DTWP->getDomTree() : nullptr,
|
||||
LIWP ? &LIWP->getLoopInfo() : nullptr));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void BasicAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
||||
BasicAAResult llvm::createLegacyPMBasicAAResult(Pass &P, Function &F) {
|
||||
return BasicAAResult(
|
||||
F.getParent()->getDataLayout(),
|
||||
P.getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
|
||||
P.getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F));
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/InstVisitor.h"
|
||||
@ -53,18 +53,11 @@ using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "cfl-aa"
|
||||
|
||||
// -- Setting up/registering CFLAA pass -- //
|
||||
char CFLAliasAnalysis::ID = 0;
|
||||
|
||||
INITIALIZE_AG_PASS(CFLAliasAnalysis, AliasAnalysis, "cfl-aa",
|
||||
"CFL-Based AA implementation", false, true, false)
|
||||
|
||||
ImmutablePass *llvm::createCFLAliasAnalysisPass() {
|
||||
return new CFLAliasAnalysis();
|
||||
}
|
||||
CFLAAResult::CFLAAResult(const TargetLibraryInfo &TLI) : AAResultBase(TLI) {}
|
||||
CFLAAResult::CFLAAResult(CFLAAResult &&Arg) : AAResultBase(std::move(Arg)) {}
|
||||
|
||||
// \brief Information we have about a function and would like to keep around
|
||||
struct CFLAliasAnalysis::FunctionInfo {
|
||||
struct CFLAAResult::FunctionInfo {
|
||||
StratifiedSets<Value *> Sets;
|
||||
// Lots of functions have < 4 returns. Adjust as necessary.
|
||||
SmallVector<Value *, 4> ReturnedValues;
|
||||
@ -73,22 +66,6 @@ struct CFLAliasAnalysis::FunctionInfo {
|
||||
: Sets(std::move(S)), ReturnedValues(std::move(RV)) {}
|
||||
};
|
||||
|
||||
CFLAliasAnalysis::CFLAliasAnalysis() : ImmutablePass(ID) {
|
||||
initializeCFLAliasAnalysisPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
CFLAliasAnalysis::~CFLAliasAnalysis() {}
|
||||
|
||||
void CFLAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AliasAnalysis::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
void *CFLAliasAnalysis::getAdjustedAnalysisPointer(const void *ID) {
|
||||
if (ID == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis *)this;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Try to go from a Value* to a Function*. Never returns nullptr.
|
||||
static Optional<Function *> parentFunctionOfValue(Value *);
|
||||
|
||||
@ -177,11 +154,11 @@ struct Edge {
|
||||
|
||||
// \brief Gets the edges our graph should have, based on an Instruction*
|
||||
class GetEdgesVisitor : public InstVisitor<GetEdgesVisitor, void> {
|
||||
CFLAliasAnalysis &AA;
|
||||
CFLAAResult &AA;
|
||||
SmallVectorImpl<Edge> &Output;
|
||||
|
||||
public:
|
||||
GetEdgesVisitor(CFLAliasAnalysis &AA, SmallVectorImpl<Edge> &Output)
|
||||
GetEdgesVisitor(CFLAAResult &AA, SmallVectorImpl<Edge> &Output)
|
||||
: AA(AA), Output(Output) {}
|
||||
|
||||
void visitInstruction(Instruction &) {
|
||||
@ -669,12 +646,10 @@ static Optional<StratifiedAttr> valueToAttrIndex(Value *Val);
|
||||
static EdgeType flipWeight(EdgeType);
|
||||
|
||||
// Gets edges of the given Instruction*, writing them to the SmallVector*.
|
||||
static void argsToEdges(CFLAliasAnalysis &, Instruction *,
|
||||
SmallVectorImpl<Edge> &);
|
||||
static void argsToEdges(CFLAAResult &, Instruction *, SmallVectorImpl<Edge> &);
|
||||
|
||||
// Gets edges of the given ConstantExpr*, writing them to the SmallVector*.
|
||||
static void argsToEdges(CFLAliasAnalysis &, ConstantExpr *,
|
||||
SmallVectorImpl<Edge> &);
|
||||
static void argsToEdges(CFLAAResult &, ConstantExpr *, SmallVectorImpl<Edge> &);
|
||||
|
||||
// Gets the "Level" that one should travel in StratifiedSets
|
||||
// given an EdgeType.
|
||||
@ -682,13 +657,13 @@ static Level directionOfEdgeType(EdgeType);
|
||||
|
||||
// Builds the graph needed for constructing the StratifiedSets for the
|
||||
// given function
|
||||
static void buildGraphFrom(CFLAliasAnalysis &, Function *,
|
||||
static void buildGraphFrom(CFLAAResult &, Function *,
|
||||
SmallVectorImpl<Value *> &, NodeMapT &, GraphT &);
|
||||
|
||||
// Gets the edges of a ConstantExpr as if it was an Instruction. This
|
||||
// function also acts on any nested ConstantExprs, adding the edges
|
||||
// of those to the given SmallVector as well.
|
||||
static void constexprToEdges(CFLAliasAnalysis &, ConstantExpr &,
|
||||
static void constexprToEdges(CFLAAResult &, ConstantExpr &,
|
||||
SmallVectorImpl<Edge> &);
|
||||
|
||||
// Given an Instruction, this will add it to the graph, along with any
|
||||
@ -697,7 +672,7 @@ static void constexprToEdges(CFLAliasAnalysis &, ConstantExpr &,
|
||||
// %0 = load i16* getelementptr ([1 x i16]* @a, 0, 0), align 2
|
||||
// addInstructionToGraph would add both the `load` and `getelementptr`
|
||||
// instructions to the graph appropriately.
|
||||
static void addInstructionToGraph(CFLAliasAnalysis &, Instruction &,
|
||||
static void addInstructionToGraph(CFLAAResult &, Instruction &,
|
||||
SmallVectorImpl<Value *> &, NodeMapT &,
|
||||
GraphT &);
|
||||
|
||||
@ -777,7 +752,7 @@ static EdgeType flipWeight(EdgeType Initial) {
|
||||
llvm_unreachable("Incomplete coverage of EdgeType enum");
|
||||
}
|
||||
|
||||
static void argsToEdges(CFLAliasAnalysis &Analysis, Instruction *Inst,
|
||||
static void argsToEdges(CFLAAResult &Analysis, Instruction *Inst,
|
||||
SmallVectorImpl<Edge> &Output) {
|
||||
assert(hasUsefulEdges(Inst) &&
|
||||
"Expected instructions to have 'useful' edges");
|
||||
@ -785,7 +760,7 @@ static void argsToEdges(CFLAliasAnalysis &Analysis, Instruction *Inst,
|
||||
v.visit(Inst);
|
||||
}
|
||||
|
||||
static void argsToEdges(CFLAliasAnalysis &Analysis, ConstantExpr *CE,
|
||||
static void argsToEdges(CFLAAResult &Analysis, ConstantExpr *CE,
|
||||
SmallVectorImpl<Edge> &Output) {
|
||||
assert(hasUsefulEdges(CE) && "Expected constant expr to have 'useful' edges");
|
||||
GetEdgesVisitor v(Analysis, Output);
|
||||
@ -804,7 +779,7 @@ static Level directionOfEdgeType(EdgeType Weight) {
|
||||
llvm_unreachable("Incomplete switch coverage");
|
||||
}
|
||||
|
||||
static void constexprToEdges(CFLAliasAnalysis &Analysis,
|
||||
static void constexprToEdges(CFLAAResult &Analysis,
|
||||
ConstantExpr &CExprToCollapse,
|
||||
SmallVectorImpl<Edge> &Results) {
|
||||
SmallVector<ConstantExpr *, 4> Worklist;
|
||||
@ -834,7 +809,7 @@ static void constexprToEdges(CFLAliasAnalysis &Analysis,
|
||||
}
|
||||
}
|
||||
|
||||
static void addInstructionToGraph(CFLAliasAnalysis &Analysis, Instruction &Inst,
|
||||
static void addInstructionToGraph(CFLAAResult &Analysis, Instruction &Inst,
|
||||
SmallVectorImpl<Value *> &ReturnedValues,
|
||||
NodeMapT &Map, GraphT &Graph) {
|
||||
const auto findOrInsertNode = [&Map, &Graph](Value *Val) {
|
||||
@ -897,7 +872,7 @@ static void addInstructionToGraph(CFLAliasAnalysis &Analysis, Instruction &Inst,
|
||||
// buy us much that we don't already have. I'd like to add interprocedural
|
||||
// analysis prior to this however, in case that somehow requires the graph
|
||||
// produced by this for efficient execution
|
||||
static void buildGraphFrom(CFLAliasAnalysis &Analysis, Function *Fn,
|
||||
static void buildGraphFrom(CFLAAResult &Analysis, Function *Fn,
|
||||
SmallVectorImpl<Value *> &ReturnedValues,
|
||||
NodeMapT &Map, GraphT &Graph) {
|
||||
for (auto &Bb : Fn->getBasicBlockList())
|
||||
@ -928,7 +903,7 @@ static bool canSkipAddingToSets(Value *Val) {
|
||||
}
|
||||
|
||||
// Builds the graph + StratifiedSets for a function.
|
||||
CFLAliasAnalysis::FunctionInfo CFLAliasAnalysis::buildSetsFrom(Function *Fn) {
|
||||
CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
|
||||
NodeMapT Map;
|
||||
GraphT Graph;
|
||||
SmallVector<Value *, 4> ReturnedValues;
|
||||
@ -1014,7 +989,7 @@ CFLAliasAnalysis::FunctionInfo CFLAliasAnalysis::buildSetsFrom(Function *Fn) {
|
||||
return FunctionInfo(Builder.build(), std::move(ReturnedValues));
|
||||
}
|
||||
|
||||
void CFLAliasAnalysis::scan(Function *Fn) {
|
||||
void CFLAAResult::scan(Function *Fn) {
|
||||
auto InsertPair = Cache.insert(std::make_pair(Fn, Optional<FunctionInfo>()));
|
||||
(void)InsertPair;
|
||||
assert(InsertPair.second &&
|
||||
@ -1025,12 +1000,12 @@ void CFLAliasAnalysis::scan(Function *Fn) {
|
||||
Handles.push_front(FunctionHandle(Fn, this));
|
||||
}
|
||||
|
||||
void CFLAliasAnalysis::evict(Function *Fn) { Cache.erase(Fn); }
|
||||
void CFLAAResult::evict(Function *Fn) { Cache.erase(Fn); }
|
||||
|
||||
/// \brief Ensures that the given function is available in the cache.
|
||||
/// Returns the appropriate entry from the cache.
|
||||
const Optional<CFLAliasAnalysis::FunctionInfo> &
|
||||
CFLAliasAnalysis::ensureCached(Function *Fn) {
|
||||
const Optional<CFLAAResult::FunctionInfo> &
|
||||
CFLAAResult::ensureCached(Function *Fn) {
|
||||
auto Iter = Cache.find(Fn);
|
||||
if (Iter == Cache.end()) {
|
||||
scan(Fn);
|
||||
@ -1041,8 +1016,8 @@ CFLAliasAnalysis::ensureCached(Function *Fn) {
|
||||
return Iter->second;
|
||||
}
|
||||
|
||||
AliasResult CFLAliasAnalysis::query(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
AliasResult CFLAAResult::query(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
auto *ValA = const_cast<Value *>(LocA.Ptr);
|
||||
auto *ValB = const_cast<Value *>(LocB.Ptr);
|
||||
|
||||
@ -1108,7 +1083,37 @@ AliasResult CFLAliasAnalysis::query(const MemoryLocation &LocA,
|
||||
return NoAlias;
|
||||
}
|
||||
|
||||
bool CFLAliasAnalysis::doInitialization(Module &M) {
|
||||
InitializeAliasAnalysis(this, &M.getDataLayout());
|
||||
return true;
|
||||
CFLAAResult CFLAA::run(Function &F, AnalysisManager<Function> *AM) {
|
||||
return CFLAAResult(AM->getResult<TargetLibraryAnalysis>(F));
|
||||
}
|
||||
|
||||
char CFLAA::PassID;
|
||||
|
||||
char CFLAAWrapperPass::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(CFLAAWrapperPass, "cfl-aa", "CFL-Based Alias Analysis",
|
||||
false, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(CFLAAWrapperPass, "cfl-aa", "CFL-Based Alias Analysis",
|
||||
false, true)
|
||||
|
||||
ImmutablePass *llvm::createCFLAAWrapperPass() { return new CFLAAWrapperPass(); }
|
||||
|
||||
CFLAAWrapperPass::CFLAAWrapperPass() : ImmutablePass(ID) {
|
||||
initializeCFLAAWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool CFLAAWrapperPass::doInitialization(Module &M) {
|
||||
Result.reset(
|
||||
new CFLAAResult(getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CFLAAWrapperPass::doFinalization(Module &M) {
|
||||
Result.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
void CFLAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
add_llvm_library(LLVMAnalysis
|
||||
AliasAnalysis.cpp
|
||||
AliasAnalysisCounter.cpp
|
||||
AliasAnalysisEvaluator.cpp
|
||||
AliasSetTracker.cpp
|
||||
Analysis.cpp
|
||||
@ -48,7 +47,6 @@ add_llvm_library(LLVMAnalysis
|
||||
MemoryDependenceAnalysis.cpp
|
||||
MemoryLocation.cpp
|
||||
ModuleDebugInfoPrinter.cpp
|
||||
NoAliasAnalysis.cpp
|
||||
ObjCARCAliasAnalysis.cpp
|
||||
ObjCARCAnalysisUtils.cpp
|
||||
ObjCARCInstKind.cpp
|
||||
|
@ -118,7 +118,7 @@ INITIALIZE_PASS_BEGIN(DependenceAnalysis, "da",
|
||||
"Dependence Analysis", true, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(DependenceAnalysis, "da",
|
||||
"Dependence Analysis", true, true)
|
||||
|
||||
@ -132,7 +132,7 @@ FunctionPass *llvm::createDependenceAnalysisPass() {
|
||||
|
||||
bool DependenceAnalysis::runOnFunction(Function &F) {
|
||||
this->F = &F;
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
return false;
|
||||
@ -145,7 +145,7 @@ void DependenceAnalysis::releaseMemory() {
|
||||
|
||||
void DependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequiredTransitive<AliasAnalysis>();
|
||||
AU.addRequiredTransitive<AAResultsWrapperPass>();
|
||||
AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
|
||||
AU.addRequiredTransitive<LoopInfoWrapperPass>();
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
@ -58,7 +59,7 @@ static cl::opt<bool> EnableUnsafeGlobalsModRefAliasResults(
|
||||
/// general and as pertains to specific globals. We only have this detailed
|
||||
/// information when we know *something* useful about the behavior. If we
|
||||
/// saturate to fully general mod/ref, we remove the info for the function.
|
||||
class GlobalsModRef::FunctionInfo {
|
||||
class GlobalsAAResult::FunctionInfo {
|
||||
typedef SmallDenseMap<const GlobalValue *, ModRefInfo, 16> GlobalInfoMapType;
|
||||
|
||||
/// Build a wrapper struct that has 8-byte alignment. All heap allocations
|
||||
@ -191,56 +192,41 @@ private:
|
||||
PointerIntPair<AlignedMap *, 3, unsigned, AlignedMapPointerTraits> Info;
|
||||
};
|
||||
|
||||
void GlobalsModRef::DeletionCallbackHandle::deleted() {
|
||||
void GlobalsAAResult::DeletionCallbackHandle::deleted() {
|
||||
Value *V = getValPtr();
|
||||
if (auto *F = dyn_cast<Function>(V))
|
||||
GMR.FunctionInfos.erase(F);
|
||||
GAR.FunctionInfos.erase(F);
|
||||
|
||||
if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
|
||||
if (GMR.NonAddressTakenGlobals.erase(GV)) {
|
||||
if (GAR.NonAddressTakenGlobals.erase(GV)) {
|
||||
// This global might be an indirect global. If so, remove it and
|
||||
// remove any AllocRelatedValues for it.
|
||||
if (GMR.IndirectGlobals.erase(GV)) {
|
||||
if (GAR.IndirectGlobals.erase(GV)) {
|
||||
// Remove any entries in AllocsForIndirectGlobals for this global.
|
||||
for (auto I = GMR.AllocsForIndirectGlobals.begin(),
|
||||
E = GMR.AllocsForIndirectGlobals.end();
|
||||
for (auto I = GAR.AllocsForIndirectGlobals.begin(),
|
||||
E = GAR.AllocsForIndirectGlobals.end();
|
||||
I != E; ++I)
|
||||
if (I->second == GV)
|
||||
GMR.AllocsForIndirectGlobals.erase(I);
|
||||
GAR.AllocsForIndirectGlobals.erase(I);
|
||||
}
|
||||
|
||||
// Scan the function info we have collected and remove this global
|
||||
// from all of them.
|
||||
for (auto &FIPair : GMR.FunctionInfos)
|
||||
for (auto &FIPair : GAR.FunctionInfos)
|
||||
FIPair.second.eraseModRefInfoForGlobal(*GV);
|
||||
}
|
||||
}
|
||||
|
||||
// If this is an allocation related to an indirect global, remove it.
|
||||
GMR.AllocsForIndirectGlobals.erase(V);
|
||||
GAR.AllocsForIndirectGlobals.erase(V);
|
||||
|
||||
// And clear out the handle.
|
||||
setValPtr(nullptr);
|
||||
GMR.Handles.erase(I);
|
||||
GAR.Handles.erase(I);
|
||||
// This object is now destroyed!
|
||||
}
|
||||
|
||||
char GlobalsModRef::ID = 0;
|
||||
INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis, "globalsmodref-aa",
|
||||
"Simple mod/ref analysis for globals", false, true,
|
||||
false)
|
||||
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||
INITIALIZE_AG_PASS_END(GlobalsModRef, AliasAnalysis, "globalsmodref-aa",
|
||||
"Simple mod/ref analysis for globals", false, true,
|
||||
false)
|
||||
|
||||
Pass *llvm::createGlobalsModRefPass() { return new GlobalsModRef(); }
|
||||
|
||||
GlobalsModRef::GlobalsModRef() : ModulePass(ID) {
|
||||
initializeGlobalsModRefPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
FunctionModRefBehavior GlobalsModRef::getModRefBehavior(const Function *F) {
|
||||
FunctionModRefBehavior GlobalsAAResult::getModRefBehavior(const Function *F) {
|
||||
FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior;
|
||||
|
||||
if (FunctionInfo *FI = getFunctionInfo(F)) {
|
||||
@ -250,10 +236,11 @@ FunctionModRefBehavior GlobalsModRef::getModRefBehavior(const Function *F) {
|
||||
Min = FMRB_OnlyReadsMemory;
|
||||
}
|
||||
|
||||
return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min);
|
||||
return FunctionModRefBehavior(AAResultBase::getModRefBehavior(F) & Min);
|
||||
}
|
||||
|
||||
FunctionModRefBehavior GlobalsModRef::getModRefBehavior(ImmutableCallSite CS) {
|
||||
FunctionModRefBehavior
|
||||
GlobalsAAResult::getModRefBehavior(ImmutableCallSite CS) {
|
||||
FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior;
|
||||
|
||||
if (const Function *F = CS.getCalledFunction())
|
||||
@ -264,12 +251,13 @@ FunctionModRefBehavior GlobalsModRef::getModRefBehavior(ImmutableCallSite CS) {
|
||||
Min = FMRB_OnlyReadsMemory;
|
||||
}
|
||||
|
||||
return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
|
||||
return FunctionModRefBehavior(AAResultBase::getModRefBehavior(CS) & Min);
|
||||
}
|
||||
|
||||
/// Returns the function info for the function, or null if we don't have
|
||||
/// anything useful to say about it.
|
||||
GlobalsModRef::FunctionInfo *GlobalsModRef::getFunctionInfo(const Function *F) {
|
||||
GlobalsAAResult::FunctionInfo *
|
||||
GlobalsAAResult::getFunctionInfo(const Function *F) {
|
||||
auto I = FunctionInfos.find(F);
|
||||
if (I != FunctionInfos.end())
|
||||
return &I->second;
|
||||
@ -280,7 +268,7 @@ GlobalsModRef::FunctionInfo *GlobalsModRef::getFunctionInfo(const Function *F) {
|
||||
/// GlobalValue's in the program. If none of them have their "address taken"
|
||||
/// (really, their address passed to something nontrivial), record this fact,
|
||||
/// and record the functions that they are used directly in.
|
||||
void GlobalsModRef::AnalyzeGlobals(Module &M) {
|
||||
void GlobalsAAResult::AnalyzeGlobals(Module &M) {
|
||||
SmallPtrSet<Function *, 64> TrackedFunctions;
|
||||
for (Function &F : M)
|
||||
if (F.hasLocalLinkage())
|
||||
@ -337,10 +325,10 @@ void GlobalsModRef::AnalyzeGlobals(Module &M) {
|
||||
/// write to the value.
|
||||
///
|
||||
/// If OkayStoreDest is non-null, stores into this global are allowed.
|
||||
bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
||||
SmallPtrSetImpl<Function *> *Readers,
|
||||
SmallPtrSetImpl<Function *> *Writers,
|
||||
GlobalValue *OkayStoreDest) {
|
||||
bool GlobalsAAResult::AnalyzeUsesOfPointer(Value *V,
|
||||
SmallPtrSetImpl<Function *> *Readers,
|
||||
SmallPtrSetImpl<Function *> *Writers,
|
||||
GlobalValue *OkayStoreDest) {
|
||||
if (!V->getType()->isPointerTy())
|
||||
return true;
|
||||
|
||||
@ -367,7 +355,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
||||
// passing into the function.
|
||||
if (!CS.isCallee(&U)) {
|
||||
// Detect calls to free.
|
||||
if (isFreeCall(I, TLI)) {
|
||||
if (isFreeCall(I, &TLI)) {
|
||||
if (Writers)
|
||||
Writers->insert(CS->getParent()->getParent());
|
||||
} else {
|
||||
@ -392,7 +380,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V,
|
||||
/// Further, all loads out of GV must directly use the memory, not store the
|
||||
/// pointer somewhere. If this is true, we consider the memory pointed to by
|
||||
/// GV to be owned by GV and can disambiguate other pointers from it.
|
||||
bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
|
||||
bool GlobalsAAResult::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
|
||||
// Keep track of values related to the allocation of the memory, f.e. the
|
||||
// value produced by the malloc call and any casts.
|
||||
std::vector<Value *> AllocRelatedValues;
|
||||
@ -420,7 +408,7 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
|
||||
Value *Ptr = GetUnderlyingObject(SI->getOperand(0),
|
||||
GV->getParent()->getDataLayout());
|
||||
|
||||
if (!isAllocLikeFn(Ptr, TLI))
|
||||
if (!isAllocLikeFn(Ptr, &TLI))
|
||||
return false; // Too hard to analyze.
|
||||
|
||||
// Analyze all uses of the allocation. If any of them are used in a
|
||||
@ -455,7 +443,7 @@ bool GlobalsModRef::AnalyzeIndirectGlobalMemory(GlobalValue *GV) {
|
||||
/// immediately stored to and read from. Propagate this information up the call
|
||||
/// graph to all callers and compute the mod/ref info for all memory for each
|
||||
/// function.
|
||||
void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
|
||||
void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) {
|
||||
// We do a bottom-up SCC traversal of the call graph. In other words, we
|
||||
// visit all callees before callers (leaf-first).
|
||||
for (scc_iterator<CallGraph *> I = scc_begin(&CG); !I.isAtEnd(); ++I) {
|
||||
@ -538,7 +526,7 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
|
||||
// We handle calls specially because the graph-relevant aspects are
|
||||
// handled above.
|
||||
if (auto CS = CallSite(&I)) {
|
||||
if (isAllocationFn(&I, TLI) || isFreeCall(&I, TLI)) {
|
||||
if (isAllocationFn(&I, &TLI) || isFreeCall(&I, &TLI)) {
|
||||
// FIXME: It is completely unclear why this is necessary and not
|
||||
// handled by the above graph code.
|
||||
FI.addModRefInfo(MRI_ModRef);
|
||||
@ -546,7 +534,7 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
|
||||
// The callgraph doesn't include intrinsic calls.
|
||||
if (Callee->isIntrinsic()) {
|
||||
FunctionModRefBehavior Behaviour =
|
||||
AliasAnalysis::getModRefBehavior(Callee);
|
||||
AAResultBase::getModRefBehavior(Callee);
|
||||
FI.addModRefInfo(ModRefInfo(Behaviour & MRI_ModRef));
|
||||
}
|
||||
}
|
||||
@ -599,8 +587,8 @@ void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
|
||||
// variables in this way to either not trust AA results while the escape is
|
||||
// active, or to be forced to operate as a module pass that cannot co-exist
|
||||
// with an alias analysis such as GMR.
|
||||
bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
|
||||
const Value *V) {
|
||||
bool GlobalsAAResult::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
|
||||
const Value *V) {
|
||||
// In order to know that the underlying object cannot alias the
|
||||
// non-addr-taken global, we must know that it would have to be an escape.
|
||||
// Thus if the underlying object is a function argument, a load from
|
||||
@ -631,8 +619,8 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
|
||||
Type *GVType = GVar->getInitializer()->getType();
|
||||
Type *InputGVType = InputGVar->getInitializer()->getType();
|
||||
if (GVType->isSized() && InputGVType->isSized() &&
|
||||
(DL->getTypeAllocSize(GVType) > 0) &&
|
||||
(DL->getTypeAllocSize(InputGVType) > 0))
|
||||
(DL.getTypeAllocSize(GVType) > 0) &&
|
||||
(DL.getTypeAllocSize(InputGVType) > 0))
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -651,7 +639,7 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
|
||||
if (auto *LI = dyn_cast<LoadInst>(Input)) {
|
||||
// A pointer loaded from a global would have been captured, and we know
|
||||
// that the global is non-escaping, so no alias.
|
||||
if (isa<GlobalValue>(GetUnderlyingObject(LI->getPointerOperand(), *DL)))
|
||||
if (isa<GlobalValue>(GetUnderlyingObject(LI->getPointerOperand(), DL)))
|
||||
continue;
|
||||
|
||||
// Otherwise, a load could come from anywhere, so bail.
|
||||
@ -665,8 +653,8 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
|
||||
if (++Depth > 4)
|
||||
return false;
|
||||
if (auto *SI = dyn_cast<SelectInst>(Input)) {
|
||||
const Value *LHS = GetUnderlyingObject(SI->getTrueValue(), *DL);
|
||||
const Value *RHS = GetUnderlyingObject(SI->getFalseValue(), *DL);
|
||||
const Value *LHS = GetUnderlyingObject(SI->getTrueValue(), DL);
|
||||
const Value *RHS = GetUnderlyingObject(SI->getFalseValue(), DL);
|
||||
if (Visited.insert(LHS).second)
|
||||
Inputs.push_back(LHS);
|
||||
if (Visited.insert(RHS).second)
|
||||
@ -675,7 +663,7 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
|
||||
}
|
||||
if (auto *PN = dyn_cast<PHINode>(Input)) {
|
||||
for (const Value *Op : PN->incoming_values()) {
|
||||
Op = GetUnderlyingObject(Op, *DL);
|
||||
Op = GetUnderlyingObject(Op, DL);
|
||||
if (Visited.insert(Op).second)
|
||||
Inputs.push_back(Op);
|
||||
}
|
||||
@ -684,7 +672,7 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
|
||||
|
||||
// FIXME: It would be good to handle other obvious no-alias cases here, but
|
||||
// it isn't clear how to do so reasonbly without building a small version
|
||||
// of BasicAA into this code. We could recurse into AliasAnalysis::alias
|
||||
// of BasicAA into this code. We could recurse into AAResultBase::alias
|
||||
// here but that seems likely to go poorly as we're inside the
|
||||
// implementation of such a query. Until then, just conservatievly retun
|
||||
// false.
|
||||
@ -698,11 +686,11 @@ bool GlobalsModRef::isNonEscapingGlobalNoAlias(const GlobalValue *GV,
|
||||
/// alias - If one of the pointers is to a global that we are tracking, and the
|
||||
/// other is some random pointer, we know there cannot be an alias, because the
|
||||
/// address of the global isn't taken.
|
||||
AliasResult GlobalsModRef::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
AliasResult GlobalsAAResult::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
// Get the base object these pointers point to.
|
||||
const Value *UV1 = GetUnderlyingObject(LocA.Ptr, *DL);
|
||||
const Value *UV2 = GetUnderlyingObject(LocB.Ptr, *DL);
|
||||
const Value *UV1 = GetUnderlyingObject(LocA.Ptr, DL);
|
||||
const Value *UV2 = GetUnderlyingObject(LocB.Ptr, DL);
|
||||
|
||||
// If either of the underlying values is a global, they may be non-addr-taken
|
||||
// globals, which we can answer queries about.
|
||||
@ -774,16 +762,15 @@ AliasResult GlobalsModRef::alias(const MemoryLocation &LocA,
|
||||
if ((GV1 || GV2) && GV1 != GV2)
|
||||
return NoAlias;
|
||||
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
}
|
||||
|
||||
ModRefInfo GlobalsModRef::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo GlobalsAAResult::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
unsigned Known = MRI_ModRef;
|
||||
|
||||
// If we are asking for mod/ref info of a direct call with a pointer to a
|
||||
// global we are tracking, return information if we have it.
|
||||
const DataLayout &DL = CS.getCaller()->getParent()->getDataLayout();
|
||||
if (const GlobalValue *GV =
|
||||
dyn_cast<GlobalValue>(GetUnderlyingObject(Loc.Ptr, DL)))
|
||||
if (GV->hasLocalLinkage())
|
||||
@ -794,5 +781,68 @@ ModRefInfo GlobalsModRef::getModRefInfo(ImmutableCallSite CS,
|
||||
|
||||
if (Known == MRI_NoModRef)
|
||||
return MRI_NoModRef; // No need to query other mod/ref analyses
|
||||
return ModRefInfo(Known & AliasAnalysis::getModRefInfo(CS, Loc));
|
||||
return ModRefInfo(Known & AAResultBase::getModRefInfo(CS, Loc));
|
||||
}
|
||||
|
||||
GlobalsAAResult::GlobalsAAResult(const DataLayout &DL,
|
||||
const TargetLibraryInfo &TLI)
|
||||
: AAResultBase(TLI), DL(DL) {}
|
||||
|
||||
GlobalsAAResult::GlobalsAAResult(GlobalsAAResult &&Arg)
|
||||
: AAResultBase(std::move(Arg)), DL(Arg.DL) {}
|
||||
|
||||
/*static*/ GlobalsAAResult
|
||||
GlobalsAAResult::analyzeModule(Module &M, const TargetLibraryInfo &TLI,
|
||||
CallGraph &CG) {
|
||||
GlobalsAAResult Result(M.getDataLayout(), TLI);
|
||||
|
||||
// Find non-addr taken globals.
|
||||
Result.AnalyzeGlobals(M);
|
||||
|
||||
// Propagate on CG.
|
||||
Result.AnalyzeCallGraph(CG, M);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
GlobalsAAResult GlobalsAA::run(Module &M, AnalysisManager<Module> *AM) {
|
||||
return GlobalsAAResult::analyzeModule(M,
|
||||
AM->getResult<TargetLibraryAnalysis>(M),
|
||||
AM->getResult<CallGraphAnalysis>(M));
|
||||
}
|
||||
|
||||
char GlobalsAA::PassID;
|
||||
|
||||
char GlobalsAAWrapperPass::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(GlobalsAAWrapperPass, "globals-aa",
|
||||
"Globals Alias Analysis", false, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(GlobalsAAWrapperPass, "globals-aa",
|
||||
"Globals Alias Analysis", false, true)
|
||||
|
||||
ModulePass *llvm::createGlobalsAAWrapperPass() {
|
||||
return new GlobalsAAWrapperPass();
|
||||
}
|
||||
|
||||
GlobalsAAWrapperPass::GlobalsAAWrapperPass() : ModulePass(ID) {
|
||||
initializeGlobalsAAWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool GlobalsAAWrapperPass::runOnModule(Module &M) {
|
||||
Result.reset(new GlobalsAAResult(GlobalsAAResult::analyzeModule(
|
||||
M, getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
|
||||
getAnalysis<CallGraphWrapperPass>().getCallGraph())));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GlobalsAAWrapperPass::doFinalization(Module &M) {
|
||||
Result.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
void GlobalsAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<CallGraphWrapperPass>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ namespace {
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
@ -167,7 +167,7 @@ INITIALIZE_PASS_BEGIN(Lint, "lint", "Statically lint-checks LLVM IR",
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(Lint, "lint", "Statically lint-checks LLVM IR",
|
||||
false, true)
|
||||
|
||||
@ -181,7 +181,7 @@ INITIALIZE_PASS_END(Lint, "lint", "Statically lint-checks LLVM IR",
|
||||
bool Lint::runOnFunction(Function &F) {
|
||||
Mod = F.getParent();
|
||||
DL = &F.getParent()->getDataLayout();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
|
@ -1802,7 +1802,7 @@ bool LoopAccessAnalysis::runOnFunction(Function &F) {
|
||||
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
|
||||
TLI = TLIP ? &TLIP->getTLI() : nullptr;
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
|
||||
@ -1811,7 +1811,7 @@ bool LoopAccessAnalysis::runOnFunction(Function &F) {
|
||||
|
||||
void LoopAccessAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<ScalarEvolutionWrapperPass>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
|
||||
@ -1823,7 +1823,7 @@ static const char laa_name[] = "Loop Access Analysis";
|
||||
#define LAA_NAME "loop-accesses"
|
||||
|
||||
INITIALIZE_PASS_BEGIN(LoopAccessAnalysis, LAA_NAME, laa_name, false, true)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
||||
|
@ -49,7 +49,7 @@ namespace {
|
||||
void print(raw_ostream &OS, const Module * = nullptr) const override;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequiredTransitive<AliasAnalysis>();
|
||||
AU.addRequiredTransitive<AAResultsWrapperPass>();
|
||||
AU.addRequiredTransitive<MemoryDependenceAnalysis>();
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
@ -65,8 +65,8 @@ char MemoryDependenceAnalysis::ID = 0;
|
||||
// Register this pass...
|
||||
INITIALIZE_PASS_BEGIN(MemoryDependenceAnalysis, "memdep",
|
||||
"Memory Dependence Analysis", false, true)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(MemoryDependenceAnalysis, "memdep",
|
||||
"Memory Dependence Analysis", false, true)
|
||||
@ -94,12 +94,12 @@ void MemoryDependenceAnalysis::releaseMemory() {
|
||||
void MemoryDependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addRequiredTransitive<AliasAnalysis>();
|
||||
AU.addRequiredTransitive<AAResultsWrapperPass>();
|
||||
AU.addRequiredTransitive<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
||||
bool MemoryDependenceAnalysis::runOnFunction(Function &F) {
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
|
||||
DominatorTreeWrapperPass *DTWP =
|
||||
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
|
||||
|
@ -1,92 +0,0 @@
|
||||
//===- NoAliasAnalysis.cpp - Minimal Alias Analysis Impl ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the default implementation of the Alias Analysis interface
|
||||
// that simply returns "I don't know" for all queries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
/// NoAA - This class implements the -no-aa pass, which always returns "I
|
||||
/// don't know" for alias queries. NoAA is unlike other alias analysis
|
||||
/// implementations, in that it does not chain to a previous analysis. As
|
||||
/// such it doesn't follow many of the rules that other alias analyses must.
|
||||
///
|
||||
struct NoAA : public ImmutablePass, public AliasAnalysis {
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
NoAA() : ImmutablePass(ID) {
|
||||
initializeNoAAPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {}
|
||||
|
||||
bool doInitialization(Module &M) override {
|
||||
// Note: NoAA does not call InitializeAliasAnalysis because it's
|
||||
// special and does not support chaining.
|
||||
DL = &M.getDataLayout();
|
||||
return true;
|
||||
}
|
||||
|
||||
AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) override {
|
||||
return MayAlias;
|
||||
}
|
||||
|
||||
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS) override {
|
||||
return FMRB_UnknownModRefBehavior;
|
||||
}
|
||||
FunctionModRefBehavior getModRefBehavior(const Function *F) override {
|
||||
return FMRB_UnknownModRefBehavior;
|
||||
}
|
||||
|
||||
bool pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) override {
|
||||
return false;
|
||||
}
|
||||
ModRefInfo getArgModRefInfo(ImmutableCallSite CS,
|
||||
unsigned ArgIdx) override {
|
||||
return MRI_ModRef;
|
||||
}
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) override {
|
||||
return MRI_ModRef;
|
||||
}
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) override {
|
||||
return MRI_ModRef;
|
||||
}
|
||||
|
||||
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
||||
/// an analysis interface through multiple inheritance. If needed, it
|
||||
/// should override this to adjust the this pointer as needed for the
|
||||
/// specified pass info.
|
||||
void *getAdjustedAnalysisPointer(const void *ID) override {
|
||||
if (ID == &AliasAnalysis::ID)
|
||||
return (AliasAnalysis*)this;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
} // End of anonymous namespace
|
||||
|
||||
// Register this pass...
|
||||
char NoAA::ID = 0;
|
||||
INITIALIZE_AG_PASS(NoAA, AliasAnalysis, "no-aa",
|
||||
"No Alias Analysis (always returns 'may' alias)",
|
||||
true, true, true)
|
||||
|
||||
ImmutablePass *llvm::createNoAAPass() { return new NoAA(); }
|
@ -18,6 +18,9 @@
|
||||
/// used. Naive LLVM IR transformations which would otherwise be
|
||||
/// behavior-preserving may break these assumptions.
|
||||
///
|
||||
/// TODO: Theoretically we could check for dependencies between objc_* calls
|
||||
/// and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/ObjCARCAliasAnalysis.h"
|
||||
@ -34,46 +37,27 @@
|
||||
using namespace llvm;
|
||||
using namespace llvm::objcarc;
|
||||
|
||||
// Register this pass...
|
||||
char ObjCARCAliasAnalysis::ID = 0;
|
||||
INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa",
|
||||
"ObjC-ARC-Based Alias Analysis", false, true, false)
|
||||
|
||||
ImmutablePass *llvm::createObjCARCAliasAnalysisPass() {
|
||||
return new ObjCARCAliasAnalysis();
|
||||
}
|
||||
|
||||
bool ObjCARCAliasAnalysis::doInitialization(Module &M) {
|
||||
InitializeAliasAnalysis(this, &M.getDataLayout());
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AliasAnalysis::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
AliasResult ObjCARCAliasAnalysis::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
if (!EnableARCOpts)
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
|
||||
// First, strip off no-ops, including ObjC-specific no-ops, and try making a
|
||||
// precise alias query.
|
||||
const Value *SA = GetRCIdentityRoot(LocA.Ptr);
|
||||
const Value *SB = GetRCIdentityRoot(LocB.Ptr);
|
||||
AliasResult Result =
|
||||
AliasAnalysis::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
|
||||
MemoryLocation(SB, LocB.Size, LocB.AATags));
|
||||
AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
|
||||
MemoryLocation(SB, LocB.Size, LocB.AATags));
|
||||
if (Result != MayAlias)
|
||||
return Result;
|
||||
|
||||
// If that failed, climb to the underlying object, including climbing through
|
||||
// ObjC-specific no-ops, and try making an imprecise alias query.
|
||||
const Value *UA = GetUnderlyingObjCPtr(SA, *DL);
|
||||
const Value *UB = GetUnderlyingObjCPtr(SB, *DL);
|
||||
const Value *UA = GetUnderlyingObjCPtr(SA, DL);
|
||||
const Value *UB = GetUnderlyingObjCPtr(SB, DL);
|
||||
if (UA != SA || UB != SB) {
|
||||
Result = AliasAnalysis::alias(MemoryLocation(UA), MemoryLocation(UB));
|
||||
Result = AAResultBase::alias(MemoryLocation(UA), MemoryLocation(UB));
|
||||
// We can't use MustAlias or PartialAlias results here because
|
||||
// GetUnderlyingObjCPtr may return an offsetted pointer value.
|
||||
if (Result == NoAlias)
|
||||
@ -85,39 +69,32 @@ AliasResult ObjCARCAliasAnalysis::alias(const MemoryLocation &LocA,
|
||||
return MayAlias;
|
||||
}
|
||||
|
||||
bool ObjCARCAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) {
|
||||
bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) {
|
||||
if (!EnableARCOpts)
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
|
||||
|
||||
// First, strip off no-ops, including ObjC-specific no-ops, and try making
|
||||
// a precise alias query.
|
||||
const Value *S = GetRCIdentityRoot(Loc.Ptr);
|
||||
if (AliasAnalysis::pointsToConstantMemory(
|
||||
if (AAResultBase::pointsToConstantMemory(
|
||||
MemoryLocation(S, Loc.Size, Loc.AATags), OrLocal))
|
||||
return true;
|
||||
|
||||
// If that failed, climb to the underlying object, including climbing through
|
||||
// ObjC-specific no-ops, and try making an imprecise alias query.
|
||||
const Value *U = GetUnderlyingObjCPtr(S, *DL);
|
||||
const Value *U = GetUnderlyingObjCPtr(S, DL);
|
||||
if (U != S)
|
||||
return AliasAnalysis::pointsToConstantMemory(MemoryLocation(U), OrLocal);
|
||||
return AAResultBase::pointsToConstantMemory(MemoryLocation(U), OrLocal);
|
||||
|
||||
// If that failed, fail. We don't need to chain here, since that's covered
|
||||
// by the earlier precise query.
|
||||
return false;
|
||||
}
|
||||
|
||||
FunctionModRefBehavior
|
||||
ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
||||
// We have nothing to do. Just chain to the next AliasAnalysis.
|
||||
return AliasAnalysis::getModRefBehavior(CS);
|
||||
}
|
||||
|
||||
FunctionModRefBehavior
|
||||
ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) {
|
||||
FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) {
|
||||
if (!EnableARCOpts)
|
||||
return AliasAnalysis::getModRefBehavior(F);
|
||||
return AAResultBase::getModRefBehavior(F);
|
||||
|
||||
switch (GetFunctionClass(F)) {
|
||||
case ARCInstKind::NoopCast:
|
||||
@ -126,13 +103,13 @@ ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) {
|
||||
break;
|
||||
}
|
||||
|
||||
return AliasAnalysis::getModRefBehavior(F);
|
||||
return AAResultBase::getModRefBehavior(F);
|
||||
}
|
||||
|
||||
ModRefInfo ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo ObjCARCAAResult::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
if (!EnableARCOpts)
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
return AAResultBase::getModRefInfo(CS, Loc);
|
||||
|
||||
switch (GetBasicARCInstKind(CS.getInstruction())) {
|
||||
case ARCInstKind::Retain:
|
||||
@ -151,12 +128,43 @@ ModRefInfo ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
break;
|
||||
}
|
||||
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
return AAResultBase::getModRefInfo(CS, Loc);
|
||||
}
|
||||
|
||||
ModRefInfo ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
// TODO: Theoretically we could check for dependencies between objc_* calls
|
||||
// and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls.
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
ObjCARCAAResult ObjCARCAA::run(Function &F, AnalysisManager<Function> *AM) {
|
||||
return ObjCARCAAResult(F.getParent()->getDataLayout(),
|
||||
AM->getResult<TargetLibraryAnalysis>(F));
|
||||
}
|
||||
|
||||
char ObjCARCAA::PassID;
|
||||
|
||||
char ObjCARCAAWrapperPass::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(ObjCARCAAWrapperPass, "objc-arc-aa",
|
||||
"ObjC-ARC-Based Alias Analysis", false, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(ObjCARCAAWrapperPass, "objc-arc-aa",
|
||||
"ObjC-ARC-Based Alias Analysis", false, true)
|
||||
|
||||
ImmutablePass *llvm::createObjCARCAAWrapperPass() {
|
||||
return new ObjCARCAAWrapperPass();
|
||||
}
|
||||
|
||||
ObjCARCAAWrapperPass::ObjCARCAAWrapperPass() : ImmutablePass(ID) {
|
||||
initializeObjCARCAAWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool ObjCARCAAWrapperPass::doInitialization(Module &M) {
|
||||
Result.reset(new ObjCARCAAResult(
|
||||
M.getDataLayout(), getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ObjCARCAAWrapperPass::doFinalization(Module &M) {
|
||||
Result.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObjCARCAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
@ -20,66 +20,20 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
using namespace llvm;
|
||||
|
||||
// Register this pass...
|
||||
char ScalarEvolutionAliasAnalysis::ID = 0;
|
||||
INITIALIZE_AG_PASS_BEGIN(ScalarEvolutionAliasAnalysis, AliasAnalysis, "scev-aa",
|
||||
"ScalarEvolution-based Alias Analysis", false, true,
|
||||
false)
|
||||
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
|
||||
INITIALIZE_AG_PASS_END(ScalarEvolutionAliasAnalysis, AliasAnalysis, "scev-aa",
|
||||
"ScalarEvolution-based Alias Analysis", false, true,
|
||||
false)
|
||||
|
||||
FunctionPass *llvm::createScalarEvolutionAliasAnalysisPass() {
|
||||
return new ScalarEvolutionAliasAnalysis();
|
||||
}
|
||||
|
||||
void ScalarEvolutionAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequiredTransitive<ScalarEvolutionWrapperPass>();
|
||||
AU.setPreservesAll();
|
||||
AliasAnalysis::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
bool ScalarEvolutionAliasAnalysis::runOnFunction(Function &F) {
|
||||
InitializeAliasAnalysis(this, &F.getParent()->getDataLayout());
|
||||
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Given an expression, try to find a base value.
|
||||
///
|
||||
/// Returns null if none was found.
|
||||
Value *ScalarEvolutionAliasAnalysis::GetBaseValue(const SCEV *S) {
|
||||
if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
|
||||
// In an addrec, assume that the base will be in the start, rather
|
||||
// than the step.
|
||||
return GetBaseValue(AR->getStart());
|
||||
} else if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(S)) {
|
||||
// If there's a pointer operand, it'll be sorted at the end of the list.
|
||||
const SCEV *Last = A->getOperand(A->getNumOperands() - 1);
|
||||
if (Last->getType()->isPointerTy())
|
||||
return GetBaseValue(Last);
|
||||
} else if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
|
||||
// This is a leaf node.
|
||||
return U->getValue();
|
||||
}
|
||||
// No Identified object found.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AliasResult ScalarEvolutionAliasAnalysis::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
// If either of the memory references is empty, it doesn't matter what the
|
||||
// pointer values are. This allows the code below to ignore this special
|
||||
// case.
|
||||
if (LocA.Size == 0 || LocB.Size == 0)
|
||||
return NoAlias;
|
||||
|
||||
// This is ScalarEvolutionAliasAnalysis. Get the SCEVs!
|
||||
const SCEV *AS = SE->getSCEV(const_cast<Value *>(LocA.Ptr));
|
||||
const SCEV *BS = SE->getSCEV(const_cast<Value *>(LocB.Ptr));
|
||||
// This is SCEVAAResult. Get the SCEVs!
|
||||
const SCEV *AS = SE.getSCEV(const_cast<Value *>(LocA.Ptr));
|
||||
const SCEV *BS = SE.getSCEV(const_cast<Value *>(LocB.Ptr));
|
||||
|
||||
// If they evaluate to the same expression, it's a MustAlias.
|
||||
if (AS == BS)
|
||||
@ -87,20 +41,20 @@ AliasResult ScalarEvolutionAliasAnalysis::alias(const MemoryLocation &LocA,
|
||||
|
||||
// If something is known about the difference between the two addresses,
|
||||
// see if it's enough to prove a NoAlias.
|
||||
if (SE->getEffectiveSCEVType(AS->getType()) ==
|
||||
SE->getEffectiveSCEVType(BS->getType())) {
|
||||
unsigned BitWidth = SE->getTypeSizeInBits(AS->getType());
|
||||
if (SE.getEffectiveSCEVType(AS->getType()) ==
|
||||
SE.getEffectiveSCEVType(BS->getType())) {
|
||||
unsigned BitWidth = SE.getTypeSizeInBits(AS->getType());
|
||||
APInt ASizeInt(BitWidth, LocA.Size);
|
||||
APInt BSizeInt(BitWidth, LocB.Size);
|
||||
|
||||
// Compute the difference between the two pointers.
|
||||
const SCEV *BA = SE->getMinusSCEV(BS, AS);
|
||||
const SCEV *BA = SE.getMinusSCEV(BS, AS);
|
||||
|
||||
// Test whether the difference is known to be great enough that memory of
|
||||
// the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
|
||||
// are non-zero, which is special-cased above.
|
||||
if (ASizeInt.ule(SE->getUnsignedRange(BA).getUnsignedMin()) &&
|
||||
(-BSizeInt).uge(SE->getUnsignedRange(BA).getUnsignedMax()))
|
||||
if (ASizeInt.ule(SE.getUnsignedRange(BA).getUnsignedMin()) &&
|
||||
(-BSizeInt).uge(SE.getUnsignedRange(BA).getUnsignedMax()))
|
||||
return NoAlias;
|
||||
|
||||
// Folding the subtraction while preserving range information can be tricky
|
||||
@ -108,13 +62,13 @@ AliasResult ScalarEvolutionAliasAnalysis::alias(const MemoryLocation &LocA,
|
||||
// and try again to see if things fold better that way.
|
||||
|
||||
// Compute the difference between the two pointers.
|
||||
const SCEV *AB = SE->getMinusSCEV(AS, BS);
|
||||
const SCEV *AB = SE.getMinusSCEV(AS, BS);
|
||||
|
||||
// Test whether the difference is known to be great enough that memory of
|
||||
// the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
|
||||
// are non-zero, which is special-cased above.
|
||||
if (BSizeInt.ule(SE->getUnsignedRange(AB).getUnsignedMin()) &&
|
||||
(-ASizeInt).uge(SE->getUnsignedRange(AB).getUnsignedMax()))
|
||||
if (BSizeInt.ule(SE.getUnsignedRange(AB).getUnsignedMin()) &&
|
||||
(-ASizeInt).uge(SE.getUnsignedRange(AB).getUnsignedMax()))
|
||||
return NoAlias;
|
||||
}
|
||||
|
||||
@ -133,5 +87,62 @@ AliasResult ScalarEvolutionAliasAnalysis::alias(const MemoryLocation &LocA,
|
||||
return NoAlias;
|
||||
|
||||
// Forward the query to the next analysis.
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
}
|
||||
|
||||
/// Given an expression, try to find a base value.
|
||||
///
|
||||
/// Returns null if none was found.
|
||||
Value *SCEVAAResult::GetBaseValue(const SCEV *S) {
|
||||
if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
|
||||
// In an addrec, assume that the base will be in the start, rather
|
||||
// than the step.
|
||||
return GetBaseValue(AR->getStart());
|
||||
} else if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(S)) {
|
||||
// If there's a pointer operand, it'll be sorted at the end of the list.
|
||||
const SCEV *Last = A->getOperand(A->getNumOperands() - 1);
|
||||
if (Last->getType()->isPointerTy())
|
||||
return GetBaseValue(Last);
|
||||
} else if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
|
||||
// This is a leaf node.
|
||||
return U->getValue();
|
||||
}
|
||||
// No Identified object found.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SCEVAAResult SCEVAA::run(Function &F, AnalysisManager<Function> *AM) {
|
||||
return SCEVAAResult(AM->getResult<TargetLibraryAnalysis>(F),
|
||||
AM->getResult<ScalarEvolutionAnalysis>(F));
|
||||
}
|
||||
|
||||
char SCEVAA::PassID;
|
||||
|
||||
char SCEVAAWrapperPass::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(SCEVAAWrapperPass, "scev-aa",
|
||||
"ScalarEvolution-based Alias Analysis", false, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(SCEVAAWrapperPass, "scev-aa",
|
||||
"ScalarEvolution-based Alias Analysis", false, true)
|
||||
|
||||
FunctionPass *llvm::createSCEVAAWrapperPass() {
|
||||
return new SCEVAAWrapperPass();
|
||||
}
|
||||
|
||||
SCEVAAWrapperPass::SCEVAAWrapperPass() : FunctionPass(ID) {
|
||||
initializeSCEVAAWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool SCEVAAWrapperPass::runOnFunction(Function &F) {
|
||||
Result.reset(
|
||||
new SCEVAAResult(getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(),
|
||||
getAnalysis<ScalarEvolutionWrapperPass>().getSE()));
|
||||
return false;
|
||||
}
|
||||
|
||||
void SCEVAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<ScalarEvolutionWrapperPass>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
|
||||
#include "llvm/Analysis/ScopedNoAliasAA.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
@ -72,26 +72,62 @@ public:
|
||||
};
|
||||
} // End of anonymous namespace
|
||||
|
||||
// Register this pass...
|
||||
char ScopedNoAliasAA::ID = 0;
|
||||
INITIALIZE_AG_PASS(ScopedNoAliasAA, AliasAnalysis, "scoped-noalias",
|
||||
"Scoped NoAlias Alias Analysis", false, true, false)
|
||||
AliasResult ScopedNoAliasAAResult::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
if (!EnableScopedNoAlias)
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
|
||||
ImmutablePass *llvm::createScopedNoAliasAAPass() {
|
||||
return new ScopedNoAliasAA();
|
||||
// Get the attached MDNodes.
|
||||
const MDNode *AScopes = LocA.AATags.Scope, *BScopes = LocB.AATags.Scope;
|
||||
|
||||
const MDNode *ANoAlias = LocA.AATags.NoAlias, *BNoAlias = LocB.AATags.NoAlias;
|
||||
|
||||
if (!mayAliasInScopes(AScopes, BNoAlias))
|
||||
return NoAlias;
|
||||
|
||||
if (!mayAliasInScopes(BScopes, ANoAlias))
|
||||
return NoAlias;
|
||||
|
||||
// If they may alias, chain to the next AliasAnalysis.
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
}
|
||||
|
||||
bool ScopedNoAliasAA::doInitialization(Module &M) {
|
||||
InitializeAliasAnalysis(this, &M.getDataLayout());
|
||||
return true;
|
||||
ModRefInfo ScopedNoAliasAAResult::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
if (!EnableScopedNoAlias)
|
||||
return AAResultBase::getModRefInfo(CS, Loc);
|
||||
|
||||
if (!mayAliasInScopes(Loc.AATags.Scope, CS.getInstruction()->getMetadata(
|
||||
LLVMContext::MD_noalias)))
|
||||
return MRI_NoModRef;
|
||||
|
||||
if (!mayAliasInScopes(
|
||||
CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
|
||||
Loc.AATags.NoAlias))
|
||||
return MRI_NoModRef;
|
||||
|
||||
return AAResultBase::getModRefInfo(CS, Loc);
|
||||
}
|
||||
|
||||
void ScopedNoAliasAA::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AliasAnalysis::getAnalysisUsage(AU);
|
||||
ModRefInfo ScopedNoAliasAAResult::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
if (!EnableScopedNoAlias)
|
||||
return AAResultBase::getModRefInfo(CS1, CS2);
|
||||
|
||||
if (!mayAliasInScopes(
|
||||
CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
|
||||
CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
|
||||
return MRI_NoModRef;
|
||||
|
||||
if (!mayAliasInScopes(
|
||||
CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
|
||||
CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
|
||||
return MRI_NoModRef;
|
||||
|
||||
return AAResultBase::getModRefInfo(CS1, CS2);
|
||||
}
|
||||
|
||||
void ScopedNoAliasAA::collectMDInDomain(
|
||||
void ScopedNoAliasAAResult::collectMDInDomain(
|
||||
const MDNode *List, const MDNode *Domain,
|
||||
SmallPtrSetImpl<const MDNode *> &Nodes) const {
|
||||
for (unsigned i = 0, ie = List->getNumOperands(); i != ie; ++i)
|
||||
@ -100,8 +136,8 @@ void ScopedNoAliasAA::collectMDInDomain(
|
||||
Nodes.insert(MD);
|
||||
}
|
||||
|
||||
bool ScopedNoAliasAA::mayAliasInScopes(const MDNode *Scopes,
|
||||
const MDNode *NoAlias) const {
|
||||
bool ScopedNoAliasAAResult::mayAliasInScopes(const MDNode *Scopes,
|
||||
const MDNode *NoAlias) const {
|
||||
if (!Scopes || !NoAlias)
|
||||
return true;
|
||||
|
||||
@ -136,72 +172,40 @@ bool ScopedNoAliasAA::mayAliasInScopes(const MDNode *Scopes,
|
||||
return true;
|
||||
}
|
||||
|
||||
AliasResult ScopedNoAliasAA::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
if (!EnableScopedNoAlias)
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
|
||||
// Get the attached MDNodes.
|
||||
const MDNode *AScopes = LocA.AATags.Scope, *BScopes = LocB.AATags.Scope;
|
||||
|
||||
const MDNode *ANoAlias = LocA.AATags.NoAlias, *BNoAlias = LocB.AATags.NoAlias;
|
||||
|
||||
if (!mayAliasInScopes(AScopes, BNoAlias))
|
||||
return NoAlias;
|
||||
|
||||
if (!mayAliasInScopes(BScopes, ANoAlias))
|
||||
return NoAlias;
|
||||
|
||||
// If they may alias, chain to the next AliasAnalysis.
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
ScopedNoAliasAAResult ScopedNoAliasAA::run(Function &F,
|
||||
AnalysisManager<Function> *AM) {
|
||||
return ScopedNoAliasAAResult(AM->getResult<TargetLibraryAnalysis>(F));
|
||||
}
|
||||
|
||||
bool ScopedNoAliasAA::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) {
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
||||
char ScopedNoAliasAA::PassID;
|
||||
|
||||
char ScopedNoAliasAAWrapperPass::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(ScopedNoAliasAAWrapperPass, "scoped-noalias",
|
||||
"Scoped NoAlias Alias Analysis", false, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(ScopedNoAliasAAWrapperPass, "scoped-noalias",
|
||||
"Scoped NoAlias Alias Analysis", false, true)
|
||||
|
||||
ImmutablePass *llvm::createScopedNoAliasAAWrapperPass() {
|
||||
return new ScopedNoAliasAAWrapperPass();
|
||||
}
|
||||
|
||||
FunctionModRefBehavior
|
||||
ScopedNoAliasAA::getModRefBehavior(ImmutableCallSite CS) {
|
||||
return AliasAnalysis::getModRefBehavior(CS);
|
||||
ScopedNoAliasAAWrapperPass::ScopedNoAliasAAWrapperPass() : ImmutablePass(ID) {
|
||||
initializeScopedNoAliasAAWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
FunctionModRefBehavior ScopedNoAliasAA::getModRefBehavior(const Function *F) {
|
||||
return AliasAnalysis::getModRefBehavior(F);
|
||||
bool ScopedNoAliasAAWrapperPass::doInitialization(Module &M) {
|
||||
Result.reset(new ScopedNoAliasAAResult(
|
||||
getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()));
|
||||
return false;
|
||||
}
|
||||
|
||||
ModRefInfo ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
if (!EnableScopedNoAlias)
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
|
||||
if (!mayAliasInScopes(Loc.AATags.Scope, CS.getInstruction()->getMetadata(
|
||||
LLVMContext::MD_noalias)))
|
||||
return MRI_NoModRef;
|
||||
|
||||
if (!mayAliasInScopes(
|
||||
CS.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
|
||||
Loc.AATags.NoAlias))
|
||||
return MRI_NoModRef;
|
||||
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
bool ScopedNoAliasAAWrapperPass::doFinalization(Module &M) {
|
||||
Result.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
ModRefInfo ScopedNoAliasAA::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
if (!EnableScopedNoAlias)
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
|
||||
if (!mayAliasInScopes(
|
||||
CS1.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
|
||||
CS2.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
|
||||
return MRI_NoModRef;
|
||||
|
||||
if (!mayAliasInScopes(
|
||||
CS2.getInstruction()->getMetadata(LLVMContext::MD_alias_scope),
|
||||
CS1.getInstruction()->getMetadata(LLVMContext::MD_noalias)))
|
||||
return MRI_NoModRef;
|
||||
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
void ScopedNoAliasAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
||||
|
@ -122,6 +122,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/TypeBasedAliasAnalysis.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
@ -269,25 +270,6 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
// Register this pass...
|
||||
char TypeBasedAliasAnalysis::ID = 0;
|
||||
INITIALIZE_AG_PASS(TypeBasedAliasAnalysis, AliasAnalysis, "tbaa",
|
||||
"Type-Based Alias Analysis", false, true, false)
|
||||
|
||||
ImmutablePass *llvm::createTypeBasedAliasAnalysisPass() {
|
||||
return new TypeBasedAliasAnalysis();
|
||||
}
|
||||
|
||||
bool TypeBasedAliasAnalysis::doInitialization(Module &M) {
|
||||
InitializeAliasAnalysis(this, &M.getDataLayout());
|
||||
return true;
|
||||
}
|
||||
|
||||
void TypeBasedAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AliasAnalysis::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
/// Check the first operand of the tbaa tag node, if it is a MDNode, we treat
|
||||
/// it as struct-path aware TBAA format, otherwise, we treat it as scalar TBAA
|
||||
/// format.
|
||||
@ -297,145 +279,36 @@ static bool isStructPathTBAA(const MDNode *MD) {
|
||||
return isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3;
|
||||
}
|
||||
|
||||
/// Aliases - Test whether the type represented by A may alias the
|
||||
/// type represented by B.
|
||||
bool TypeBasedAliasAnalysis::Aliases(const MDNode *A, const MDNode *B) const {
|
||||
// Make sure that both MDNodes are struct-path aware.
|
||||
if (isStructPathTBAA(A) && isStructPathTBAA(B))
|
||||
return PathAliases(A, B);
|
||||
|
||||
// Keep track of the root node for A and B.
|
||||
TBAANode RootA, RootB;
|
||||
|
||||
// Climb the tree from A to see if we reach B.
|
||||
for (TBAANode T(A);;) {
|
||||
if (T.getNode() == B)
|
||||
// B is an ancestor of A.
|
||||
return true;
|
||||
|
||||
RootA = T;
|
||||
T = T.getParent();
|
||||
if (!T.getNode())
|
||||
break;
|
||||
}
|
||||
|
||||
// Climb the tree from B to see if we reach A.
|
||||
for (TBAANode T(B);;) {
|
||||
if (T.getNode() == A)
|
||||
// A is an ancestor of B.
|
||||
return true;
|
||||
|
||||
RootB = T;
|
||||
T = T.getParent();
|
||||
if (!T.getNode())
|
||||
break;
|
||||
}
|
||||
|
||||
// Neither node is an ancestor of the other.
|
||||
|
||||
// If they have different roots, they're part of different potentially
|
||||
// unrelated type systems, so we must be conservative.
|
||||
if (RootA.getNode() != RootB.getNode())
|
||||
return true;
|
||||
|
||||
// If they have the same root, then we've proved there's no alias.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Test whether the struct-path tag represented by A may alias the
|
||||
/// struct-path tag represented by B.
|
||||
bool TypeBasedAliasAnalysis::PathAliases(const MDNode *A,
|
||||
const MDNode *B) const {
|
||||
// Verify that both input nodes are struct-path aware.
|
||||
assert(isStructPathTBAA(A) && "MDNode A is not struct-path aware.");
|
||||
assert(isStructPathTBAA(B) && "MDNode B is not struct-path aware.");
|
||||
|
||||
// Keep track of the root node for A and B.
|
||||
TBAAStructTypeNode RootA, RootB;
|
||||
TBAAStructTagNode TagA(A), TagB(B);
|
||||
|
||||
// TODO: We need to check if AccessType of TagA encloses AccessType of
|
||||
// TagB to support aggregate AccessType. If yes, return true.
|
||||
|
||||
// Start from the base type of A, follow the edge with the correct offset in
|
||||
// the type DAG and adjust the offset until we reach the base type of B or
|
||||
// until we reach the Root node.
|
||||
// Compare the adjusted offset once we have the same base.
|
||||
|
||||
// Climb the type DAG from base type of A to see if we reach base type of B.
|
||||
const MDNode *BaseA = TagA.getBaseType();
|
||||
const MDNode *BaseB = TagB.getBaseType();
|
||||
uint64_t OffsetA = TagA.getOffset(), OffsetB = TagB.getOffset();
|
||||
for (TBAAStructTypeNode T(BaseA);;) {
|
||||
if (T.getNode() == BaseB)
|
||||
// Base type of A encloses base type of B, check if the offsets match.
|
||||
return OffsetA == OffsetB;
|
||||
|
||||
RootA = T;
|
||||
// Follow the edge with the correct offset, OffsetA will be adjusted to
|
||||
// be relative to the field type.
|
||||
T = T.getParent(OffsetA);
|
||||
if (!T.getNode())
|
||||
break;
|
||||
}
|
||||
|
||||
// Reset OffsetA and climb the type DAG from base type of B to see if we reach
|
||||
// base type of A.
|
||||
OffsetA = TagA.getOffset();
|
||||
for (TBAAStructTypeNode T(BaseB);;) {
|
||||
if (T.getNode() == BaseA)
|
||||
// Base type of B encloses base type of A, check if the offsets match.
|
||||
return OffsetA == OffsetB;
|
||||
|
||||
RootB = T;
|
||||
// Follow the edge with the correct offset, OffsetB will be adjusted to
|
||||
// be relative to the field type.
|
||||
T = T.getParent(OffsetB);
|
||||
if (!T.getNode())
|
||||
break;
|
||||
}
|
||||
|
||||
// Neither node is an ancestor of the other.
|
||||
|
||||
// If they have different roots, they're part of different potentially
|
||||
// unrelated type systems, so we must be conservative.
|
||||
if (RootA.getNode() != RootB.getNode())
|
||||
return true;
|
||||
|
||||
// If they have the same root, then we've proved there's no alias.
|
||||
return false;
|
||||
}
|
||||
|
||||
AliasResult TypeBasedAliasAnalysis::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
AliasResult TypeBasedAAResult::alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB) {
|
||||
if (!EnableTBAA)
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
|
||||
// Get the attached MDNodes. If either value lacks a tbaa MDNode, we must
|
||||
// be conservative.
|
||||
const MDNode *AM = LocA.AATags.TBAA;
|
||||
if (!AM)
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
const MDNode *BM = LocB.AATags.TBAA;
|
||||
if (!BM)
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
|
||||
// If they may alias, chain to the next AliasAnalysis.
|
||||
if (Aliases(AM, BM))
|
||||
return AliasAnalysis::alias(LocA, LocB);
|
||||
return AAResultBase::alias(LocA, LocB);
|
||||
|
||||
// Otherwise return a definitive result.
|
||||
return NoAlias;
|
||||
}
|
||||
|
||||
bool TypeBasedAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) {
|
||||
bool TypeBasedAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal) {
|
||||
if (!EnableTBAA)
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
|
||||
|
||||
const MDNode *M = Loc.AATags.TBAA;
|
||||
if (!M)
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
|
||||
|
||||
// If this is an "immutable" type, we can assume the pointer is pointing
|
||||
// to constant memory.
|
||||
@ -443,13 +316,13 @@ bool TypeBasedAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
(isStructPathTBAA(M) && TBAAStructTagNode(M).TypeIsImmutable()))
|
||||
return true;
|
||||
|
||||
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
||||
return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
|
||||
}
|
||||
|
||||
FunctionModRefBehavior
|
||||
TypeBasedAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
||||
TypeBasedAAResult::getModRefBehavior(ImmutableCallSite CS) {
|
||||
if (!EnableTBAA)
|
||||
return AliasAnalysis::getModRefBehavior(CS);
|
||||
return AAResultBase::getModRefBehavior(CS);
|
||||
|
||||
FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior;
|
||||
|
||||
@ -460,19 +333,18 @@ TypeBasedAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
||||
(isStructPathTBAA(M) && TBAAStructTagNode(M).TypeIsImmutable()))
|
||||
Min = FMRB_OnlyReadsMemory;
|
||||
|
||||
return FunctionModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
|
||||
return FunctionModRefBehavior(AAResultBase::getModRefBehavior(CS) & Min);
|
||||
}
|
||||
|
||||
FunctionModRefBehavior
|
||||
TypeBasedAliasAnalysis::getModRefBehavior(const Function *F) {
|
||||
FunctionModRefBehavior TypeBasedAAResult::getModRefBehavior(const Function *F) {
|
||||
// Functions don't have metadata. Just chain to the next implementation.
|
||||
return AliasAnalysis::getModRefBehavior(F);
|
||||
return AAResultBase::getModRefBehavior(F);
|
||||
}
|
||||
|
||||
ModRefInfo TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
ModRefInfo TypeBasedAAResult::getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) {
|
||||
if (!EnableTBAA)
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
return AAResultBase::getModRefInfo(CS, Loc);
|
||||
|
||||
if (const MDNode *L = Loc.AATags.TBAA)
|
||||
if (const MDNode *M =
|
||||
@ -480,13 +352,13 @@ ModRefInfo TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
if (!Aliases(L, M))
|
||||
return MRI_NoModRef;
|
||||
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
return AAResultBase::getModRefInfo(CS, Loc);
|
||||
}
|
||||
|
||||
ModRefInfo TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
ModRefInfo TypeBasedAAResult::getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) {
|
||||
if (!EnableTBAA)
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
return AAResultBase::getModRefInfo(CS1, CS2);
|
||||
|
||||
if (const MDNode *M1 =
|
||||
CS1.getInstruction()->getMetadata(LLVMContext::MD_tbaa))
|
||||
@ -495,7 +367,7 @@ ModRefInfo TypeBasedAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
|
||||
if (!Aliases(M1, M2))
|
||||
return MRI_NoModRef;
|
||||
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
return AAResultBase::getModRefInfo(CS1, CS2);
|
||||
}
|
||||
|
||||
bool MDNode::isTBAAVtableAccess() const {
|
||||
@ -604,3 +476,147 @@ void Instruction::getAAMetadata(AAMDNodes &N, bool Merge) const {
|
||||
N.NoAlias = getMetadata(LLVMContext::MD_noalias);
|
||||
}
|
||||
|
||||
/// Aliases - Test whether the type represented by A may alias the
|
||||
/// type represented by B.
|
||||
bool TypeBasedAAResult::Aliases(const MDNode *A, const MDNode *B) const {
|
||||
// Make sure that both MDNodes are struct-path aware.
|
||||
if (isStructPathTBAA(A) && isStructPathTBAA(B))
|
||||
return PathAliases(A, B);
|
||||
|
||||
// Keep track of the root node for A and B.
|
||||
TBAANode RootA, RootB;
|
||||
|
||||
// Climb the tree from A to see if we reach B.
|
||||
for (TBAANode T(A);;) {
|
||||
if (T.getNode() == B)
|
||||
// B is an ancestor of A.
|
||||
return true;
|
||||
|
||||
RootA = T;
|
||||
T = T.getParent();
|
||||
if (!T.getNode())
|
||||
break;
|
||||
}
|
||||
|
||||
// Climb the tree from B to see if we reach A.
|
||||
for (TBAANode T(B);;) {
|
||||
if (T.getNode() == A)
|
||||
// A is an ancestor of B.
|
||||
return true;
|
||||
|
||||
RootB = T;
|
||||
T = T.getParent();
|
||||
if (!T.getNode())
|
||||
break;
|
||||
}
|
||||
|
||||
// Neither node is an ancestor of the other.
|
||||
|
||||
// If they have different roots, they're part of different potentially
|
||||
// unrelated type systems, so we must be conservative.
|
||||
if (RootA.getNode() != RootB.getNode())
|
||||
return true;
|
||||
|
||||
// If they have the same root, then we've proved there's no alias.
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Test whether the struct-path tag represented by A may alias the
|
||||
/// struct-path tag represented by B.
|
||||
bool TypeBasedAAResult::PathAliases(const MDNode *A, const MDNode *B) const {
|
||||
// Verify that both input nodes are struct-path aware.
|
||||
assert(isStructPathTBAA(A) && "MDNode A is not struct-path aware.");
|
||||
assert(isStructPathTBAA(B) && "MDNode B is not struct-path aware.");
|
||||
|
||||
// Keep track of the root node for A and B.
|
||||
TBAAStructTypeNode RootA, RootB;
|
||||
TBAAStructTagNode TagA(A), TagB(B);
|
||||
|
||||
// TODO: We need to check if AccessType of TagA encloses AccessType of
|
||||
// TagB to support aggregate AccessType. If yes, return true.
|
||||
|
||||
// Start from the base type of A, follow the edge with the correct offset in
|
||||
// the type DAG and adjust the offset until we reach the base type of B or
|
||||
// until we reach the Root node.
|
||||
// Compare the adjusted offset once we have the same base.
|
||||
|
||||
// Climb the type DAG from base type of A to see if we reach base type of B.
|
||||
const MDNode *BaseA = TagA.getBaseType();
|
||||
const MDNode *BaseB = TagB.getBaseType();
|
||||
uint64_t OffsetA = TagA.getOffset(), OffsetB = TagB.getOffset();
|
||||
for (TBAAStructTypeNode T(BaseA);;) {
|
||||
if (T.getNode() == BaseB)
|
||||
// Base type of A encloses base type of B, check if the offsets match.
|
||||
return OffsetA == OffsetB;
|
||||
|
||||
RootA = T;
|
||||
// Follow the edge with the correct offset, OffsetA will be adjusted to
|
||||
// be relative to the field type.
|
||||
T = T.getParent(OffsetA);
|
||||
if (!T.getNode())
|
||||
break;
|
||||
}
|
||||
|
||||
// Reset OffsetA and climb the type DAG from base type of B to see if we reach
|
||||
// base type of A.
|
||||
OffsetA = TagA.getOffset();
|
||||
for (TBAAStructTypeNode T(BaseB);;) {
|
||||
if (T.getNode() == BaseA)
|
||||
// Base type of B encloses base type of A, check if the offsets match.
|
||||
return OffsetA == OffsetB;
|
||||
|
||||
RootB = T;
|
||||
// Follow the edge with the correct offset, OffsetB will be adjusted to
|
||||
// be relative to the field type.
|
||||
T = T.getParent(OffsetB);
|
||||
if (!T.getNode())
|
||||
break;
|
||||
}
|
||||
|
||||
// Neither node is an ancestor of the other.
|
||||
|
||||
// If they have different roots, they're part of different potentially
|
||||
// unrelated type systems, so we must be conservative.
|
||||
if (RootA.getNode() != RootB.getNode())
|
||||
return true;
|
||||
|
||||
// If they have the same root, then we've proved there's no alias.
|
||||
return false;
|
||||
}
|
||||
|
||||
TypeBasedAAResult TypeBasedAA::run(Function &F, AnalysisManager<Function> *AM) {
|
||||
return TypeBasedAAResult(AM->getResult<TargetLibraryAnalysis>(F));
|
||||
}
|
||||
|
||||
char TypeBasedAA::PassID;
|
||||
|
||||
char TypeBasedAAWrapperPass::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(TypeBasedAAWrapperPass, "tbaa",
|
||||
"Type-Based Alias Analysis", false, true)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(TypeBasedAAWrapperPass, "tbaa", "Type-Based Alias Analysis",
|
||||
false, true)
|
||||
|
||||
ImmutablePass *llvm::createTypeBasedAAWrapperPass() {
|
||||
return new TypeBasedAAWrapperPass();
|
||||
}
|
||||
|
||||
TypeBasedAAWrapperPass::TypeBasedAAWrapperPass() : ImmutablePass(ID) {
|
||||
initializeTypeBasedAAWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool TypeBasedAAWrapperPass::doInitialization(Module &M) {
|
||||
Result.reset(new TypeBasedAAResult(
|
||||
getAnalysis<TargetLibraryInfoWrapperPass>().getTLI()));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeBasedAAWrapperPass::doFinalization(Module &M) {
|
||||
Result.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
void TypeBasedAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ public:
|
||||
InlineSpiller(MachineFunctionPass &pass, MachineFunction &mf, VirtRegMap &vrm)
|
||||
: MF(mf), LIS(pass.getAnalysis<LiveIntervals>()),
|
||||
LSS(pass.getAnalysis<LiveStacks>()),
|
||||
AA(&pass.getAnalysis<AliasAnalysis>()),
|
||||
AA(&pass.getAnalysis<AAResultsWrapperPass>().getAAResults()),
|
||||
MDT(pass.getAnalysis<MachineDominatorTree>()),
|
||||
Loops(pass.getAnalysis<MachineLoopInfo>()), VRM(vrm),
|
||||
MFI(*mf.getFrameInfo()), MRI(mf.getRegInfo()),
|
||||
|
@ -48,7 +48,7 @@ char LiveIntervals::ID = 0;
|
||||
char &llvm::LiveIntervalsID = LiveIntervals::ID;
|
||||
INITIALIZE_PASS_BEGIN(LiveIntervals, "liveintervals",
|
||||
"Live Interval Analysis", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(LiveVariables)
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
||||
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
|
||||
@ -76,8 +76,8 @@ cl::opt<bool> UseSegmentSetForPhysRegs(
|
||||
|
||||
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
// LiveVariables isn't really required by this analysis, it is only required
|
||||
// here to make sure it is live during TwoAddressInstructionPass and
|
||||
// PHIElimination. This is temporary.
|
||||
@ -124,7 +124,7 @@ bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) {
|
||||
MRI = &MF->getRegInfo();
|
||||
TRI = MF->getSubtarget().getRegisterInfo();
|
||||
TII = MF->getSubtarget().getInstrInfo();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
Indexes = &getAnalysis<SlotIndexes>();
|
||||
DomTree = &getAnalysis<MachineDominatorTree>();
|
||||
|
||||
|
@ -57,7 +57,7 @@ namespace {
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreservedID(MachineLoopInfoID);
|
||||
AU.addRequired<MachineDominatorTree>();
|
||||
AU.addPreserved<MachineDominatorTree>();
|
||||
@ -111,7 +111,7 @@ char &llvm::MachineCSEID = MachineCSE::ID;
|
||||
INITIALIZE_PASS_BEGIN(MachineCSE, "machine-cse",
|
||||
"Machine Common Subexpression Elimination", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(MachineCSE, "machine-cse",
|
||||
"Machine Common Subexpression Elimination", false, false)
|
||||
|
||||
@ -714,7 +714,7 @@ bool MachineCSE::runOnMachineFunction(MachineFunction &MF) {
|
||||
TII = MF.getSubtarget().getInstrInfo();
|
||||
TRI = MF.getSubtarget().getRegisterInfo();
|
||||
MRI = &MF.getRegInfo();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
DT = &getAnalysis<MachineDominatorTree>();
|
||||
LookAheadLimit = TII->getMachineCSELookAheadLimit();
|
||||
return PerformCSE(DT->getRootNode());
|
||||
|
@ -13,11 +13,14 @@
|
||||
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/DominanceFrontier.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/IVUsers.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/StackProtector.h"
|
||||
@ -49,13 +52,16 @@ void MachineFunctionPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
// passes explicitly. This does not include setPreservesCFG,
|
||||
// because CodeGen overloads that to mean preserving the MachineBasicBlock
|
||||
// CFG in addition to the LLVM IR CFG.
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addPreserved<BasicAAWrapperPass>();
|
||||
AU.addPreserved<DominanceFrontier>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
AU.addPreserved<IVUsers>();
|
||||
AU.addPreserved<LoopInfoWrapperPass>();
|
||||
AU.addPreserved<MemoryDependenceAnalysis>();
|
||||
AU.addPreserved<ScalarEvolutionWrapperPass>();
|
||||
AU.addPreserved<SCEVAAWrapperPass>();
|
||||
AU.addPreserved<StackProtector>();
|
||||
|
||||
FunctionPass::getAnalysisUsage(AU);
|
||||
|
@ -138,7 +138,7 @@ namespace {
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<MachineLoopInfo>();
|
||||
AU.addRequired<MachineDominatorTree>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<MachineLoopInfo>();
|
||||
AU.addPreserved<MachineDominatorTree>();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
@ -315,7 +315,7 @@ INITIALIZE_PASS_BEGIN(MachineLICM, "machinelicm",
|
||||
"Machine Loop Invariant Code Motion", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(MachineLICM, "machinelicm",
|
||||
"Machine Loop Invariant Code Motion", false, false)
|
||||
|
||||
@ -367,7 +367,7 @@ bool MachineLICM::runOnMachineFunction(MachineFunction &MF) {
|
||||
// Get our Loop information...
|
||||
MLI = &getAnalysis<MachineLoopInfo>();
|
||||
DT = &getAnalysis<MachineDominatorTree>();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
SmallVector<MachineLoop *, 8> Worklist(MLI->begin(), MLI->end());
|
||||
while (!Worklist.empty()) {
|
||||
|
@ -146,7 +146,7 @@ char &llvm::MachineSchedulerID = MachineScheduler::ID;
|
||||
|
||||
INITIALIZE_PASS_BEGIN(MachineScheduler, "machine-scheduler",
|
||||
"Machine Instruction Scheduler", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
|
||||
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
|
||||
INITIALIZE_PASS_END(MachineScheduler, "machine-scheduler",
|
||||
@ -161,7 +161,7 @@ void MachineScheduler::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequiredID(MachineDominatorsID);
|
||||
AU.addRequired<MachineLoopInfo>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<TargetPassConfig>();
|
||||
AU.addRequired<SlotIndexes>();
|
||||
AU.addPreserved<SlotIndexes>();
|
||||
@ -322,7 +322,7 @@ bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) {
|
||||
MLI = &getAnalysis<MachineLoopInfo>();
|
||||
MDT = &getAnalysis<MachineDominatorTree>();
|
||||
PassConfig = &getAnalysis<TargetPassConfig>();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
LIS = &getAnalysis<LiveIntervals>();
|
||||
|
||||
|
@ -87,7 +87,7 @@ namespace {
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<MachineDominatorTree>();
|
||||
AU.addRequired<MachinePostDominatorTree>();
|
||||
AU.addRequired<MachineLoopInfo>();
|
||||
@ -150,7 +150,7 @@ INITIALIZE_PASS_BEGIN(MachineSinking, "machine-sink",
|
||||
"Machine code sinking", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(MachineSinking, "machine-sink",
|
||||
"Machine code sinking", false, false)
|
||||
|
||||
@ -268,7 +268,7 @@ bool MachineSinking::runOnMachineFunction(MachineFunction &MF) {
|
||||
PDT = &getAnalysis<MachinePostDominatorTree>();
|
||||
LI = &getAnalysis<MachineLoopInfo>();
|
||||
MBFI = UseBlockFreqInfo ? &getAnalysis<MachineBlockFrequencyInfo>() : nullptr;
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
bool EverMadeChange = false;
|
||||
|
||||
|
@ -226,6 +226,10 @@ TargetPassConfig::TargetPassConfig(TargetMachine *tm, PassManagerBase &pm)
|
||||
// including this pass itself.
|
||||
initializeCodeGen(*PassRegistry::getPassRegistry());
|
||||
|
||||
// Also register alias analysis passes required by codegen passes.
|
||||
initializeBasicAAWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
|
||||
// Substitute Pseudo Pass IDs for real ones.
|
||||
substitutePass(&EarlyTailDuplicateID, &TailDuplicateID);
|
||||
substitutePass(&PostRAMachineLICMID, &MachineLICMID);
|
||||
@ -381,10 +385,10 @@ void TargetPassConfig::addIRPasses() {
|
||||
// BasicAliasAnalysis wins if they disagree. This is intended to help
|
||||
// support "obvious" type-punning idioms.
|
||||
if (UseCFLAA)
|
||||
addPass(createCFLAliasAnalysisPass());
|
||||
addPass(createTypeBasedAliasAnalysisPass());
|
||||
addPass(createScopedNoAliasAAPass());
|
||||
addPass(createBasicAliasAnalysisPass());
|
||||
addPass(createCFLAAWrapperPass());
|
||||
addPass(createTypeBasedAAWrapperPass());
|
||||
addPass(createScopedNoAliasAAWrapperPass());
|
||||
addPass(createBasicAAWrapperPass());
|
||||
|
||||
// Before running any passes, run the verifier to determine if the input
|
||||
// coming from the front-end and/or optimizer is valid.
|
||||
|
@ -87,7 +87,7 @@ namespace {
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<TargetPassConfig>();
|
||||
AU.addRequired<MachineDominatorTree>();
|
||||
AU.addPreserved<MachineDominatorTree>();
|
||||
@ -267,7 +267,7 @@ bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
|
||||
|
||||
TII = Fn.getSubtarget().getInstrInfo();
|
||||
MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
|
||||
AliasAnalysis *AA = &getAnalysis<AliasAnalysis>();
|
||||
AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
TargetPassConfig *PassConfig = &getAnalysis<TargetPassConfig>();
|
||||
|
||||
RegClassInfo.runOnMachineFunction(Fn);
|
||||
|
@ -58,7 +58,7 @@ INITIALIZE_PASS_END(ProcessImplicitDefs, "processimpdefs",
|
||||
|
||||
void ProcessImplicitDefs::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
|
@ -133,8 +133,8 @@ RABasic::RABasic(): MachineFunctionPass(ID) {
|
||||
|
||||
void RABasic::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addRequired<LiveIntervals>();
|
||||
AU.addPreserved<LiveIntervals>();
|
||||
AU.addPreserved<SlotIndexes>();
|
||||
|
@ -461,8 +461,8 @@ void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<MachineBlockFrequencyInfo>();
|
||||
AU.addPreserved<MachineBlockFrequencyInfo>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addRequired<LiveIntervals>();
|
||||
AU.addPreserved<LiveIntervals>();
|
||||
AU.addRequired<SlotIndexes>();
|
||||
|
@ -497,8 +497,8 @@ void PBQPRAConstraintList::anchor() {}
|
||||
|
||||
void RegAllocPBQP::getAnalysisUsage(AnalysisUsage &au) const {
|
||||
au.setPreservesCFG();
|
||||
au.addRequired<AliasAnalysis>();
|
||||
au.addPreserved<AliasAnalysis>();
|
||||
au.addRequired<AAResultsWrapperPass>();
|
||||
au.addPreserved<AAResultsWrapperPass>();
|
||||
au.addRequired<SlotIndexes>();
|
||||
au.addPreserved<SlotIndexes>();
|
||||
au.addRequired<LiveIntervals>();
|
||||
|
@ -275,7 +275,7 @@ INITIALIZE_PASS_BEGIN(RegisterCoalescer, "simple-register-coalescing",
|
||||
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
|
||||
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(RegisterCoalescer, "simple-register-coalescing",
|
||||
"Simple Register Coalescing", false, false)
|
||||
|
||||
@ -453,7 +453,7 @@ bool CoalescerPair::isCoalescable(const MachineInstr *MI) const {
|
||||
|
||||
void RegisterCoalescer::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<LiveIntervals>();
|
||||
AU.addPreserved<LiveIntervals>();
|
||||
AU.addPreserved<SlotIndexes>();
|
||||
@ -2943,7 +2943,7 @@ bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) {
|
||||
TRI = STI.getRegisterInfo();
|
||||
TII = STI.getInstrInfo();
|
||||
LIS = &getAnalysis<LiveIntervals>();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
Loops = &getAnalysis<MachineLoopInfo>();
|
||||
if (EnableGlobalCopies == cl::BOU_UNSET)
|
||||
JoinGlobalCopies = STI.enableJoinGlobalCopies();
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "StatepointLowering.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/CodeGen/Analysis.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
||||
@ -30,7 +31,6 @@
|
||||
namespace llvm {
|
||||
|
||||
class AddrSpaceCastInst;
|
||||
class AliasAnalysis;
|
||||
class AllocaInst;
|
||||
class BasicBlock;
|
||||
class BitCastInst;
|
||||
|
@ -356,9 +356,9 @@ SelectionDAGISel::SelectionDAGISel(TargetMachine &tm,
|
||||
OptLevel(OL),
|
||||
DAGSize(0) {
|
||||
initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
|
||||
initializeAliasAnalysisAnalysisGroup(*PassRegistry::getPassRegistry());
|
||||
initializeBranchProbabilityInfoWrapperPassPass(
|
||||
*PassRegistry::getPassRegistry());
|
||||
initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||
initializeTargetLibraryInfoWrapperPassPass(
|
||||
*PassRegistry::getPassRegistry());
|
||||
}
|
||||
@ -370,8 +370,7 @@ SelectionDAGISel::~SelectionDAGISel() {
|
||||
}
|
||||
|
||||
void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<GCModuleInfo>();
|
||||
AU.addPreserved<GCModuleInfo>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
@ -444,7 +443,7 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) {
|
||||
TII = MF->getSubtarget().getInstrInfo();
|
||||
TLI = MF->getSubtarget().getTargetLowering();
|
||||
RegInfo = &MF->getRegInfo();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
LibInfo = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
GFI = Fn.hasGC() ? &getAnalysis<GCModuleInfo>().getFunctionInfo(Fn) : nullptr;
|
||||
|
||||
|
@ -151,7 +151,7 @@ public:
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<LiveVariables>();
|
||||
AU.addPreserved<SlotIndexes>();
|
||||
AU.addPreserved<LiveIntervals>();
|
||||
@ -168,7 +168,7 @@ public:
|
||||
char TwoAddressInstructionPass::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(TwoAddressInstructionPass, "twoaddressinstruction",
|
||||
"Two-Address instruction pass", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(TwoAddressInstructionPass, "twoaddressinstruction",
|
||||
"Two-Address instruction pass", false, false)
|
||||
|
||||
@ -1599,7 +1599,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &Func) {
|
||||
InstrItins = MF->getSubtarget().getInstrItineraryData();
|
||||
LV = getAnalysisIfAvailable<LiveVariables>();
|
||||
LIS = getAnalysisIfAvailable<LiveIntervals>();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
OptLevel = TM.getOptLevel();
|
||||
|
||||
bool MadeChange = false;
|
||||
|
@ -101,7 +101,7 @@ void LTOCodeGenerator::initializeLTOPasses() {
|
||||
initializeSROA_DTPass(R);
|
||||
initializeSROA_SSAUpPass(R);
|
||||
initializeFunctionAttrsPass(R);
|
||||
initializeGlobalsModRefPass(R);
|
||||
initializeGlobalsAAWrapperPassPass(R);
|
||||
initializeLICMPass(R);
|
||||
initializeMergedLoadStoreMotionPass(R);
|
||||
initializeGVNPass(R);
|
||||
|
@ -177,7 +177,7 @@ INITIALIZE_PASS_BEGIN(HexagonPacketizer, "packets", "Hexagon Packetizer",
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
|
||||
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(HexagonPacketizer, "packets", "Hexagon Packetizer",
|
||||
false, false)
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionExpander.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
|
@ -34,8 +34,11 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Analysis/CallGraphSCCPass.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/CFG.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
@ -63,7 +66,8 @@ namespace {
|
||||
///
|
||||
struct ArgPromotion : public CallGraphSCCPass {
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
CallGraphSCCPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
@ -81,7 +85,8 @@ namespace {
|
||||
bool isDenselyPacked(Type *type, const DataLayout &DL);
|
||||
bool canPaddingBeAccessed(Argument *Arg);
|
||||
CallGraphNode *PromoteArguments(CallGraphNode *CGN);
|
||||
bool isSafeToPromoteArgument(Argument *Arg, bool isByVal) const;
|
||||
bool isSafeToPromoteArgument(Argument *Arg, bool isByVal,
|
||||
AAResults &AAR) const;
|
||||
CallGraphNode *DoPromotion(Function *F,
|
||||
SmallPtrSetImpl<Argument*> &ArgsToPromote,
|
||||
SmallPtrSetImpl<Argument*> &ByValArgsToTransform);
|
||||
@ -97,8 +102,9 @@ namespace {
|
||||
char ArgPromotion::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(ArgPromotion, "argpromotion",
|
||||
"Promote 'by reference' arguments to scalars", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(ArgPromotion, "argpromotion",
|
||||
"Promote 'by reference' arguments to scalars", false, false)
|
||||
|
||||
@ -237,6 +243,14 @@ CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) {
|
||||
|
||||
const DataLayout &DL = F->getParent()->getDataLayout();
|
||||
|
||||
// We need to manually construct BasicAA directly in order to disable its use
|
||||
// of other function analyses.
|
||||
BasicAAResult BAR(createLegacyPMBasicAAResult(*this, *F));
|
||||
|
||||
// Construct our own AA results for this function. We do this manually to
|
||||
// work around the limitations of the legacy pass manager.
|
||||
AAResults AAR(createLegacyPMAAResults(*this, *F, BAR));
|
||||
|
||||
// Check to see which arguments are promotable. If an argument is promotable,
|
||||
// add it to ArgsToPromote.
|
||||
SmallPtrSet<Argument*, 8> ArgsToPromote;
|
||||
@ -315,7 +329,7 @@ CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) {
|
||||
}
|
||||
|
||||
// Otherwise, see if we can promote the pointer to its value.
|
||||
if (isSafeToPromoteArgument(PtrArg, PtrArg->hasByValOrInAllocaAttr()))
|
||||
if (isSafeToPromoteArgument(PtrArg, PtrArg->hasByValOrInAllocaAttr(), AAR))
|
||||
ArgsToPromote.insert(PtrArg);
|
||||
}
|
||||
|
||||
@ -416,7 +430,8 @@ static void MarkIndicesSafe(const ArgPromotion::IndicesVector &ToMark,
|
||||
/// elements of the aggregate in order to avoid exploding the number of
|
||||
/// arguments passed in.
|
||||
bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg,
|
||||
bool isByValOrInAlloca) const {
|
||||
bool isByValOrInAlloca,
|
||||
AAResults &AAR) const {
|
||||
typedef std::set<IndicesVector> GEPIndicesSet;
|
||||
|
||||
// Quick exit for unused arguments
|
||||
@ -505,7 +520,7 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg,
|
||||
// TODO: This runs the above loop over and over again for dead GEPs
|
||||
// Couldn't we just do increment the UI iterator earlier and erase the
|
||||
// use?
|
||||
return isSafeToPromoteArgument(Arg, isByValOrInAlloca);
|
||||
return isSafeToPromoteArgument(Arg, isByValOrInAlloca, AAR);
|
||||
}
|
||||
|
||||
// Ensure that all of the indices are constants.
|
||||
@ -562,8 +577,6 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg,
|
||||
// blocks we know to be transparent to the load.
|
||||
SmallPtrSet<BasicBlock*, 16> TranspBlocks;
|
||||
|
||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
|
||||
for (unsigned i = 0, e = Loads.size(); i != e; ++i) {
|
||||
// Check to see if the load is invalidated from the start of the block to
|
||||
// the load itself.
|
||||
@ -571,7 +584,7 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg,
|
||||
BasicBlock *BB = Load->getParent();
|
||||
|
||||
MemoryLocation Loc = MemoryLocation::get(Load);
|
||||
if (AA.canInstructionRangeModRef(BB->front(), *Load, Loc, MRI_Mod))
|
||||
if (AAR.canInstructionRangeModRef(BB->front(), *Load, Loc, MRI_Mod))
|
||||
return false; // Pointer is invalidated!
|
||||
|
||||
// Now check every path from the entry block to the load for transparency.
|
||||
@ -579,7 +592,7 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg,
|
||||
// loading block.
|
||||
for (BasicBlock *P : predecessors(BB)) {
|
||||
for (BasicBlock *TranspBB : inverse_depth_first_ext(P, TranspBlocks))
|
||||
if (AA.canBasicBlockModify(*TranspBB, Loc))
|
||||
if (AAR.canBasicBlockModify(*TranspBB, Loc))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,12 @@
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Analysis/CallGraphSCCPass.h"
|
||||
#include "llvm/Analysis/CaptureTracking.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
@ -51,7 +54,7 @@ STATISTIC(NumAnnotated, "Number of attributes added to library functions");
|
||||
namespace {
|
||||
struct FunctionAttrs : public CallGraphSCCPass {
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
FunctionAttrs() : CallGraphSCCPass(ID), AA(nullptr) {
|
||||
FunctionAttrs() : CallGraphSCCPass(ID) {
|
||||
initializeFunctionAttrsPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
@ -134,13 +137,12 @@ namespace {
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
CallGraphSCCPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
private:
|
||||
AliasAnalysis *AA;
|
||||
TargetLibraryInfo *TLI;
|
||||
};
|
||||
}
|
||||
@ -148,7 +150,7 @@ namespace {
|
||||
char FunctionAttrs::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(FunctionAttrs, "functionattrs",
|
||||
"Deduce function attributes", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(FunctionAttrs, "functionattrs",
|
||||
@ -177,7 +179,15 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
|
||||
// memory and give up.
|
||||
return false;
|
||||
|
||||
FunctionModRefBehavior MRB = AA->getModRefBehavior(F);
|
||||
// We need to manually construct BasicAA directly in order to disable its
|
||||
// use of other function analyses.
|
||||
BasicAAResult BAR(createLegacyPMBasicAAResult(*this, *F));
|
||||
|
||||
// Construct our own AA results for this function. We do this manually to
|
||||
// work around the limitations of the legacy pass manager.
|
||||
AAResults AAR(createLegacyPMAAResults(*this, *F, BAR));
|
||||
|
||||
FunctionModRefBehavior MRB = AAR.getModRefBehavior(F);
|
||||
if (MRB == FMRB_DoesNotAccessMemory)
|
||||
// Already perfect!
|
||||
continue;
|
||||
@ -204,7 +214,7 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
|
||||
// Ignore calls to functions in the same SCC.
|
||||
if (CS.getCalledFunction() && SCCNodes.count(CS.getCalledFunction()))
|
||||
continue;
|
||||
FunctionModRefBehavior MRB = AA->getModRefBehavior(CS);
|
||||
FunctionModRefBehavior MRB = AAR.getModRefBehavior(CS);
|
||||
// If the call doesn't access arbitrary memory, we may be able to
|
||||
// figure out something.
|
||||
if (AliasAnalysis::onlyAccessesArgPointees(MRB)) {
|
||||
@ -220,7 +230,7 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
|
||||
I->getAAMetadata(AAInfo);
|
||||
|
||||
MemoryLocation Loc(Arg, MemoryLocation::UnknownSize, AAInfo);
|
||||
if (!AA->pointsToConstantMemory(Loc, /*OrLocal=*/true)) {
|
||||
if (!AAR.pointsToConstantMemory(Loc, /*OrLocal=*/true)) {
|
||||
if (MRB & MRI_Mod)
|
||||
// Writes non-local memory. Give up.
|
||||
return false;
|
||||
@ -243,20 +253,20 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
|
||||
// Ignore non-volatile loads from local memory. (Atomic is okay here.)
|
||||
if (!LI->isVolatile()) {
|
||||
MemoryLocation Loc = MemoryLocation::get(LI);
|
||||
if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true))
|
||||
if (AAR.pointsToConstantMemory(Loc, /*OrLocal=*/true))
|
||||
continue;
|
||||
}
|
||||
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
|
||||
// Ignore non-volatile stores to local memory. (Atomic is okay here.)
|
||||
if (!SI->isVolatile()) {
|
||||
MemoryLocation Loc = MemoryLocation::get(SI);
|
||||
if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true))
|
||||
if (AAR.pointsToConstantMemory(Loc, /*OrLocal=*/true))
|
||||
continue;
|
||||
}
|
||||
} else if (VAArgInst *VI = dyn_cast<VAArgInst>(I)) {
|
||||
// Ignore vaargs on local memory.
|
||||
MemoryLocation Loc = MemoryLocation::get(VI);
|
||||
if (AA->pointsToConstantMemory(Loc, /*OrLocal=*/true))
|
||||
if (AAR.pointsToConstantMemory(Loc, /*OrLocal=*/true))
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1848,7 +1858,6 @@ bool FunctionAttrs::annotateLibraryCalls(const CallGraphSCC &SCC) {
|
||||
}
|
||||
|
||||
bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
|
||||
bool Changed = annotateLibraryCalls(SCC);
|
||||
|
@ -14,10 +14,10 @@
|
||||
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Analysis/InlineCost.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/CallingConv.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
@ -67,10 +67,10 @@ public:
|
||||
char AlwaysInliner::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
|
||||
"Inliner for always_inline functions", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
|
||||
"Inliner for always_inline functions", false, false)
|
||||
|
||||
|
@ -12,10 +12,10 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Analysis/InlineCost.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/CallingConv.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
@ -75,10 +75,10 @@ static int computeThresholdFromOptLevels(unsigned OptLevel,
|
||||
char SimpleInliner::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(SimpleInliner, "inline",
|
||||
"Function Integration/Inlining", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(SimpleInliner, "inline",
|
||||
"Function Integration/Inlining", false, false)
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Analysis/InlineCost.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
@ -76,8 +77,8 @@ Inliner::Inliner(char &ID, int Threshold, bool InsertLifetime)
|
||||
/// If the derived class implements this method, it should
|
||||
/// always explicitly call the implementation here.
|
||||
void Inliner::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
CallGraphSCCPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
@ -126,15 +127,23 @@ static void AdjustCallerSSPLevel(Function *Caller, Function *Callee) {
|
||||
/// available from other functions inlined into the caller. If we are able to
|
||||
/// inline this call site we attempt to reuse already available allocas or add
|
||||
/// any new allocas to the set if not possible.
|
||||
static bool InlineCallIfPossible(CallSite CS, InlineFunctionInfo &IFI,
|
||||
static bool InlineCallIfPossible(Pass &P, CallSite CS, InlineFunctionInfo &IFI,
|
||||
InlinedArrayAllocasTy &InlinedArrayAllocas,
|
||||
int InlineHistory, bool InsertLifetime) {
|
||||
Function *Callee = CS.getCalledFunction();
|
||||
Function *Caller = CS.getCaller();
|
||||
|
||||
// We need to manually construct BasicAA directly in order to disable
|
||||
// its use of other function analyses.
|
||||
BasicAAResult BAR(createLegacyPMBasicAAResult(P, *Callee));
|
||||
|
||||
// Construct our own AA results for this function. We do this manually to
|
||||
// work around the limitations of the legacy pass manager.
|
||||
AAResults AAR(createLegacyPMAAResults(P, *Callee, BAR));
|
||||
|
||||
// Try to inline the function. Get the list of static allocas that were
|
||||
// inlined.
|
||||
if (!InlineFunction(CS, IFI, InsertLifetime))
|
||||
if (!InlineFunction(CS, IFI, &AAR, InsertLifetime))
|
||||
return false;
|
||||
|
||||
AdjustCallerSSPLevel(Caller, Callee);
|
||||
@ -432,9 +441,7 @@ static bool InlineHistoryIncludes(Function *F, int InlineHistoryID,
|
||||
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
|
||||
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
|
||||
AssumptionCacheTracker *ACT = &getAnalysis<AssumptionCacheTracker>();
|
||||
auto *TLIP = getAnalysisIfAvailable<TargetLibraryInfoWrapperPass>();
|
||||
const TargetLibraryInfo *TLI = TLIP ? &TLIP->getTLI() : nullptr;
|
||||
AliasAnalysis *AA = &getAnalysis<AliasAnalysis>();
|
||||
auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
|
||||
SmallPtrSet<Function*, 8> SCCFunctions;
|
||||
DEBUG(dbgs() << "Inliner visiting SCC:");
|
||||
@ -494,7 +501,7 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) {
|
||||
|
||||
|
||||
InlinedArrayAllocasTy InlinedArrayAllocas;
|
||||
InlineFunctionInfo InlineInfo(&CG, AA, ACT);
|
||||
InlineFunctionInfo InlineInfo(&CG, ACT);
|
||||
|
||||
// Now that we have all of the call sites, loop over them and inline them if
|
||||
// it looks profitable to do so.
|
||||
@ -515,7 +522,7 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) {
|
||||
// just delete the call instead of trying to inline it, regardless of
|
||||
// size. This happens because IPSCCP propagates the result out of the
|
||||
// call and then we're left with the dead call.
|
||||
if (isInstructionTriviallyDead(CS.getInstruction(), TLI)) {
|
||||
if (isInstructionTriviallyDead(CS.getInstruction(), &TLI)) {
|
||||
DEBUG(dbgs() << " -> Deleting dead call: "
|
||||
<< *CS.getInstruction() << "\n");
|
||||
// Update the call graph by deleting the edge from Callee to Caller.
|
||||
@ -552,7 +559,7 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) {
|
||||
}
|
||||
|
||||
// Attempt to inline the function.
|
||||
if (!InlineCallIfPossible(CS, InlineInfo, InlinedArrayAllocas,
|
||||
if (!InlineCallIfPossible(*this, CS, InlineInfo, InlinedArrayAllocas,
|
||||
InlineHistoryID, InsertLifetime)) {
|
||||
emitOptimizationRemarkMissed(CallerCtx, DEBUG_TYPE, *Caller, DLoc,
|
||||
Twine(Callee->getName() +
|
||||
|
@ -153,10 +153,9 @@ void PassManagerBuilder::addInitialAliasAnalysisPasses(
|
||||
// BasicAliasAnalysis wins if they disagree. This is intended to help
|
||||
// support "obvious" type-punning idioms.
|
||||
if (UseCFLAA)
|
||||
PM.add(createCFLAliasAnalysisPass());
|
||||
PM.add(createTypeBasedAliasAnalysisPass());
|
||||
PM.add(createScopedNoAliasAAPass());
|
||||
PM.add(createBasicAliasAnalysisPass());
|
||||
PM.add(createCFLAAWrapperPass());
|
||||
PM.add(createTypeBasedAAWrapperPass());
|
||||
PM.add(createScopedNoAliasAAWrapperPass());
|
||||
}
|
||||
|
||||
void PassManagerBuilder::populateFunctionPassManager(
|
||||
@ -227,7 +226,7 @@ void PassManagerBuilder::populateModulePassManager(
|
||||
// We add a module alias analysis pass here. In part due to bugs in the
|
||||
// analysis infrastructure this "works" in that the analysis stays alive
|
||||
// for the entire SCC pass run below.
|
||||
MPM.add(createGlobalsModRefPass());
|
||||
MPM.add(createGlobalsAAWrapperPass());
|
||||
|
||||
// Start of CallGraph SCC passes.
|
||||
if (!DisableUnitAtATime)
|
||||
@ -360,7 +359,7 @@ void PassManagerBuilder::populateModulePassManager(
|
||||
// this to work. Fortunately, it is trivial to preserve AliasAnalysis
|
||||
// (doing nothing preserves it as it is required to be conservatively
|
||||
// correct in the face of IR changes).
|
||||
MPM.add(createGlobalsModRefPass());
|
||||
MPM.add(createGlobalsAAWrapperPass());
|
||||
|
||||
if (RunFloat2Int)
|
||||
MPM.add(createFloat2IntPass());
|
||||
@ -519,7 +518,7 @@ void PassManagerBuilder::addLTOOptimizationPasses(legacy::PassManagerBase &PM) {
|
||||
|
||||
// Run a few AA driven optimizations here and now, to cleanup the code.
|
||||
PM.add(createFunctionAttrsPass()); // Add nocapture.
|
||||
PM.add(createGlobalsModRefPass()); // IP alias analysis.
|
||||
PM.add(createGlobalsAAWrapperPass()); // IP alias analysis.
|
||||
|
||||
PM.add(createLICMPass()); // Hoist loop invariants.
|
||||
if (EnableMLSM)
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/ConstantFolding.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/LibCallSemantics.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
@ -3071,11 +3072,12 @@ public:
|
||||
|
||||
void InstructionCombiningPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
}
|
||||
|
||||
bool InstructionCombiningPass::runOnFunction(Function &F) {
|
||||
@ -3083,7 +3085,7 @@ bool InstructionCombiningPass::runOnFunction(Function &F) {
|
||||
return false;
|
||||
|
||||
// Required analyses.
|
||||
auto AA = &getAnalysis<AliasAnalysis>();
|
||||
auto AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
|
||||
auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
@ -3101,7 +3103,8 @@ INITIALIZE_PASS_BEGIN(InstructionCombiningPass, "instcombine",
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_END(InstructionCombiningPass, "instcombine",
|
||||
"Combine redundant instructions", false, false)
|
||||
|
||||
|
@ -221,7 +221,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
}
|
||||
|
||||
virtual bool doInitialization(Module &M) {
|
||||
@ -513,7 +513,7 @@ void SafeStack::moveDynamicAllocasToUnsafeStack(
|
||||
}
|
||||
|
||||
bool SafeStack::runOnFunction(Function &F) {
|
||||
auto AA = &getAnalysis<AliasAnalysis>();
|
||||
auto AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
DEBUG(dbgs() << "[SafeStack] Function: " << F.getName() << "\n");
|
||||
|
||||
|
@ -29,7 +29,7 @@ using namespace llvm::objcarc;
|
||||
/// initializeObjCARCOptsPasses - Initialize all passes linked into the
|
||||
/// ObjCARCOpts library.
|
||||
void llvm::initializeObjCARCOpts(PassRegistry &Registry) {
|
||||
initializeObjCARCAliasAnalysisPass(Registry);
|
||||
initializeObjCARCAAWrapperPassPass(Registry);
|
||||
initializeObjCARCAPElimPass(Registry);
|
||||
initializeObjCARCExpandPass(Registry);
|
||||
initializeObjCARCContractPass(Registry);
|
||||
|
@ -511,10 +511,10 @@ bool ObjCARCContract::runOnFunction(Function &F) {
|
||||
return false;
|
||||
|
||||
Changed = false;
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
|
||||
PA.setAA(&getAnalysis<AliasAnalysis>());
|
||||
PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults());
|
||||
|
||||
DEBUG(llvm::dbgs() << "**** ObjCARC Contract ****\n");
|
||||
|
||||
@ -629,13 +629,13 @@ bool ObjCARCContract::runOnFunction(Function &F) {
|
||||
char ObjCARCContract::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(ObjCARCContract, "objc-arc-contract",
|
||||
"ObjC ARC contraction", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_END(ObjCARCContract, "objc-arc-contract",
|
||||
"ObjC ARC contraction", false, false)
|
||||
|
||||
void ObjCARCContract::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.setPreservesCFG();
|
||||
}
|
||||
|
@ -556,7 +556,7 @@ namespace {
|
||||
char ObjCARCOpt::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(ObjCARCOpt,
|
||||
"objc-arc", "ObjC ARC optimization", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(ObjCARCAliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass)
|
||||
INITIALIZE_PASS_END(ObjCARCOpt,
|
||||
"objc-arc", "ObjC ARC optimization", false, false)
|
||||
|
||||
@ -565,8 +565,8 @@ Pass *llvm::createObjCARCOptPass() {
|
||||
}
|
||||
|
||||
void ObjCARCOpt::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<ObjCARCAliasAnalysis>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<ObjCARCAAWrapperPass>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
// ARC optimization doesn't currently split critical edges.
|
||||
AU.setPreservesCFG();
|
||||
}
|
||||
@ -2192,7 +2192,7 @@ bool ObjCARCOpt::runOnFunction(Function &F) {
|
||||
DEBUG(dbgs() << "<<< ObjCARCOpt: Visiting Function: " << F.getName() << " >>>"
|
||||
"\n");
|
||||
|
||||
PA.setAA(&getAnalysis<AliasAnalysis>());
|
||||
PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults());
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (AreStatisticsEnabled()) {
|
||||
|
@ -26,10 +26,10 @@
|
||||
#define LLVM_LIB_TRANSFORMS_OBJCARC_PROVENANCEANALYSIS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
|
||||
namespace llvm {
|
||||
class Value;
|
||||
class AliasAnalysis;
|
||||
class DataLayout;
|
||||
class PHINode;
|
||||
class SelectInst;
|
||||
|
@ -35,7 +35,7 @@ char PAEval::ID = 0;
|
||||
PAEval::PAEval() : FunctionPass(ID) {}
|
||||
|
||||
void PAEval::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
}
|
||||
|
||||
static StringRef getName(Value *V) {
|
||||
@ -65,7 +65,7 @@ bool PAEval::runOnFunction(Function &F) {
|
||||
}
|
||||
|
||||
ProvenanceAnalysis PA;
|
||||
PA.setAA(&getAnalysis<AliasAnalysis>());
|
||||
PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults());
|
||||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
|
||||
for (Value *V1 : Values) {
|
||||
@ -89,6 +89,6 @@ FunctionPass *llvm::createPAEvalPass() { return new PAEval(); }
|
||||
|
||||
INITIALIZE_PASS_BEGIN(PAEval, "pa-eval",
|
||||
"Evaluate ProvenanceAnalysis on all pairs", false, true)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(PAEval, "pa-eval",
|
||||
"Evaluate ProvenanceAnalysis on all pairs", false, true)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/CaptureTracking.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
@ -60,7 +61,7 @@ namespace {
|
||||
if (skipOptnoneFunction(F))
|
||||
return false;
|
||||
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
MD = &getAnalysis<MemoryDependenceAnalysis>();
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
@ -87,11 +88,11 @@ namespace {
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<MemoryDependenceAnalysis>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
AU.addPreserved<MemoryDependenceAnalysis>();
|
||||
}
|
||||
};
|
||||
@ -99,8 +100,9 @@ namespace {
|
||||
|
||||
char DSE::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(DSE, "dse", "Dead Store Elimination", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(DSE, "dse", "Dead Store Elimination", false, false)
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
bool runOnFunction(Function &F) override;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -41,7 +41,7 @@ private:
|
||||
char FlattenCFGPass::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(FlattenCFGPass, "flattencfg", "Flatten the CFG", false,
|
||||
false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(FlattenCFGPass, "flattencfg", "Flatten the CFG", false,
|
||||
false)
|
||||
|
||||
@ -69,7 +69,7 @@ static bool iterativelyFlattenCFG(Function &F, AliasAnalysis *AA) {
|
||||
}
|
||||
|
||||
bool FlattenCFGPass::runOnFunction(Function &F) {
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
bool EverChanged = false;
|
||||
// iterativelyFlattenCFG can make some blocks dead.
|
||||
while (iterativelyFlattenCFG(F, AA)) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/IR/ConstantRange.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
@ -61,7 +62,7 @@ namespace {
|
||||
bool runOnFunction(Function &F) override;
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
}
|
||||
|
||||
void findRoots(Function &F, SmallPtrSet<Instruction*,8> &Roots);
|
||||
@ -84,7 +85,9 @@ namespace {
|
||||
}
|
||||
|
||||
char Float2Int::ID = 0;
|
||||
INITIALIZE_PASS(Float2Int, "float2int", "Float to int", false, false)
|
||||
INITIALIZE_PASS_BEGIN(Float2Int, "float2int", "Float to int", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_END(Float2Int, "float2int", "Float to int", false, false)
|
||||
|
||||
// Given a FCmp predicate, return a matching ICmp predicate if one
|
||||
// exists, otherwise return BAD_ICMP_PREDICATE.
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/ConstantFolding.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/Loads.h"
|
||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||
@ -693,10 +694,10 @@ namespace {
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
if (!NoLoads)
|
||||
AU.addRequired<MemoryDependenceAnalysis>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
}
|
||||
|
||||
|
||||
@ -745,7 +746,8 @@ INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_END(GVN, "gvn", "Global Value Numbering", false, false)
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
@ -2410,7 +2412,7 @@ bool GVN::runOnFunction(Function& F) {
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
|
||||
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
VN.setAliasAnalysis(&getAnalysis<AliasAnalysis>());
|
||||
VN.setAliasAnalysis(&getAnalysis<AAResultsWrapperPass>().getAAResults());
|
||||
VN.setMemDep(MD);
|
||||
VN.setDomTree(DT);
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionExpander.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
|
@ -34,10 +34,13 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AliasSetTracker.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/ConstantFolding.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/CFG.h"
|
||||
@ -118,9 +121,12 @@ namespace {
|
||||
AU.addPreservedID(LoopSimplifyID);
|
||||
AU.addRequiredID(LCSSAID);
|
||||
AU.addPreservedID(LCSSAID);
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addPreserved<BasicAAWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
AU.addPreserved<ScalarEvolutionWrapperPass>();
|
||||
AU.addPreserved<SCEVAAWrapperPass>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
}
|
||||
|
||||
@ -166,7 +172,10 @@ INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
|
||||
INITIALIZE_PASS_DEPENDENCY(LCSSA)
|
||||
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass)
|
||||
INITIALIZE_PASS_END(LICM, "licm", "Loop Invariant Code Motion", false, false)
|
||||
|
||||
Pass *llvm::createLICMPass() { return new LICM(); }
|
||||
@ -183,7 +192,7 @@ bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
|
||||
// Get our Loop and Alias Analysis information...
|
||||
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
|
||||
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AliasSetTracker.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/TargetFolder.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
@ -223,7 +224,7 @@ bool LoadCombine::runOnBasicBlock(BasicBlock &BB) {
|
||||
if (skipOptnoneFunction(BB))
|
||||
return false;
|
||||
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
IRBuilder<true, TargetFolder> TheBuilder(
|
||||
BB.getContext(), TargetFolder(BB.getModule()->getDataLayout()));
|
||||
@ -262,8 +263,8 @@ bool LoadCombine::runOnBasicBlock(BasicBlock &BB) {
|
||||
void LoadCombine::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
}
|
||||
|
||||
char LoadCombine::ID = 0;
|
||||
@ -274,7 +275,8 @@ BasicBlockPass *llvm::createLoadCombinePass() {
|
||||
|
||||
INITIALIZE_PASS_BEGIN(LoadCombine, "load-combine", "Combine Adjacent Loads",
|
||||
false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_END(LoadCombine, "load-combine", "Combine Adjacent Loads",
|
||||
false, false)
|
||||
|
||||
|
@ -44,8 +44,11 @@
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionExpander.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
@ -94,14 +97,17 @@ public:
|
||||
AU.addPreservedID(LoopSimplifyID);
|
||||
AU.addRequiredID(LCSSAID);
|
||||
AU.addPreservedID(LCSSAID);
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addRequired<ScalarEvolutionWrapperPass>();
|
||||
AU.addPreserved<ScalarEvolutionWrapperPass>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<SCEVAAWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
AU.addRequired<TargetTransformInfoWrapperPass>();
|
||||
AU.addPreserved<BasicAAWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -148,7 +154,10 @@ INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
|
||||
INITIALIZE_PASS_DEPENDENCY(LCSSA)
|
||||
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
|
||||
INITIALIZE_PASS_END(LoopIdiomRecognize, "loop-idiom", "Recognize loop idioms",
|
||||
false, false)
|
||||
@ -189,7 +198,7 @@ bool LoopIdiomRecognize::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
if (Name == "memset" || Name == "memcpy")
|
||||
return false;
|
||||
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
|
@ -438,7 +438,7 @@ struct LoopInterchange : public FunctionPass {
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<ScalarEvolutionWrapperPass>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
AU.addRequired<DependenceAnalysis>();
|
||||
@ -1286,7 +1286,7 @@ bool LoopInterchangeTransform::adjustLoopLinks() {
|
||||
char LoopInterchange::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(LoopInterchange, "loop-interchange",
|
||||
"Interchanges loops for cache reuse", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(DependenceAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
|
||||
|
@ -147,7 +147,7 @@ namespace {
|
||||
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
AU.addPreserved<LoopInfoWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
@ -449,7 +449,7 @@ namespace {
|
||||
|
||||
char LoopReroll::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(LoopReroll, "loop-reroll", "Reroll loops", false, false)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass)
|
||||
@ -1466,7 +1466,7 @@ bool LoopReroll::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
if (skipOptnoneFunction(L))
|
||||
return false;
|
||||
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
|
||||
TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
||||
|
@ -14,11 +14,14 @@
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/CodeMetrics.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/Analysis/TargetTransformInfo.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/CFG.h"
|
||||
@ -57,7 +60,7 @@ namespace {
|
||||
|
||||
// LCSSA form makes instruction renaming easier.
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
@ -67,7 +70,10 @@ namespace {
|
||||
AU.addRequiredID(LCSSAID);
|
||||
AU.addPreservedID(LCSSAID);
|
||||
AU.addPreserved<ScalarEvolutionWrapperPass>();
|
||||
AU.addPreserved<SCEVAAWrapperPass>();
|
||||
AU.addRequired<TargetTransformInfoWrapperPass>();
|
||||
AU.addPreserved<BasicAAWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
}
|
||||
|
||||
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
|
||||
@ -90,6 +96,9 @@ INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopSimplify)
|
||||
INITIALIZE_PASS_DEPENDENCY(LCSSA)
|
||||
INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_END(LoopRotate, "loop-rotate", "Rotate Loops", false, false)
|
||||
|
||||
Pass *llvm::createLoopRotatePass(int MaxHeaderSize) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
@ -324,9 +325,9 @@ namespace {
|
||||
AU.addRequired<AssumptionCacheTracker>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<MemoryDependenceAnalysis>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
AU.addPreserved<MemoryDependenceAnalysis>();
|
||||
}
|
||||
|
||||
@ -359,7 +360,8 @@ INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_END(MemCpyOpt, "memcpyopt", "MemCpy Optimization",
|
||||
false, false)
|
||||
|
||||
@ -502,7 +504,7 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
|
||||
if (C) {
|
||||
// Check that nothing touches the dest of the "copy" between
|
||||
// the call and the store.
|
||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
MemoryLocation StoreLoc = MemoryLocation::get(SI);
|
||||
for (BasicBlock::iterator I = --BasicBlock::iterator(SI),
|
||||
E = C; I != E; --I) {
|
||||
@ -703,7 +705,7 @@ bool MemCpyOpt::performCallSlotOptzn(Instruction *cpy,
|
||||
// unexpected manner, for example via a global, which we deduce from
|
||||
// the use analysis, we also need to know that it does not sneakily
|
||||
// access dest. We rely on AA to figure this out for us.
|
||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
ModRefInfo MR = AA.getModRefInfo(C, cpyDest, srcSize);
|
||||
// If necessary, perform additional analysis.
|
||||
if (MR != MRI_NoModRef)
|
||||
@ -779,7 +781,7 @@ bool MemCpyOpt::processMemCpyMemCpyDependence(MemCpyInst *M, MemCpyInst *MDep) {
|
||||
if (!MDepLen || !MLen || MDepLen->getZExtValue() < MLen->getZExtValue())
|
||||
return false;
|
||||
|
||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
// Verify that the copied-from memory doesn't change in between the two
|
||||
// transfers. For example, in:
|
||||
@ -1031,7 +1033,7 @@ bool MemCpyOpt::processMemCpy(MemCpyInst *M) {
|
||||
/// Transforms memmove calls to memcpy calls when the src/dst are guaranteed
|
||||
/// not to alias.
|
||||
bool MemCpyOpt::processMemMove(MemMoveInst *M) {
|
||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
if (!TLI->has(LibFunc::memmove))
|
||||
return false;
|
||||
|
@ -78,6 +78,7 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/Loads.h"
|
||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
||||
@ -117,9 +118,9 @@ private:
|
||||
// This transformation requires dominator postdominator info
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
AU.addPreserved<MemoryDependenceAnalysis>();
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
}
|
||||
|
||||
// Helper routines
|
||||
@ -169,7 +170,8 @@ INITIALIZE_PASS_BEGIN(MergedLoadStoreMotion, "mldst-motion",
|
||||
"MergedLoadStoreMotion", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(MemoryDependenceAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_END(MergedLoadStoreMotion, "mldst-motion",
|
||||
"MergedLoadStoreMotion", false, false)
|
||||
|
||||
@ -564,7 +566,7 @@ bool MergedLoadStoreMotion::mergeStores(BasicBlock *T) {
|
||||
///
|
||||
bool MergedLoadStoreMotion::runOnFunction(Function &F) {
|
||||
MD = getAnalysisIfAvailable<MemoryDependenceAnalysis>();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
bool Changed = false;
|
||||
DEBUG(dbgs() << "Instruction Merger\n");
|
||||
|
@ -227,15 +227,15 @@ void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM) {
|
||||
}
|
||||
|
||||
void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM) {
|
||||
unwrap(PM)->add(createTypeBasedAliasAnalysisPass());
|
||||
unwrap(PM)->add(createTypeBasedAAWrapperPass());
|
||||
}
|
||||
|
||||
void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM) {
|
||||
unwrap(PM)->add(createScopedNoAliasAAPass());
|
||||
unwrap(PM)->add(createScopedNoAliasAAWrapperPass());
|
||||
}
|
||||
|
||||
void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM) {
|
||||
unwrap(PM)->add(createBasicAliasAnalysisPass());
|
||||
unwrap(PM)->add(createBasicAAWrapperPass());
|
||||
}
|
||||
|
||||
void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM) {
|
||||
|
@ -48,7 +48,7 @@ namespace {
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
FunctionPass::getAnalysisUsage(AU);
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.addRequired<AAResultsWrapperPass>();
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
@ -66,7 +66,7 @@ char Sinking::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(Sinking, "sink", "Code sinking", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
|
||||
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
||||
INITIALIZE_PASS_END(Sinking, "sink", "Code sinking", false, false)
|
||||
|
||||
FunctionPass *llvm::createSinkingPass() { return new Sinking(); }
|
||||
@ -99,7 +99,7 @@ bool Sinking::AllUsesDominatedByBlock(Instruction *Inst,
|
||||
bool Sinking::runOnFunction(Function &F) {
|
||||
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
||||
LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
||||
AA = &getAnalysis<AliasAnalysis>();
|
||||
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
||||
|
||||
bool MadeChange, EverMadeChange = false;
|
||||
|
||||
|
@ -54,12 +54,12 @@ PreserveAlignmentAssumptions("preserve-alignment-assumptions-during-inlining",
|
||||
cl::desc("Convert align attributes to assumptions during inlining."));
|
||||
|
||||
bool llvm::InlineFunction(CallInst *CI, InlineFunctionInfo &IFI,
|
||||
bool InsertLifetime) {
|
||||
return InlineFunction(CallSite(CI), IFI, InsertLifetime);
|
||||
AAResults *CalleeAAR, bool InsertLifetime) {
|
||||
return InlineFunction(CallSite(CI), IFI, CalleeAAR, InsertLifetime);
|
||||
}
|
||||
bool llvm::InlineFunction(InvokeInst *II, InlineFunctionInfo &IFI,
|
||||
bool InsertLifetime) {
|
||||
return InlineFunction(CallSite(II), IFI, InsertLifetime);
|
||||
AAResults *CalleeAAR, bool InsertLifetime) {
|
||||
return InlineFunction(CallSite(II), IFI, CalleeAAR, InsertLifetime);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -490,7 +490,7 @@ static void CloneAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap) {
|
||||
/// parameters with noalias metadata specifying the new scope, and tag all
|
||||
/// non-derived loads, stores and memory intrinsics with the new alias scopes.
|
||||
static void AddAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap,
|
||||
const DataLayout &DL, AliasAnalysis *AA) {
|
||||
const DataLayout &DL, AAResults *CalleeAAR) {
|
||||
if (!EnableNoAliasConversion)
|
||||
return;
|
||||
|
||||
@ -575,8 +575,8 @@ static void AddAliasScopeMetadata(CallSite CS, ValueToValueMapTy &VMap,
|
||||
continue;
|
||||
|
||||
IsFuncCall = true;
|
||||
if (AA) {
|
||||
FunctionModRefBehavior MRB = AA->getModRefBehavior(ICS);
|
||||
if (CalleeAAR) {
|
||||
FunctionModRefBehavior MRB = CalleeAAR->getModRefBehavior(ICS);
|
||||
if (MRB == FMRB_OnlyAccessesArgumentPointees ||
|
||||
MRB == FMRB_OnlyReadsArgumentPointees)
|
||||
IsArgMemOnlyCall = true;
|
||||
@ -1011,7 +1011,7 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
|
||||
/// exists in the instruction stream. Similarly this will inline a recursive
|
||||
/// function by one level.
|
||||
bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
bool InsertLifetime) {
|
||||
AAResults *CalleeAAR, bool InsertLifetime) {
|
||||
Instruction *TheCall = CS.getInstruction();
|
||||
assert(TheCall->getParent() && TheCall->getParent()->getParent() &&
|
||||
"Instruction not in function!");
|
||||
@ -1136,7 +1136,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
CloneAliasScopeMetadata(CS, VMap);
|
||||
|
||||
// Add noalias metadata if necessary.
|
||||
AddAliasScopeMetadata(CS, VMap, DL, IFI.AA);
|
||||
AddAliasScopeMetadata(CS, VMap, DL, CalleeAAR);
|
||||
|
||||
// FIXME: We could register any cloned assumptions instead of clearing the
|
||||
// whole function's cache.
|
||||
|
@ -31,8 +31,10 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
@ -297,8 +299,10 @@ struct LCSSA : public FunctionPass {
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
AU.addPreservedID(LoopSimplifyID);
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
AU.addPreserved<ScalarEvolutionWrapperPass>();
|
||||
AU.addPreserved<SCEVAAWrapperPass>();
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -307,6 +311,8 @@ char LCSSA::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(LCSSA, "lcssa", "Loop-Closed SSA Form Pass", false, false)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass)
|
||||
INITIALIZE_PASS_END(LCSSA, "lcssa", "Loop-Closed SSA Form Pass", false, false)
|
||||
|
||||
Pass *llvm::createLCSSAPass() { return new LCSSA(); }
|
||||
|
@ -44,11 +44,14 @@
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/BasicAliasAnalysis.h"
|
||||
#include "llvm/Analysis/AssumptionCache.h"
|
||||
#include "llvm/Analysis/DependenceAnalysis.h"
|
||||
#include "llvm/Analysis/GlobalsModRef.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/ScalarEvolution.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
|
||||
#include "llvm/IR/CFG.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
@ -759,8 +762,11 @@ namespace {
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
AU.addPreserved<LoopInfoWrapperPass>();
|
||||
|
||||
AU.addPreserved<AliasAnalysis>();
|
||||
AU.addPreserved<BasicAAWrapperPass>();
|
||||
AU.addPreserved<AAResultsWrapperPass>();
|
||||
AU.addPreserved<GlobalsAAWrapperPass>();
|
||||
AU.addPreserved<ScalarEvolutionWrapperPass>();
|
||||
AU.addPreserved<SCEVAAWrapperPass>();
|
||||
AU.addPreserved<DependenceAnalysis>();
|
||||
AU.addPreservedID(BreakCriticalEdgesID); // No critical edges added.
|
||||
}
|
||||
@ -776,6 +782,9 @@ INITIALIZE_PASS_BEGIN(LoopSimplify, "loop-simplify",
|
||||
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
||||
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
||||
INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass)
|
||||
INITIALIZE_PASS_END(LoopSimplify, "loop-simplify",
|
||||
"Canonicalize natural loops", false, false)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user