Pass vs. FunctionPass

I wonder in what cases FunctionPass is better that Pass. For example,
addPassesToEmitAssembly takes PassManger and addPassesToJITCompile takes
FunctionPassManager.

Another question is about FunctionPassManager::run(Function&) and
FunctionPass(Function&). The former calls the later, which is fine, but the
latter looks like this:

bool FunctionPass::run(Function &F) {
  if (F.isExternal()) return false;// Passes are not run on external
functions!

  return doInitialization(*F.getParent()) | runOnFunction(F)
       > doFinalization(*F.getParent());
}

So, with FunctionPassManager, doInitializaton will be called once for each
function, which is strange, given that that method takes Module&. When this
behaviour is desirable?

- Volodya

I wonder in what cases FunctionPass is better that Pass. For example,
addPassesToEmitAssembly takes PassManger and addPassesToJITCompile takes
FunctionPassManager.

It's just better from a software engineering perspective to use FunctionPass
if you are doing things on the global (function) level rather than the
module level. Also it allows passes to be scheduled in order on functions
rather than whole modules.

Another question is about FunctionPassManager::run(Function&) and
FunctionPass(Function&). The former calls the later, which is fine, but

the

latter looks like this:

bool FunctionPass::run(Function &F) {
  if (F.isExternal()) return false;// Passes are not run on external
functions!

  return doInitialization(*F.getParent()) | runOnFunction(F)
       > doFinalization(*F.getParent());
}

So, with FunctionPassManager, doInitializaton will be called once for each
function, which is strange, given that that method takes Module&. When

this

behaviour is desirable?

I never looked at this code before. That explains why I've had issues with
doFinalization before, because I always assumed it only ran once per module
myself. It seems undesirable to me because not only is this a little
counter intuitive, but it also repeats work that need only be done once.
But maybe there is a good reason for this?

I wonder in what cases FunctionPass is better that Pass. For example,
addPassesToEmitAssembly takes PassManger and addPassesToJITCompile takes
FunctionPassManager.

Here's a simple way to look at it. Use a Function pass whenever you can.
A function pass will always work where a Pass works (it derives from pass
as you've noticed), but not the other way around.

In particular, there are *strict* rules that must be followed by
FunctionPass's, described in the HowToWriteAPass document. Like Patrick
mentioned, these allow the pass manager to optimize the execution of
passes on a module, and eventually will allow us to compile functions in
parallel on different threads at the same time.

Another question is about FunctionPassManager::run(Function&) and
FunctionPass(Function&). The former calls the later, which is fine, but the
latter looks like this:

bool FunctionPass::run(Function &F) {
  if (F.isExternal()) return false;// Passes are not run on external
functions!

  return doInitialization(*F.getParent()) | runOnFunction(F)
       > doFinalization(*F.getParent());
}

So, with FunctionPassManager, doInitializaton will be called once for
each function, which is strange, given that that method takes Module&.
When this behaviour is desirable?

That *is* odd, I've never noticed that code before. I think that the
FunctionPassManager is only used by the JIT. For normal optimization and
static compiles, you will get a doInitialization once at the beginning of
the module, a whole bunch of runOnFunctions, and a doFinalization call at
the end (as you would expect).

I'm not sure what the right semantics are in the JIT using the
functionpassmanager. In any case your code should work correctly (because
it is a function pass) it's a performance thing. What do you need to do
in your doInit/finalize calls for codegeneration?

-Chris

> I wonder in what cases FunctionPass is better that Pass. For example,
> addPassesToEmitAssembly takes PassManger and addPassesToJITCompile takes
> FunctionPassManager.

Here's a simple way to look at it. Use a Function pass whenever you can.
A function pass will always work where a Pass works (it derives from pass
as you've noticed), but not the other way around.

In particular, there are *strict* rules that must be followed by
FunctionPass's, described in the HowToWriteAPass document. Like Patrick
mentioned, these allow the pass manager to optimize the execution of
passes on a module, and eventually will allow us to compile functions in
parallel on different threads at the same time.

One thing I was just thinking is that at some future date one may be able to
specify which functions to run specific function passes on (leaving off
costly optimizations on functions you know it will have little effect on and
some such, especially optimizations that require heavy analysis). This
would be especially useful in some kind of system that runs a bunch of
passes and tests the output for speed (in large numbers, guided by some kind
of search algorithm, though it would greatly increase the size of the search
space).

> Another question is about FunctionPassManager::run(Function&) and
> FunctionPass(Function&). The former calls the later, which is fine, but

the