Out-of-tree AA pass used from ModulePass

(Please keep me in CC, not sure my subscription request has made it through yet)
Hi all,

I am building a fairly extensive set of compiler passes out-of-tree with LLVM, and this all works nicely, except for tying my custom AA pass MyAA into the overall AA aggregator via AAResultsWrapper. As far as I can see, the ExternalAAWrapper does what I want and allows me to add an out-of-tree AA pass to the list of passes that is consulted when my other passes (let's say MyFuncPass) need an alias analysis result, by having registered a call-back in ExternalAAWrapper that will add MyAAResult into llvm::AAResult, which then gets consulted in AA queries if needed. This works for now (with some hacks).

The problem is, however, when I convert MyFuncPass to a module pass, and I am then trying to get aa results for my functions. The problem is that the call-back I registered (I see that happening!) with ExternalAAWrapper is never being run, so my AA results are not added to the mix. I am using opt and the legacy pass managers, and I am struggling to understand how this should be used correctly, and why the call-back is not executed in time when turning my pass into a ModulePass.

I am getting my aa results via getAnalysis<AAResultsWrapperPass>().getAAResults() in MyFuncPass, and with getAnalysis<AAResultsWrapperPass>(f).getAAResults() with f being the function I am currently looking into in the ModulePass.

I am not really sure which passes I must specify with addRequired(..) or on the command line and it seems the documentation around AA in general and external AA specifically is somewhat outdated / sparse.

Does this fairly high-level description ring any bells? My code is pretty wild at this point, so it is not trivial to create a simple example, but I can do it if it would be helpful here. Further, for various reasons (started this project a fair while ago) I am still on LLVM 8, but AFAICS, not much has changed in this area. That said, I don't have a great understanding how the whole (legacy) pass manager piece hangs together.

Thanks,
  Stephan

Hey Stephan,

To get function-level AA results in a ModulePass with the legacy pass manager you should use llvm::LegacyAARGetter. Because AA results are per-function, you call this with the function you want alias results about. That should get you any AA you registered with the external AA wrapper (we use the same mechanism in Unity’s HPC# Burst compiler for instance).

Cheers,
-Neil.

Hi Neil,

Thanks for the fast response, that looks like it is the right thing, however, I am still not getting my external AA pass invoked via the call-back. There are a few things that I notice when looking at uses of llvm::LegacyAAGetter (in LLVM) vs my code:

(1) Uses of it are usually wrapped in a function_ref<AAResults &(Function&)> which delays calling the functions, which I don’t know what it is used for
(2) My code has a module pass querying another function pass result which in turn queries the AA pass
(3) I am using the old-style of pass structure, instead of mixins

Just for testing, I get rid of both (1) and (2) by simply calling LegacyAARResult(*this)(f).getModRefBehavior(<something>) from inside my ModulePass, but it does not get daisy chained to my MyAA / the call back registered with ExternalAAWrapper. If I use the function_ref approach, I somehow get a segment violation (I think I don't understand some lifetime challenge here).

Is the code you reference available somewhere for me to have a look or some other code that uses an external AA pass from the command line? A quick look on GitHub didn't turn up too many (just a SCAF piece) results... otherwise, I will try to create a small example and post that here.

Thanks,
  Stephan

Hey Stephan,

Code is all closed-source secret-sauce, but here is how we register our AA via the external AA callback:

struct Functor final
{
Functor() = default;
Functor(const Functor& other)
{
// We don’t actually copy any of our analysis because they should not have been initialized yet.
}

void operator()(llvm::Pass& pass, llvm::Function& function, llvm::AAResults& aliasAnalysis)
{
// Add our Unity Burst Alias Analysis tracking.
ubaaAliasAnalysis.invalidate(function);
aliasAnalysis.addAAResult(ubaaAliasAnalysis);
}

private:
UBAAAliasAnalysis ubaaAliasAnalysis;
};

llvm::Pass* burst_CreateExtraAliasAnalysisLegacyPass()
{
std::function<void(llvm::Pass&, llvm::Function&, llvm::AAResults&)> func = Functor();
return createExternalAAWrapperPass(func);
}

Hopefully that can help!

Cheers,
-Neil.

Hi Neil,

Thanks for your response, that was certainly helpful in telling me that I was on the right track. With a bit of GDBing and following through my LLVM code, I noticed that I am missing

https://github.com/llvm/llvm-project/commit/103a58c8f2b0a62a42f6eedcdef38222ff22a538

in my old LLVM 8 version. That would explain why it works for you, and not for me. Many thanks for the support, I will backport this to my LLVM version.

Stephan