problem loading analysis results from Inliner pass

Hi, I'm trying to access an analysis pass from the Inliner pass, and
I'm having a lot of trouble getting that to work - I can verify that
my pass is loaded and run (it is a dynamically loaded pass that is
part of an analysisgroup), however, when I access it using
getAnalysis<> from within Inliner::runOnSCC, I am instead getting the
default, dummy version of my analysis, which should be overridden by
the one that was brought in with -load.

I'm having a hard time debugging this, so any tips for how to track
the problem down would be appreciated.

I am running on Linux, and the version of LLVM I am working with is
from CVS a couple of months ago, so if this sounds like a problem
that's been solved already, it might be - that'd be good news.

This arrangement of analysis passes has worked in the past, and the
fact that my pass is loaded but not resolved correctly leads me to
believe it isn't a platform issue, but I'm open to any suggestions.

Thanks, and let me know if any more details would be helpful,
-mike

Hi, I'm trying to access an analysis pass from the Inliner pass, and
I'm having a lot of trouble getting that to work - I can verify that
my pass is loaded and run (it is a dynamically loaded pass that is
part of an analysisgroup), however, when I access it using
getAnalysis<> from within Inliner::runOnSCC, I am instead getting the
default, dummy version of my analysis, which should be overridden by
the one that was brought in with -load.

What sort of pass is it? The inliner is a ModulePass, so the only thing it can getAnalysis<> are modulepasses and immutablepasses: functionpasses won't work.

I'm having a hard time debugging this, so any tips for how to track
the problem down would be appreciated.

Try passing -debug-pass=Structure to opt.

I am running on Linux, and the version of LLVM I am working with is
from CVS a couple of months ago, so if this sounds like a problem
that's been solved already, it might be - that'd be good news.

It doesn't sound familiar.

This arrangement of analysis passes has worked in the past, and the
fact that my pass is loaded but not resolved correctly leads me to
believe it isn't a platform issue, but I'm open to any suggestions.

That's possible too, I don't really know. I would guess that it's a function pass which is getting killed before you pass runs. -debug-pass=Structure should help figure out if that's the case.

-Chris

> Hi, I'm trying to access an analysis pass from the Inliner pass, and
> I'm having a lot of trouble getting that to work - I can verify that
> my pass is loaded and run (it is a dynamically loaded pass that is
> part of an analysisgroup), however, when I access it using
> getAnalysis<> from within Inliner::runOnSCC, I am instead getting the
> default, dummy version of my analysis, which should be overridden by
> the one that was brought in with -load.

What sort of pass is it? The inliner is a ModulePass, so the only thing
it can getAnalysis<> are modulepasses and immutablepasses: functionpasses
won't work.

My pass is a ModulePass, although it's actually just an interface to
external data, so I suppose it could potentially be an ImmutablePass.
I've been meaning to revisit that, but it wasn't a high priority as
long as it was working.

...snip...

> This arrangement of analysis passes has worked in the past, and the
> fact that my pass is loaded but not resolved correctly leads me to
> believe it isn't a platform issue, but I'm open to any suggestions.

That's possible too, I don't really know. I would guess that it's a
function pass which is getting killed before you pass runs.
-debug-pass=Structure should help figure out if that's the case.

using -debug-pass=Structure does show me that my pass is loaded and
killed immediately. Here's a sample. "Dummy PMF Interface" is the noop
default implementation of the "PMFAnalysis" analysis group, while "PMF
File Loader" is the real implementation that I'm interested in.

Pass Arguments: -pmf-load -raiseallocs -simplifycfg -mem2reg
-globalopt -globaldce -ipconstprop -deadargelim -instcombine
-simplifycfg -prune-eh -inline -argpromotion -raise -tailduplicate
-simplifycfg -scalarrepl -instcombine -break-crit-edges -condprop
-tailcallelim -simplifycfg -reassociate -loopsimplify -licm
-instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp
-instcombine -break-crit-edges -condprop -dse -mergereturn -adce
-simplifycfg -deadtypeelim -constmerge -verify
Target Data Layout
Dummy PMF Interface
Basic Alias Analysis (default AA impl)
Basic Value Numbering (default GVN impl)
Module Pass Manager
  PMF File Loader
--PMF File Loader
  Raise allocations from calls to instructions
--Raise allocations from calls to instructions
  Function Pass Manager
    Simplify the CFG
-- Simplify the CFG
    Immediate Dominators Construction
    Dominator Tree Construction
-- Immediate Dominators Construction
    Dominance Frontier Construction
    Promote Memory to Register
-- Dominance Frontier Construction
-- Dominator Tree Construction
-- Promote Memory to Register
  Global Variable Optimizer
--Global Variable Optimizer
  Dead Global Elimination
--Dead Global Elimination
  Interprocedural constant propagation
--Interprocedural constant propagation
  Dead Argument Elimination
--Dead Argument Elimination
  Function Pass Manager
    Combine redundant instructions
-- Combine redundant instructions
    Simplify the CFG
-- Simplify the CFG
  Call Graph Construction
  Remove unused exception handling info
