I’m wondering if the documentation for LoopPass (http://llvm.org/docs/WritingAnLLVMPass.html#LoopPass) is misleading or incorrect (or if I’m just missing something.) The documentation states:
“The doFinalization
method … is called when the pass framework has finished calling runOnLoop
for every loop in the program being compiled.”
From this, I understood that for a single instance of a LoopPass sub-class, the doFinalization method would be called exactly once, after all loops had been seen. However in practice I am seeing doFinalization() being called multiple times per program. Digging into the code, it appears that LPPassManager actually makes the calls to doFinalization() at the end of it’s runOnFunction() method (http://llvm.org/docs/doxygen/html/LoopPass_8cpp_source.html#l00281, at time of writing). This therefore means that doFinalization() can be called multiple times per LoopPass; as many as there are functions defined in the input file.
Assuming I have made no mistakes here, is this a case of poorly written documentation, or an error in the implementation? I note that FPPassManager does it calls to FunctionPass’ doFinalization() in it’s own doFinalization() method, which seems the correct behaviour to me.
Thanks,
Stephen
Hi Stephen,
I'm wondering if the documentation for LoopPass
(Writing an LLVM Pass — LLVM 18.0.0git documentation) is misleading or
incorrect (or if I'm just missing something.) The documentation states:
"The doFinalization method ... is called when the pass framework has finished
calling runOnLoop <Writing an LLVM Pass — LLVM 18.0.0git documentation; for
every loop in the program being compiled."
From this, I understood that for a single instance of a LoopPass sub-class, the
doFinalization method would be called exactly once, after all loops had been
seen. However in practice I am seeing doFinalization() being called multiple
times per program. Digging into the code, it appears that LPPassManager actually
makes the calls to doFinalization() at the end of it's runOnFunction() method
(LLVM: lib/Analysis/LoopPass.cpp Source File, at time of
writing). This therefore means that doFinalization() can be called multiple
times per LoopPass; as many as there are functions defined in the input file.
my understanding is that this is the expected behaviour and the documentation
should be improved (want to propose a patch?).
Ciao, Duncan.
Hi Stephen,
I'm wondering if the documentation for LoopPass
(http://llvm.org/docs/**WritingAnLLVMPass.html#**LoopPass<http://llvm.org/docs/WritingAnLLVMPass.html#LoopPass>\)
is misleading or
incorrect (or if I'm just missing something.) The documentation states:
"The doFinalization method ... is called when the pass framework has
finished
calling runOnLoop <http://llvm.org/docs/**WritingAnLLVMPass.html#**
runOnLoop <Writing an LLVM Pass — LLVM 18.0.0git documentation; for
every loop in the program being compiled."
From this, I understood that for a single instance of a LoopPass
sub-class, the
doFinalization method would be called exactly once, after all loops had
been
seen. However in practice I am seeing doFinalization() being called
multiple
times per program. Digging into the code, it appears that LPPassManager
actually
makes the calls to doFinalization() at the end of it's runOnFunction()
method
(http://llvm.org/docs/doxygen/**html/LoopPass_8cpp_source.**html#l00281<http://llvm.org/docs/doxygen/html/LoopPass_8cpp_source.html#l00281>,
at time of
writing). This therefore means that doFinalization() can be called
multiple
times per LoopPass; as many as there are functions defined in the input
file.
my understanding is that this is the expected behaviour and the
documentation
should be improved (want to propose a patch?).
I'm actually really hoping to change this behavior in the not-too-distant
future.
The goal that I and several others have worked out is that for *all*
passes, the doInitialization and doFinalization are called once per module.
All of the doInitialization methods should be called before the first
pass's runOn*** method is called, and all of the doFinalization calls
should be after the last pass's runOn*** have finished.
The goal of the initialization and finalization methods is to allow
per-module caching, uniquing, setup, and teardown.
I know that we are quite far from this goal in practice sadly, but I think
the goal remains the same.
Hi Chandler,
Hi Stephen,
I'm wondering if the documentation for LoopPass
(http://llvm.org/docs/__WritingAnLLVMPass.html#__LoopPass
<Writing an LLVM Pass — LLVM 18.0.0git documentation) is misleading or
incorrect (or if I'm just missing something.) The documentation states:
"The doFinalization method ... is called when the pass framework has
finished
calling runOnLoop
<http://llvm.org/docs/__WritingAnLLVMPass.html#__runOnLoop
<Writing an LLVM Pass — LLVM 18.0.0git documentation; for
every loop in the program being compiled."
From this, I understood that for a single instance of a LoopPass
sub-class, the
doFinalization method would be called exactly once, after all loops had been
seen. However in practice I am seeing doFinalization() being called multiple
times per program. Digging into the code, it appears that LPPassManager
actually
makes the calls to doFinalization() at the end of it's runOnFunction()
method
(http://llvm.org/docs/doxygen/__html/LoopPass_8cpp_source.__html#l00281
<LLVM: lib/Analysis/LoopPass.cpp Source File, at
time of
writing). This therefore means that doFinalization() can be called multiple
times per LoopPass; as many as there are functions defined in the input
file.
my understanding is that this is the expected behaviour and the documentation
should be improved (want to propose a patch?).
I'm actually really hoping to change this behavior in the not-too-distant future.
The goal that I and several others have worked out is that for *all* passes, the
doInitialization and doFinalization are called once per module. All of the
doInitialization methods should be called before the first pass's runOn***
method is called, and all of the doFinalization calls should be after the last
pass's runOn*** have finished.
would it still be possible to optimize and codegen functions as they are output
(rather than waiting for the module to be completely output before doing this)?
Ciao, Duncan.
I would assume so... What gives you pause here?
(TBH, I've not really thought about this deeply, so I may be missing
something obvious...)
I see. In the meantime, is there a suggested method to do actual finalization code (i.e. code that runs after all of the loops have been processed)?
Thanks,
Stephen