Details
-
Type:
Bug
-
Status:
Open
-
Priority:
Major
-
Resolution: Unresolved
-
Affects Version/s: None
-
Fix Version/s: 3.2
-
Component/s: Compiler: Optimizing
-
Labels:None
-
Number of attachments :
Description
Having bigger basic blocks means more local optimization, merging basic blocks increases their size and exposes more opportunity for optimization. Every basic block has 2 pieces of exception information, the first are exceptional out edges taken by the block,t he second is a list of exception handler basic blocks that are "in scope" with this basic block. We currently don't merge basic blocks when their exception handler basic blocks differ, reducing the basic block size. For example,
int foo(int x) {
try
catch (Throwable t)
{ return 0; }}
int bar() {
return foo(10);
}
we would like bar to inline foo and the resultant code just directly return 11. However, the constant 10 is defined in a block in bar with no exception handler BBs and the use in foo has exception handler BBs, meaning we can never merge blocks and achieve simplification.
We need the exception handler basic blocks in the BB so that we can compute the exception maps, following assembly. The exception maps map an offset in the code to a handler address regardless of whether the block can throw the exception or not.
We could determine whether basic blocks have equivalent exceptions based on their exceptional out edges, as follows:
Index: rvm/src/org/jikesrvm/compilers/opt/ir/BasicBlock.java
===================================================================
— rvm/src/org/jikesrvm/compilers/opt/ir/BasicBlock.java (revision 14129)
+++ rvm/src/org/jikesrvm/compilers/opt/ir/BasicBlock.java (working copy)
@@ -404,8 +404,8 @@
// so just give up if they aren't equivalent.
if (exceptionHandlers != other.exceptionHandlers) {
// Even if not pointer ==, they still may be equivalent
- BasicBlockEnumeration e1 = getExceptionHandlers();
- BasicBlockEnumeration e2 = other.getExceptionHandlers();
+ BasicBlockEnumeration e1 = getExceptionalOut();
+ BasicBlockEnumeration e2 = other.getExceptionalOut();
while (e1.hasMoreElements()) {
if (!e2.hasMoreElements()) return false;
if (e1.next() != e2.next()) return false;
Assumption: an in scope exception handler BB should have an exceptional out edge to it.
I don't think that check is sufficient, because the assumption is wrong. The exceptional out edges are a sub-set of the inscope handlers, but not every inscope handler will have an exceptional outedge.
We don't prune the inscope handlers to just the reachable edges because that might limit our ability to combine blocks in the same try/catch region (one of those blocks might not have a PEI that reaches an inscope handler block, which a second block might and we want to be able to combine them later).
There are more complex tests one could use that would try to see if after merging the two sets of in scope handlers (not something we precisely support right now, but it might be implementable) that the exceptional out edges from each PEI in each block would still find the same exception handler. This is probably pretty hard to get right in the general case.
A simpler case would be to observe that if the exceptionalOuts of one of the blocks is empty, then it would be correct to combine the two blocks keeping the exception handlers of the other block.