--Remove unused exception handling info
  Function Integration/Inlining
--Function Integration/Inlining
  Promote 'by reference' arguments to scalars
--Promote 'by reference' arguments to scalars
--Call Graph Construction
  Function Pass Manager
... continues...

That's on my linux box - on darwin, a similar (but not exactly the
same) set of passes yields the expected result, where PMF File Loader
is alive for the whole sequence.

I had just written a more detailed version of this email when I
realized that the dummy pass and the real pass were not the exact same
type - the dummy was an ImmutablePass and the real pass was a
ModulePass. On changing the real pass to an ImmutablePass, I get the
behavior I expected. A quick scan of the docs doesn't say anything
about the members of a group needing to be the same kind of pass - is
that really the case? It does make sense, but maybe there ought to be
a way to catch this automatically, at least in debug builds?
Admittedly, it seems like a pretty unlikely problem, but it was
confusing.

I'll also try to replicate the exact same conditions on darwin to see
if the platform makes a difference, since I didn't run into this
problem until moving to linux.

Thanks,
-mike

A

>
> > Hi, I'm trying to access an analysis pass from the Inliner pass, and
> > I'm having a lot of trouble getting that to work - I can verify that
> > my pass is loaded and run (it is a dynamically loaded pass that is
> > part of an analysisgroup), however, when I access it using
> > getAnalysis<> from within Inliner::runOnSCC, I am instead getting the
> > default, dummy version of my analysis, which should be overridden by
> > the one that was brought in with -load.
>
> What sort of pass is it? The inliner is a ModulePass, so the only thing
> it can getAnalysis<> are modulepasses and immutablepasses: functionpasses
> won't work.

My pass is a ModulePass, although it's actually just an interface to
external data, so I suppose it could potentially be an ImmutablePass.
I've been meaning to revisit that, but it wasn't a high priority as
long as it was working.

...snip...
>
> > This arrangement of analysis passes has worked in the past, and the
> > fact that my pass is loaded but not resolved correctly leads me to
> > believe it isn't a platform issue, but I'm open to any suggestions.
>
> That's possible too, I don't really know. I would guess that it's a
> function pass which is getting killed before you pass runs.
> -debug-pass=Structure should help figure out if that's the case.

using -debug-pass=Structure does show me that my pass is loaded and
killed immediately. Here's a sample. "Dummy PMF Interface" is the noop
default implementation of the "PMFAnalysis" analysis group, while "PMF
File Loader" is the real implementation that I'm interested in.

Pass Arguments: -pmf-load -raiseallocs -simplifycfg -mem2reg
-globalopt -globaldce -ipconstprop -deadargelim -instcombine
-simplifycfg -prune-eh -inline -argpromotion -raise -tailduplicate
-simplifycfg -scalarrepl -instcombine -break-crit-edges -condprop
-tailcallelim -simplifycfg -reassociate -loopsimplify -licm
-instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp
-instcombine -break-crit-edges -condprop -dse -mergereturn -adce
-simplifycfg -deadtypeelim -constmerge -verify
Target Data Layout
Dummy PMF Interface
Basic Alias Analysis (default AA impl)
Basic Value Numbering (default GVN impl)
Module Pass Manager
  PMF File Loader
--PMF File Loader
  Raise allocations from calls to instructions
--Raise allocations from calls to instructions
  Function Pass Manager
    Simplify the CFG
-- Simplify the CFG
    Immediate Dominators Construction
    Dominator Tree Construction
-- Immediate Dominators Construction
    Dominance Frontier Construction
    Promote Memory to Register
-- Dominance Frontier Construction
-- Dominator Tree Construction
-- Promote Memory to Register
  Global Variable Optimizer
--Global Variable Optimizer
  Dead Global Elimination
--Dead Global Elimination
  Interprocedural constant propagation
--Interprocedural constant propagation
  Dead Argument Elimination
--Dead Argument Elimination
  Function Pass Manager
    Combine redundant instructions
-- Combine redundant instructions
    Simplify the CFG
-- Simplify the CFG
  Call Graph Construction
  Remove unused exception handling info
--Remove unused exception handling info
  Function Integration/Inlining
--Function Integration/Inlining
  Promote 'by reference' arguments to scalars
--Promote 'by reference' arguments to scalars
--Call Graph Construction
  Function Pass Manager
... continues...

That's on my linux box - on darwin, a similar (but not exactly the
same) set of passes yields the expected result, where PMF File Loader
is alive for the whole sequence.

I had just written a more detailed version of this email when I
realized that the dummy pass and the real pass were not the exact same
type - the dummy was an ImmutablePass and the real pass was a
ModulePass. On changing the real pass to an ImmutablePass, I get the
behavior I expected.

Just some more information:

After a more thorough test, that isn't quite the case - since the
ImmutablePass is never 'run', my code needs modification to work.
However, I thought that maybe I could just make them both ModulePasses
instead, but that produces the following runtime error:

