RegisterAnalysisGroup

Can someone explain how RegisterPass and RegisterAnalysisGroup
conspire to pick the right member of an analysis group when command-line
options dictate non-default implementations?

For example, when I pass -anders-aa to opt, where in the code is that option
parsed and setNormalCtor called on the analysis group to change from the
default basicaa?

                                                             -Dave

When basicaa registers itself as part of the analysis group, it uses:

   RegisterPass<BasicAliasAnalysis>
   X("basicaa", "Basic Alias Analysis (default AA impl)");

   // Declare that we implement the AliasAnalysis interface
   RegisterAnalysisGroup<AliasAnalysis, true> Y(X);

The "true" says that it is the default,

-Chris

Right, I get that. My question is how a pass that requires AliasAnalysis
gets Andersens when -anders-aa is passed on the command-line.
Someone has to call setNormalCtor on the PassInfo for the AliasAnalysis
group but I can't fgind that code anywhere.

Another question:

I'm debugging some analysis group code and I instrumented the
registration constructors. I see weird things like this:

Adding No Alias Analysis (always returns 'may' alias) to group
Adding Basic Alias Analysis (default AA impl) to group
Set ctor for
Adding AA use debugger to group
Adding Count Alias Analysis Query Responses to group
Registering analysis group Alias Analysis

Huh? How can group members be registered before the group is?
How does that work?

When I added a new coalescer to the compiler and tried to use it, I
got SimpleRegisterCoalescing (the default) instead. I'm trying to
figure out why.

                                     -Dave

> When basicaa registers itself as part of the analysis group, it uses:
>
> RegisterPass<BasicAliasAnalysis>
> X("basicaa", "Basic Alias Analysis (default AA impl)");
>
> // Declare that we implement the AliasAnalysis interface
> RegisterAnalysisGroup<AliasAnalysis, true> Y(X);
>
> The "true" says that it is the default,

Right, I get that. My question is how a pass that requires AliasAnalysis
gets Andersens when -anders-aa is passed on the command-line.
Someone has to call setNormalCtor on the PassInfo for the AliasAnalysis
group but I can't fgind that code anywhere.

Hmm, I'm not quite correct here. I seem to recall someone at some point
saying that when searching for a member of an analysis group, the first
implementation constructed will be used.

Is the searching code implemented by AnalysisResolver::findImplPass?

I'm debugging some analysis group code and I instrumented the
registration constructors. I see weird things like this:

Just FYI, llvm's version of cerr, et. al., won't work in constructors called
during program started because <iostream> isn't included in those
files and therefore might not be constructed yet.

I believe the same problem is the reason that some alias analysis
passes are constrcuted before the AliasAnalysis analysis group is
constructed. There's no mechanism to determine order of construction.

I still don't understand how constructing members of an analysis group
before the analysis group is constructed can work at all. Oh, I guess this
clase in RegisterAGBase's constructor takes care of it:

  InterfaceInfo = const_cast<PassInfo*>(Pass::lookupPassInfo(InterfaceID));
  if (InterfaceInfo == 0) {
    // First reference to Interface, register it now.
    registerPass();
    InterfaceInfo = &PIObj;
  }

Is that right?

This PassManager stuff is extremely confusing and not well documented. Does
it really buy us all that much? I can't believe there's much room for
rescheduling passes unless llvm actually reschedules optimizations, which
would be *very* bad indeed. Otherwise, isn't PassManager just keeping
track of when analysis information is invalidated? If so, we just need a
bitvector for that, no need for all this fancy registration code.

                                               -Dave

When basicaa registers itself as part of the analysis group, it uses:

   RegisterPass<BasicAliasAnalysis>
   X("basicaa", "Basic Alias Analysis (default AA impl)");

   // Declare that we implement the AliasAnalysis interface
   RegisterAnalysisGroup<AliasAnalysis, true> Y(X);

The "true" says that it is the default,

Right, I get that. My question is how a pass that requires AliasAnalysis
gets Andersens when -anders-aa is passed on the command-line.
Someone has to call setNormalCtor on the PassInfo for the AliasAnalysis
group but I can't fgind that code anywhere.

