[LLVMdev] (Possibly buggy?) doFinalization method behavior of FunctionPass

Cristianno Martins cristiannomartins at gmail.com
Wed May 6 09:11:17 PDT 2015


Hello again,

First of all, thanks for all the answers =) they really helped a lot =D

*Have you verified that some other pass is not adding the function
declarations back in after your pass is executed (e.g., by using the
-debug-pass=Executions argument to see what passes run after your pass)?*

I considered that for a moment, but I realized that wouldn't be possible
for two reasons: I specifically ran my pass with opt level zero; and one of
the tasks I was doing was removing unused prototypes from the Module -- so,
why would any other doFinalization pass reintroduce those prototypes if
those functions were not being invoked anywhere? (PS: since this clean-up
happened inside my doFinalization, I'm assuming only other doFinalization
would be able to change the module after this point)


*Also, does your doFinalization() method make other changes that are
persistent?*


The main reason why I chose to use doFinalization was to check if any of
the functions I'm replacing still had any uses: since my pass replaced
every function call with my respective function calls, if any uses could
still be listed, that meant that some instruction must be taking the
address of that function, and I should treat those instructions at this
point. At the end, since I was already checking for uses, I ended up
removing the extra prototypes at this point, if they were still there.

I don’t think doFinalization() is really meant to be used this way.

Its purpose is to allow clean-up of internal data-structures used by the
pass itself, not to make additional changes to the module.


Then, I have a question: why should doFinalization need a Module& as
argument? I mean, since I shouldn't be able to modify it, and all data
structures I created to work my pass are known and (mostly) directly
accessible from within doFinalization, its argument would never be useful,
right?

One option would be to rewrite your pass as a ModulePass instead of a
FunctionPass, then iterating over the functions manually, and doing the
final clean-up once that’s done.

*That said, I agree with the suggestion of writing a ModulePass.  Since the
PassManager does not run FunctionPasses in parallel yet, there's little
benefit to using them.  I have often found the limitations on
FunctionPasses to not be worth the hassle.*

Well, I actually wouldn't mind using a ModulePass to begin with, but
unfortunately I had to rewrite my pass as a FunctionPass because part of
the job it does involve accessing the DominatorTree -- and, unfortunately,
I couldn't find a way to access it from inside a ModulePass. Even when I
try to force a dependence between my module pass and DominatorTree, I can't
get it to work because (if I'm not mistaken) module passes are hard-coded
to run before function passes =/

*My understanding is that doInitialization() and doFinalization() are
designed specifically for modifying the LLVM IR (otherwise, why would a
mutable reference to the Function be provided)?*


*If that is not the case, then there is either a bug in the code or a bug
in the documentation.*

Exactly like I thought =)


I’ve always thought that the only guarantee is that doFinalization(Module
&M) runs after runOnFunction() was executed for all functions in M, and
there’s no guarantee it runs *immediately* after.

That is, a PM may run a bunch of function passes over each function, and
only then call doFinazliation() for each pass. That means that, even though
you get a mutable reference to the module, the module you’ll see is quite
different from what you may expect.



People more familiar with the pass managers – please correct me if I’m
wrong.


I don't really mind at all if other passes run or even had their
doFinalization passes running in any order in relation to mine: the point
here is doFinalization is running (I know that because module.dump() is
being called from inside that function, and I can see the module containing
the modifications I do during the execution of that method), but the final
bc file (written by opt) does have the exactly same code that I get if I
dumped module at the beginning of my doFinalization (and they have
differences between them btw =)).




--
Cristianno Martins
PhD Student of Computer Science
University of Campinas
cmartins at ic.unicamp.br
<cristiannomartins at hotmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150506/2cb31db5/attachment.html>


More information about the llvm-dev mailing list