opt: /home/mmccrack/lens/obj-llvm-darcslocal/../llvm-darcslocal/llvm/lib/VMCore/PassManagerT.h:426:
void llvm::PassManagerT<UnitType>::markPassUsed(const llvm::PassInfo*,
llvm::Pass*) [with UnitType = llvm::Module]: Assertion
`getAnalysisOrNullUp(P) &&
dynamic_cast<ImmutablePass*>(getAnalysisOrNullUp(P)) && "Pass
available but not found! " "Perhaps this is a module pass requiring a
function pass?"' failed.

Which is also unexpected. I think for now I will attempt to make my
pass work as Immutable, but I'm still curious why having both be a
ModulePass gets this error, where both as an ImmutablePass is OK for
the PassManager and one of each is also OK. Strange, but maybe I'm
missing something.

-mike

My pass is a ModulePass, although it's actually just an interface to
external data, so I suppose it could potentially be an ImmutablePass.
I've been meaning to revisit that, but it wasn't a high priority as
long as it was working.

ok

Module Pass Manager
PMF File Loader
--PMF File Loader
Raise allocations from calls to instructions
--Raise allocations from calls to instructions

...

ModulePass. On changing the real pass to an ImmutablePass, I get the
behavior I expected. A quick scan of the docs doesn't say anything
about the members of a group needing to be the same kind of pass - is
that really the case? It does make sense, but maybe there ought to be
a way to catch this automatically, at least in debug builds?
Admittedly, it seems like a pretty unlikely problem, but it was
confusing.

By default, all passes invalidate all other passes of their type or more granular. In this case, what's going on is that all of the module passes are implicitly invalidating the results of "PMF File Loader". Marking it immutable will do what you want (nothing will ever invalidate it because it's immutable) but make sure this really is what you want :slight_smile:

I'll also try to replicate the exact same conditions on darwin to see
if the platform makes a difference, since I didn't run into this
problem until moving to linux.

If it did, that would be a SERIOUS bug.

-Chris

It is hard for me to say without more information. Make sure you don't have an immutable pass requiring a modulepass or something like that.

-Chris

By default, all passes invalidate all other passes of their type or more
granular. In this case, what's going on is that all of the module passes
are implicitly invalidating the results of "PMF File Loader". Marking it
immutable will do what you want (nothing will ever invalidate it because
it's immutable) but make sure this really is what you want :slight_smile:

> I'll also try to replicate the exact same conditions on darwin to see
> if the platform makes a difference, since I didn't run into this
> problem until moving to linux.

If it did, that would be a SERIOUS bug.

OK, it does the same things on darwin, so it's not platform related.

> opt: /home/mmccrack/lens/obj-llvm-darcslocal/../llvm-darcslocal/llvm/lib/VMCore/PassManagerT.h:426:
> void llvm::PassManagerT<UnitType>::markPassUsed(const llvm::PassInfo*,
> llvm::Pass*) [with UnitType = llvm::Module]: Assertion
> `getAnalysisOrNullUp(P) &&
> dynamic_cast<ImmutablePass*>(getAnalysisOrNullUp(P)) && "Pass
> available but not found! " "Perhaps this is a module pass requiring a
> function pass?"' failed.
>
> Which is also unexpected. I think for now I will attempt to make my
> pass work as Immutable, but I'm still curious why having both be a
> ModulePass gets this error, where both as an ImmutablePass is OK for
> the PassManager and one of each is also OK. Strange, but maybe I'm
> missing something.

It is hard for me to say without more information. Make sure you don't
have an immutable pass requiring a modulepass or something like that.

-Chris

OK, I think I can summarize the situation better now:

What I have is an analysisgroup with one immutable pass member and one
module pass member - admittedly, this is nonsensical, so I'll be
making them both immutable, but this is to satisfy my curiousity, and
I think there might still be something sketchy going on here. Neither
of those analyses required any other passes.

When I had the heterogeneous analysis group, but only function passes
were requiring the group, everything worked as expected - the real
pass, a module pass could get loaded and be used instead of the dummy
pass, not invalidated early, and no crashes.

When I made the change of having an CallGraphSCCPass (the inliner)
require my analysis group, that's when I noticed the problems. With
that change, the modulepass member of the analysis group would be
invalidated immediately (I'm still not sure why this happens as a
result of what is requiring the pass), and the pass that required it
would get a bad pointer out of getAnalysis.

When I change both members of the analysis group to module passes,
that's when I get the assertion failure "Pass available but not found"
/ "perhaps this is a modulepass requiring a functionpass?", although
the only changes I made is to add one edge from a CallgraphSCCPass to
an AnalysisGroup, both members of which are now ModulePasses.

note: the assertion failure happens while building LLVM, in the
bytecode-library compilation phase, so it is happening when my 'real'
pass is not loaded.

So, having a heterogeneous AnalysisGroup is probably always wrong, and
I guess we might want to check for it at registration time. However, I
don't see what is wrong with having a CallgraphSCCPass require an
analysis group with one ModulePass. That doesn't seem to be a case of
a higher-granularity pass requiring a lower-granularity pass, but is
it a similar limitation of the current Pass Manager?

Thanks,
-mike