Hmm, I'm not quite correct here. I seem to recall someone at some point
saying that when searching for a member of an analysis group, the first
implementation constructed will be used.

Is the searching code implemented by AnalysisResolver::findImplPass?

Consider a pass manager queue like this:

-gvn

In this case, the passmanager goes to add GVN and sees that gvn requires alias analysis. However, alias analysis is not already available. As such it creates an instance of the default impl, producing:

-basicaa -gvn

Consider the passmanager running on a queu like this:

-no-aa -gvn

In this case, -no-aa does not require anything so it gets added to the queue. no-aa provides the AA analysis group.

Next step, GVN is added. As above, -gvn requires alias analysis. The passmanager sees that AA is already available, so it uses it instead of adding an instance of basicaa. This yields:

-no-aa -gvn

This is exactly by design.

I'm debugging some analysis group code and I instrumented the
registration constructors. I see weird things like this:

Just FYI, llvm's version of cerr, et. al., won't work in constructors called
during program started because <iostream> isn't included in those
files and therefore might not be constructed yet.

Right. The only reason you should want to do this is because of debugging. For local debugging purposes, it's fine to use <iostream> obviously.

I believe the same problem is the reason that some alias analysis
passes are constrcuted before the AliasAnalysis analysis group is
constructed. There's no mechanism to determine order of construction.

This shouldn't be required. The analysisgroup is created on demand.

I still don't understand how constructing members of an analysis group
before the analysis group is constructed can work at all. Oh, I guess this
clase in RegisterAGBase's constructor takes care of it:

  InterfaceInfo = const_cast<PassInfo*>(Pass::lookupPassInfo(InterfaceID));
  if (InterfaceInfo == 0) {
    // First reference to Interface, register it now.
    registerPass();
    InterfaceInfo = &PIObj;
  }

Is that right?

Yes.

This PassManager stuff is extremely confusing and not well documented.

Hrm?
http://llvm.org/docs/WritingAnLLVMPass.html

Does
it really buy us all that much?

Yes.

I can't believe there's much room for
rescheduling passes unless llvm actually reschedules optimizations, which
would be *very* bad indeed.

The PassManager does a lot of stuff, plz read the docs.

Otherwise, isn't PassManager just keeping
track of when analysis information is invalidated?

No.

-Chris

Consider the passmanager running on a queu like this:

-no-aa -gvn

In this case, -no-aa does not require anything so it gets added to the queue. no-aa provides the AA analysis group.

Next step, GVN is added. As above, -gvn requires alias analysis. The passmanager sees that AA is already available, so it uses it instead of adding an instance of basicaa. This yields:

-no-aa -gvn

This is exactly by design.

Yep, I understand that too. But it isn't working for register
coalescing for some reason. That's what I'm trying to figure
out and it's pretty tough.

This PassManager stuff is extremely confusing and not well documented.

Hrm?
Writing an LLVM Pass — LLVM 18.0.0git documentation

That doesn't document the implementation at all. It's a good high-level
document about how to register a pass with PassManager but doesn't say
anything about the underlying mechanism. It's not a document useful
for debugging problems beyond mentioning --debug-pass.

There's a lot of tricky global constructor stuff going on to register
passes, parse options, etc. Every time I have to work in this area
it's hard. That's been my experience.

I can't believe there's much room for
rescheduling passes unless llvm actually reschedules optimizations, which
would be *very* bad indeed.

The PassManager does a lot of stuff, plz read the docs.

I have. Several times. The benefits claimed for PassManager are:

1. Share analysis results

This is basically tracking when analysis information goes out-of-date.

2. Pipeline the execution of passes on the program

This isn't really a PassManager benefit. Every single compiler I've
ever worked with does this.

Another benefit not explicitly listed is the running of prerequisites.
But again, we don't need anything as complicated as PassManager to do
that. The whole schedulePass, listener, command-line interactions
are extremely complex and esoteric.

Now, dynamically loaded passes do need some kind of registrar, but it
can be much simpler than the existing PassManager implementation.

I'm not disagreeing that we want an object to manage passes. But the
implementation strikes me as much too complex for what it actually does.
We definitely want a pass manager. I'm just not sure we need
PassManager.

                                  -Dave