[Mono-dev] CIL to CIL optimizer
Bjarke Hammersholt Roune
bjarke.roune at gmail.com
Thu Aug 10 08:40:36 EDT 2006
Zoltan Varga skrev:
> Hi,
>
> What is the problem with try-finally ? There are two cases:
> - if there is an exception, the runtime will call it, just with the
catch clause
> - if there is no exception, control flow just falls from the end of
> the try block to
> the beginning of the finally block. This is just a normal control
flow edge.
>
The problem is that what happens after the finally block is done depends
on the context that caused it to run. Here is a simple example in pseudo
code:
try {
if (a) {
A: x = 2;
goto E;
}
B: x = 1;
} finally {
C: print "hello world!";
}
D: print x;
E: return
Imagine a control flow graph of this code with the labels naming the
nodes. Then there will be edges A->C, B->C, C->D, C->E and D->E. The
definition of x that reaches D will thus have to go through C, and then
C will need a phi-function to get the correct definition of x. This will
make it look like the definition of x from A is needed at C, even though
obviously it is not. The basic problem is that the control flow graph
makes it look like the path A->C->D is possible. In this example this
means that we cannot discover that x=2 is dead code.
Suppose that the x=2 at A was something throwing an exception instead
and we had a catch handler on the innermost try. Then C would need an
outgoing edge to this handler, making it look like falling through at B
could cause an exception!
So if we don't do something special for finally, we can get preposterous
information. I should perhaps say that I am interested in precise
analysis to do good optimization, but also because I would like the
program to have capabilities similar to the Java findbugs program,
though that would not be a priority at first.
I am sure this CAN be fixed for each analysis by doing the equivalent of
path sensitive analysis but restricting it to finally. Basically this
will be the same thing as making the analysis act as if the finally
block was inlined everywhere it could be called, but without actually
inlining it. I am not sure how that should interact with SSA-form.
Even if we use the naive approach the control flow graph will need to
know that removing an edge TO a finally block might or might not
necessitate removing an edge FROM it, depending on whether or not a
different branch from inside the corresponding try block has another
branch that needs to go the same outer destination. If that does not
make sense consider removing the last branch to a label outside a
finally-protected try block as compared to removing one of several
branches that all go to the same label outside the try block.
I expect to discover more of these kinds of differences from normal
control flow graph behavior as implementation proceeds, since finally
directs control flow in a different way from anything else.
I hope I have convincingly argued that finally needs special treatment
and that that treatment is non-trivial if we need reasonably precise
analysis of program behavior.
/Bjarke
More information about the Mono-devel-list
mailing list