changeset 19365:bef4a591e0b3

Avoid creating the begin block for single predecessor returns when inlining during graph building.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Fri, 13 Feb 2015 22:03:34 +0100
parents 2d6a2f18fe8c
children 4acfeb8a0010
files graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java
diffstat 2 files changed, 58 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Fri Feb 13 21:32:50 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java	Fri Feb 13 22:03:34 2015 +0100
@@ -84,6 +84,7 @@
         public int loopId;
         public int loopEnd;
         protected List<BciBlock> successors;
+        private int predecessorCount;
 
         private FixedWithNextNode firstInstruction;
         private AbstractFrameStateBuilder<?, ?> entryState;
@@ -127,6 +128,10 @@
             return id;
         }
 
+        public int getPredecessorCount() {
+            return this.predecessorCount;
+        }
+
         public int numNormalSuccessors() {
             if (exceptionDispatchBlock() != null) {
                 return successors.size() - 1;
@@ -391,6 +396,18 @@
         public void setId(int i) {
             this.id = i;
         }
+
+        public void addSuccessor(BciBlock sux) {
+            successors.add(sux);
+            sux.predecessorCount++;
+        }
+
+        public void clearSucccessors() {
+            for (BciBlock sux : successors) {
+                sux.predecessorCount--;
+            }
+            successors.clear();
+        }
     }
 
     public static class ExceptionDispatchBlock extends BciBlock {
@@ -421,6 +438,7 @@
     public LocalLiveness liveness;
     private int blocksNotYetAssignedId;
     private final boolean consecutiveLoopBlocks;
+    public int returnCount;
 
     /**
      * Creates a new BlockMap instance from bytecode of the given method .
@@ -441,6 +459,10 @@
         return this.blocks;
     }
 
+    public int getReturnCount() {
+        return this.returnCount;
+    }
+
     /**
      * Builds the block map and conservative CFG and numbers blocks.
      */
@@ -527,6 +549,7 @@
                 case DRETURN: // fall through
                 case ARETURN: // fall through
                 case RETURN: {
+                    returnCount++;
                     current = null;
                     break;
                 }
@@ -653,11 +676,13 @@
             blocksNotYetAssignedId++;
             newBlock.startBci = startBci;
             newBlock.endBci = oldBlock.endBci;
-            newBlock.getSuccessors().addAll(oldBlock.getSuccessors());
+            for (BciBlock oldSuccessor : oldBlock.getSuccessors()) {
+                newBlock.addSuccessor(oldSuccessor);
+            }
 
             oldBlock.endBci = startBci - 1;
-            oldBlock.getSuccessors().clear();
-            oldBlock.getSuccessors().add(newBlock);
+            oldBlock.clearSucccessors();
+            oldBlock.addSuccessor(newBlock);
 
             for (int i = startBci; i <= newBlock.endBci; i++) {
                 blockMap[i] = newBlock;
@@ -686,7 +711,7 @@
         if (sux.isExceptionEntry) {
             throw new BailoutException("Exception handler can be reached by both normal and exceptional control flow");
         }
-        predecessor.getSuccessors().add(sux);
+        predecessor.addSuccessor(sux);
     }
 
     private final ArrayList<BciBlock> jsrVisited = new ArrayList<>();
@@ -697,7 +722,7 @@
 
         if (block.endsWithRet()) {
             block.setRetSuccessor(blockMap[scope.nextReturnAddress()]);
-            block.getSuccessors().add(block.getRetSuccessor());
+            block.addSuccessor(block.getRetSuccessor());
             assert block.getRetSuccessor() != block.getJsrSuccessor();
         }
         Debug.log("JSR alternatives block %s  sux %s  jsrSux %s  retSux %s  jsrScope %s", block, block.getSuccessors(), block.getJsrSuccessor(), block.getRetSuccessor(), block.getJsrScope());
@@ -766,9 +791,9 @@
                     curHandler.endBci = -1;
                     curHandler.deoptBci = bci;
                     curHandler.handler = h;
-                    curHandler.getSuccessors().add(blockMap[h.getHandlerBCI()]);
+                    curHandler.addSuccessor(blockMap[h.getHandlerBCI()]);
                     if (lastHandler != null) {
-                        curHandler.getSuccessors().add(lastHandler);
+                        curHandler.addSuccessor(lastHandler);
                     }
                     exceptionDispatch.put(h, curHandler);
                 }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Feb 13 21:32:50 2015 +0100
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java	Fri Feb 13 22:03:34 2015 +0100
@@ -204,6 +204,7 @@
             private final boolean explodeLoops;
             private Stack<ExplodedLoopContext> explodeLoopsContext;
             private int nextPeelIteration = 1;
+            private int returnCount;
 
             public BytecodeParser(MetaAccessProvider metaAccess, ResolvedJavaMethod method, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, int entryBCI) {
                 super(metaAccess, method, graphBuilderConfig, optimisticOpts);
@@ -251,6 +252,7 @@
                     BciBlockMapping blockMap = BciBlockMapping.create(method, graphBuilderConfig.doLivenessAnalysis(), explodeLoops);
                     loopHeaders = blockMap.getLoopHeaders();
                     liveness = blockMap.liveness;
+                    returnCount = blockMap.getReturnCount();
 
                     lastInstr = startInstruction;
                     this.setCurrentFrameState(startFrameState);
@@ -628,7 +630,7 @@
 
             @Override
             protected void genGoto() {
-                appendGoto(createTarget(currentBlock.getSuccessors().get(0), frameState));
+                appendGoto(createTarget(currentBlock.getSuccessor(0), frameState));
                 assert currentBlock.numNormalSuccessors() == 1;
             }
 
@@ -1003,10 +1005,18 @@
                     beforeReturn(x);
                     append(new ReturnNode(x));
                 } else {
-                    if (x != null) {
-                        frameState.push(x.getKind(), x);
+                    if (returnCount == 1) {
+                        // There is only a single return.
+                        this.returnValue = x;
+                        this.beforeReturnNode = this.lastInstr;
+                        this.lastInstr = null;
+                    } else {
+                        if (x != null) {
+                            frameState.push(x.getKind(), x);
+                        }
+                        assert returnCount > 1;
+                        appendGoto(createTarget(returnBlock(bci()), frameState));
                     }
-                    appendGoto(createTarget(returnBlock(bci()), frameState));
                 }
             }
 
@@ -1213,6 +1223,10 @@
             }
 
             private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state) {
+                return createTarget(block, state, false);
+            }
+
+            private FixedNode createTarget(BciBlock block, HIRFrameStateBuilder state, boolean isGoto) {
                 assert block != null && state != null;
                 assert !block.isExceptionEntry || state.stackSize() == 1;
 
@@ -1257,7 +1271,11 @@
                      * this block again.
                      */
                     FixedNode targetNode;
-                    block.setFirstInstruction(operatingDimension, currentGraph.add(new BeginNode()));
+                    if (isGoto && block.getPredecessorCount() == 1) {
+                        block.setFirstInstruction(operatingDimension, lastInstr);
+                    } else {
+                        block.setFirstInstruction(operatingDimension, currentGraph.add(new BeginNode()));
+                    }
                     targetNode = block.getFirstInstruction(operatingDimension);
                     Target target = checkLoopExit(targetNode, block, state);
                     FixedNode result = target.fixed;
@@ -1632,9 +1650,9 @@
             protected void genIf(ValueNode x, Condition cond, ValueNode y) {
                 // assert !x.isDeleted() && !y.isDeleted();
                 // assert currentBlock.numNormalSuccessors() == 2;
-                assert currentBlock.getSuccessors().size() == 2;
-                BciBlock trueBlock = currentBlock.getSuccessors().get(0);
-                BciBlock falseBlock = currentBlock.getSuccessors().get(1);
+                assert currentBlock.getSuccessorCount() == 2;
+                BciBlock trueBlock = currentBlock.getSuccessor(0);
+                BciBlock falseBlock = currentBlock.getSuccessor(1);
                 if (trueBlock == falseBlock) {
                     appendGoto(createTarget(trueBlock, frameState));
                     return;