[llvm] r250894 - [AA] Enhance the new AliasAnalysis infrastructure with an optional
Michael Gottesman via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 21 09:24:28 PDT 2015
Thanks Chandler!
Michael
> On Oct 21, 2015, at 5:15 AM, Chandler Carruth via llvm-commits <llvm-commits at lists.llvm.org> wrote:
>
> Author: chandlerc
> Date: Wed Oct 21 07:15:19 2015
> New Revision: 250894
>
> URL: http://llvm.org/viewvc/llvm-project?rev=250894&view=rev
> Log:
> [AA] Enhance the new AliasAnalysis infrastructure with an optional
> "external" AA wrapper pass.
>
> This is a generic hook that can be used to thread custom code into the
> primary AAResultsWrapperPass for the legacy pass manager in order to
> allow it to merge external AA results into the AA results it is
> building. It does this by threading in a raw callback and so it is
> *very* powerful and should serve almost any use case I have come up with
> for extending the set of alias analyses used. The only thing not well
> supported here is using a *different order* of alias analyses. That form
> of extension *is* supportable with the new pass manager, and I can make
> the callback structure here more elaborate to support it in the legacy
> pass manager if this is a critical use case that people are already
> depending on, but the only use cases I have heard of thus far should be
> reasonably satisfied by this simpler extension mechanism.
>
> It is hard to test this using normal facilities (the built-in AAs don't
> use this for obvious reasons) so I've written a fairly extensive set of
> custom passes in the alias analysis unit test that should be an
> excellent test case because it models the out-of-tree users: it adds
> a totally custom AA to the system. This should also serve as
> a reasonably good example and guide for out-of-tree users to follow in
> order to rig up their existing alias analyses.
>
> No support in opt for commandline control is provided here however. I'm
> really unhappy with the kind of contortions that would be required to
> support that. It would fully re-introduce the analysis group
> self-recursion kind of patterns. =/
>
> I've heard from out-of-tree users that this will unblock their use cases
> with extending AAs on top of the new infrastructure and let us retain
> the new analysis-group-free-world.
>
> Differential Revision: http://reviews.llvm.org/D13418
>
> Modified:
> llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
> llvm/trunk/include/llvm/InitializePasses.h
> llvm/trunk/lib/Analysis/AliasAnalysis.cpp
> llvm/trunk/unittests/Analysis/AliasAnalysisTest.cpp
>
> Modified: llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AliasAnalysis.h?rev=250894&r1=250893&r2=250894&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/AliasAnalysis.h (original)
> +++ llvm/trunk/include/llvm/Analysis/AliasAnalysis.h Wed Oct 21 07:15:19 2015
> @@ -1024,6 +1024,16 @@ public:
>
> FunctionPass *createAAResultsWrapperPass();
>
> +/// A wrapper pass around a callback which can be used to populate the
> +/// AAResults in the AAResultsWrapperPass from an external AA.
> +///
> +/// The callback provided here will be used each time we prepare an AAResults
> +/// object, and will receive a reference to the function wrapper pass, the
> +/// function, and the AAResults object to populate. This should be used when
> +/// setting up a custom pass pipeline to inject a hook into the AA results.
> +ImmutablePass *createExternalAAWrapperPass(
> + std::function<void(Pass &, Function &, AAResults &)> Callback);
> +
> /// 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.
>
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=250894&r1=250893&r2=250894&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Wed Oct 21 07:15:19 2015
> @@ -85,6 +85,7 @@ void initializeCFGOnlyViewerPass(PassReg
> void initializeCFGPrinterPass(PassRegistry&);
> void initializeCFGSimplifyPassPass(PassRegistry&);
> void initializeCFLAAWrapperPassPass(PassRegistry&);
> +void initializeExternalAAWrapperPassPass(PassRegistry&);
> void initializeForwardControlFlowIntegrityPass(PassRegistry&);
> void initializeFlattenCFGPassPass(PassRegistry&);
> void initializeStructurizeCFGPass(PassRegistry&);
>
> Modified: llvm/trunk/lib/Analysis/AliasAnalysis.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysis.cpp?rev=250894&r1=250893&r2=250894&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/AliasAnalysis.cpp (original)
> +++ llvm/trunk/lib/Analysis/AliasAnalysis.cpp Wed Oct 21 07:15:19 2015
> @@ -364,6 +364,39 @@ bool AAResults::canInstructionRangeModRe
> // Provide a definition for the root virtual destructor.
> AAResults::Concept::~Concept() {}
>
> +namespace {
> +/// A wrapper pass for external alias analyses. This just squirrels away the
> +/// callback used to run any analyses and register their results.
> +struct ExternalAAWrapperPass : ImmutablePass {
> + typedef std::function<void(Pass &, Function &, AAResults &)> CallbackT;
> +
> + CallbackT CB;
> +
> + static char ID;
> +
> + ExternalAAWrapperPass() : ImmutablePass(ID) {
> + initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry());
> + }
> + explicit ExternalAAWrapperPass(CallbackT CB)
> + : ImmutablePass(ID), CB(std::move(CB)) {
> + initializeExternalAAWrapperPassPass(*PassRegistry::getPassRegistry());
> + }
> +
> + void getAnalysisUsage(AnalysisUsage &AU) const override {
> + AU.setPreservesAll();
> + }
> +};
> +}
> +
> +char ExternalAAWrapperPass::ID = 0;
> +INITIALIZE_PASS(ExternalAAWrapperPass, "external-aa", "External Alias Analysis",
> + false, true)
> +
> +ImmutablePass *
> +llvm::createExternalAAWrapperPass(ExternalAAWrapperPass::CallbackT Callback) {
> + return new ExternalAAWrapperPass(std::move(Callback));
> +}
> +
> AAResultsWrapperPass::AAResultsWrapperPass() : FunctionPass(ID) {
> initializeAAResultsWrapperPassPass(*PassRegistry::getPassRegistry());
> }
> @@ -374,6 +407,7 @@ INITIALIZE_PASS_BEGIN(AAResultsWrapperPa
> "Function Alias Analysis Results", false, true)
> INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass)
> INITIALIZE_PASS_DEPENDENCY(CFLAAWrapperPass)
> +INITIALIZE_PASS_DEPENDENCY(ExternalAAWrapperPass)
> INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
> INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass)
> INITIALIZE_PASS_DEPENDENCY(SCEVAAWrapperPass)
> @@ -425,6 +459,12 @@ bool AAResultsWrapperPass::runOnFunction
> if (auto *WrapperPass = getAnalysisIfAvailable<CFLAAWrapperPass>())
> AAR->addAAResult(WrapperPass->getResult());
>
> + // If available, run an external AA providing callback over the results as
> + // well.
> + if (auto *WrapperPass = getAnalysisIfAvailable<ExternalAAWrapperPass>())
> + if (WrapperPass->CB)
> + WrapperPass->CB(*this, F, *AAR);
> +
> // Analyses don't mutate the IR, so return false.
> return false;
> }
>
> Modified: llvm/trunk/unittests/Analysis/AliasAnalysisTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/AliasAnalysisTest.cpp?rev=250894&r1=250893&r2=250894&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/Analysis/AliasAnalysisTest.cpp (original)
> +++ llvm/trunk/unittests/Analysis/AliasAnalysisTest.cpp Wed Oct 21 07:15:19 2015
> @@ -8,17 +8,137 @@
> //===----------------------------------------------------------------------===//
>
> #include "llvm/Analysis/AliasAnalysis.h"
> +#include "llvm/ADT/SetVector.h"
> #include "llvm/Analysis/AssumptionCache.h"
> #include "llvm/Analysis/BasicAliasAnalysis.h"
> #include "llvm/Analysis/TargetLibraryInfo.h"
> +#include "llvm/AsmParser/Parser.h"
> #include "llvm/IR/Constants.h"
> #include "llvm/IR/Instructions.h"
> +#include "llvm/IR/InstIterator.h"
> #include "llvm/IR/LLVMContext.h"
> +#include "llvm/IR/LegacyPassManager.h"
> #include "llvm/IR/Module.h"
> #include "llvm/Support/CommandLine.h"
> +#include "llvm/Support/SourceMgr.h"
> #include "gtest/gtest.h"
>
> +using namespace llvm;
> +
> +// Set up some test passes.
> namespace llvm {
> +void initializeAATestPassPass(PassRegistry&);
> +void initializeTestCustomAAWrapperPassPass(PassRegistry&);
> +}
> +
> +namespace {
> +struct AATestPass : FunctionPass {
> + static char ID;
> + AATestPass() : FunctionPass(ID) {
> + initializeAATestPassPass(*PassRegistry::getPassRegistry());
> + }
> +
> + void getAnalysisUsage(AnalysisUsage &AU) const override {
> + AU.addRequired<AAResultsWrapperPass>();
> + AU.setPreservesAll();
> + }
> +
> + bool runOnFunction(Function &F) override {
> + AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
> +
> + SetVector<Value *> Pointers;
> + for (Argument &A : F.args())
> + if (A.getType()->isPointerTy())
> + Pointers.insert(&A);
> + for (Instruction &I : instructions(F))
> + if (I.getType()->isPointerTy())
> + Pointers.insert(&I);
> +
> + for (Value *P1 : Pointers)
> + for (Value *P2 : Pointers)
> + (void)AA.alias(P1, MemoryLocation::UnknownSize, P2,
> + MemoryLocation::UnknownSize);
> +
> + return false;
> + }
> +};
> +}
> +
> +char AATestPass::ID = 0;
> +INITIALIZE_PASS_BEGIN(AATestPass, "aa-test-pas", "Alias Analysis Test Pass",
> + false, true)
> +INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
> +INITIALIZE_PASS_END(AATestPass, "aa-test-pass", "Alias Analysis Test Pass",
> + false, true)
> +
> +namespace {
> +/// A test customizable AA result. It merely accepts a callback to run whenever
> +/// it receives an alias query. Useful for testing that a particular AA result
> +/// is reached.
> +struct TestCustomAAResult : AAResultBase<TestCustomAAResult> {
> + friend AAResultBase<TestCustomAAResult>;
> +
> + std::function<void()> CB;
> +
> + explicit TestCustomAAResult(const TargetLibraryInfo &TLI,
> + std::function<void()> CB)
> + : AAResultBase(TLI), CB(std::move(CB)) {}
> + TestCustomAAResult(TestCustomAAResult &&Arg)
> + : AAResultBase(std::move(Arg)), CB(std::move(Arg.CB)) {}
> +
> + bool invalidate(Function &, const PreservedAnalyses &) { return false; }
> +
> + AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
> + CB();
> + return MayAlias;
> + }
> +};
> +}
> +
> +namespace {
> +/// A wrapper pass for the legacy pass manager to use with the above custom AA
> +/// result.
> +class TestCustomAAWrapperPass : public ImmutablePass {
> + std::function<void()> CB;
> + std::unique_ptr<TestCustomAAResult> Result;
> +
> +public:
> + static char ID;
> +
> + explicit TestCustomAAWrapperPass(
> + std::function<void()> CB = std::function<void()>())
> + : ImmutablePass(ID), CB(std::move(CB)) {
> + initializeTestCustomAAWrapperPassPass(*PassRegistry::getPassRegistry());
> + }
> +
> + void getAnalysisUsage(AnalysisUsage &AU) const override {
> + AU.setPreservesAll();
> + AU.addRequired<TargetLibraryInfoWrapperPass>();
> + }
> +
> + bool doInitialization(Module &M) override {
> + Result.reset(new TestCustomAAResult(
> + getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(), std::move(CB)));
> + return true;
> + }
> +
> + bool doFinalization(Module &M) override {
> + Result.reset();
> + return true;
> + }
> +
> + TestCustomAAResult &getResult() { return *Result; }
> + const TestCustomAAResult &getResult() const { return *Result; }
> +};
> +}
> +
> +char TestCustomAAWrapperPass::ID = 0;
> +INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass, "test-custom-aa",
> + "Test Custom AA Wrapper Pass", false, true)
> +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
> +INITIALIZE_PASS_END(TestCustomAAWrapperPass, "test-custom-aa",
> + "Test Custom AA Wrapper Pass", false, true)
> +
> namespace {
>
> class AliasAnalysisTest : public testing::Test {
> @@ -87,5 +207,50 @@ TEST_F(AliasAnalysisTest, getModRefInfo)
> EXPECT_EQ(AA.getModRefInfo(AtomicRMW), MRI_ModRef);
> }
>
> +class AAPassInfraTest : public testing::Test {
> +protected:
> + LLVMContext &C;
> + SMDiagnostic Err;
> + std::unique_ptr<Module> M;
> +
> +public:
> + AAPassInfraTest()
> + : C(getGlobalContext()),
> + M(parseAssemblyString("define i32 @f(i32* %x, i32* %y) {\n"
> + "entry:\n"
> + " %lx = load i32, i32* %x\n"
> + " %ly = load i32, i32* %y\n"
> + " %sum = add i32 %lx, %ly\n"
> + " ret i32 %sum\n"
> + "}\n",
> + Err, C)) {
> + assert(M && "Failed to build the module!");
> + }
> +};
> +
> +TEST_F(AAPassInfraTest, injectExternalAA) {
> + legacy::PassManager PM;
> +
> + // Register our custom AA's wrapper pass manually.
> + bool IsCustomAAQueried = false;
> + PM.add(new TestCustomAAWrapperPass([&] { IsCustomAAQueried = true; }));
> +
> + // Now add the external AA wrapper with a lambda which queries for the
> + // wrapper around our custom AA and adds it to the results.
> + PM.add(createExternalAAWrapperPass([](Pass &P, Function &, AAResults &AAR) {
> + if (auto *WrapperPass = P.getAnalysisIfAvailable<TestCustomAAWrapperPass>())
> + AAR.addAAResult(WrapperPass->getResult());
> + }));
> +
> + // And run a pass that will make some alias queries. This will automatically
> + // trigger the rest of the alias analysis stack to be run. It is analagous to
> + // building a full pass pipeline with any of the existing pass manager
> + // builders.
> + PM.add(new AATestPass());
> + PM.run(*M);
> +
> + // Finally, ensure that our custom AA was indeed queried.
> + EXPECT_TRUE(IsCustomAAQueried);
> +}
> +
> } // end anonymous namspace
> -} // end llvm namespace
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list