Branch removal
Patrick Metzler
Patrick.Metzler at gmx.net
Wed Sep 19 01:42:40 PDT 2012
Hi,
my plan is to write an additional pass/transformation for the server
compiler; now I have some problems implementing it. The transformation
should delete certain branchings and make use of the conditional move
instruction on Intel platforms, hence do /some sort of/ branch
predication. To be clear: it is not intended to make the code faster or
smaller; I just want to see whether it is possible to compile branching
in Java byte code into native code without branching (in the context of
my computer science thesis).
For example, I want the if/else statement in the following Java method:
Object m( Object o1, Object o2, int n) {
Object r;
if (n == 0)
r = o1;
else
r = o2;
return r;
}
be compiled into native code like this:
... method entry ...
testl RCX, RCX
cmovz RBX, RAX
... method exit ...
assuming that EAX, EBX and ECX hold parameters o1, o2 and n,
respectively, and that the value of EAX is returned.
It is fine for me if the emitted code contains branchings as long as
they do not correspond to the if/else statement. (I expect that it
would be infeasible avoiding any branching anyway, due to, e.g.,
exceptions during allocation.) It is also fine for me to restrict the
Java programs the transformation would support; e.g., the transformation
could only consider if statements containing no method calls, if
statements with empty else branches, ...
Of course, the transformation should not be applied globally, but only
on certain branchings. I plan to mark them using Java annotations,
possibly indicating the bytecode index, although I don't know whether
this is easy to evaluate inside the compiler.
So far, I've tried out two things: First, I borrowed some code from
PhaseIdealLoop::conditional_move in order to replace a Region node and
corresponding If / projection nodes with CMov nodes. I inserted the
transformation at the end of Compile::Optimize(). This works fine for a
simple method, but gives me an error for a method using objects:
COMPILE SKIPPED: late schedule failed: incorrect graph (not retryable)
Second, I considered an example containing an if statement with an empty
else statement inside a loop. Here is a sketch of the Java source code:
MyObject a, aSwap;
// ... code left out here ...
for (E e : arrayList) {
aSwap = a.getCopy();
aSwap.do();
if (e.condition())
a = aSwap;
}
After high level optimizations, the else branch (which I expected to be
empty) contained some basic blocks, so I changed the transformation such
that it deletes the If node and the else branch, but not necessarily
deletes the corresponding Region node (as it turned out to be the Loop
node). But I was not able to remove the else branch correctly and it
gave me (I think because of CreateEx node I didn't remove):
COMPILE SKIPPED: infinite loop (not retryable)
I still need to figure out how to find the Phi nodes referenced in the
if branch I now want to execute always, in order to replace them by CMov
nodes.
My questions are:
* How can I assure my transformation leaves a consistent graph?
I found PhaseIdealLoop::verify(), is this appropriate?
* Is there already functionality implemented which removes code
unreachable from above but reachable from below?
* Is it possible to associate a Phi node with a specific Bool node, in
cases where a Region node has multiple If nodes as predecessors?
* Would you suggest to place the transformation not at the end of high
level optimizations but elsewhere, e.g. before optimizations?
* Are Java annotations parsed by C2? If so, how to access them?
* Is it possible to disable uncommon traps (completely or just for one
method)?
I would be glad if someone had some time to consider my questions.
Patrick
More information about the hotspot-compiler-dev
mailing list