diff graal/GraalCompiler/src/com/sun/c1x/graph/IR.java @ 2866:7f14e6b48a9c

added dead code elimination added ValueAnchor (temp workaround) more inlining logic (now uses DCE) IdealGraphPrinter: print even if Scheduler fails added inlining and DCE tracing options to C1XOptions
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 07 Jun 2011 16:27:08 +0200
parents 7596ae867a7b
children 5c545fef2c81
line wrap: on
line diff
--- a/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Wed Jun 01 16:56:54 2011 +0200
+++ b/graal/GraalCompiler/src/com/sun/c1x/graph/IR.java	Tue Jun 07 16:27:08 2011 +0200
@@ -83,15 +83,6 @@
             C1XTimers.HIR_OPTIMIZE.start();
         }
 
-        new PhiSimplifier(this);
-
-//        Graph newGraph = new Graph();
-//        HashMap<Node, Node> replacement = new HashMap<Node, Node>();
-//        replacement.put(compilation.graph.start(), newGraph.start());
-//        replacement.put(compilation.graph.end(), newGraph.end());
-//        newGraph.addDuplicate(compilation.graph.getNodes(), replacement);
-//        compilation.graph = newGraph;
-
         Graph graph = compilation.graph;
 
         // Split critical edges.
@@ -102,7 +93,7 @@
                 for (int j = 0; j < n.successors().size(); ++j) {
                     Node succ = n.successors().get(j);
                     if (Schedule.truePredecessorCount(succ) > 1) {
-                        Anchor a = new Anchor(null, graph);
+                        Anchor a = new Anchor(graph);
                         a.successors().setAndClear(1, n, j);
                         n.successors().set(j, a);
                     }
@@ -164,52 +155,18 @@
 
     private void buildGraph() {
         // Graph builder must set the startBlock and the osrEntryBlock
-        new GraphBuilder(compilation, compilation.method, compilation.graph).build();
+        new GraphBuilder(compilation, compilation.method, compilation.graph).build(false);
 
         verifyAndPrint("After graph building");
 
-        List<Invoke> trivialInline = new ArrayList<Invoke>();
-        List<Invoke> deoptInline = new ArrayList<Invoke>();
-        List<RiMethod> deoptMethods = new ArrayList<RiMethod>();
-        for (Node node : compilation.graph.getNodes()) {
-            if (node instanceof Invoke) {
-                Invoke invoke = (Invoke) node;
-                RiMethod target = invoke.target;
-                if (target.isResolved() && !Modifier.isNative(target.accessFlags())) {
-                    if (target.canBeStaticallyBound()) {
-                        trivialInline.add(invoke);
-                    } else {
-                        RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target);
-                        if (concrete != null) {
-                            deoptInline.add(invoke);
-                            deoptMethods.add(concrete);
-                        }
-                    }
-                }
-            }
+        DeadCodeElimination dce = new DeadCodeElimination();
+        dce.apply(compilation.graph);
+        if (dce.deletedNodeCount > 0) {
+            verifyAndPrint("After dead code elimination");
         }
 
-        int allowedInlinings = 50;
-        for (Invoke invoke : trivialInline) {
-            if (inlineMethod(invoke, invoke.target)) {
-                if (--allowedInlinings <= 0) {
-                    break;
-                }
-            }
-        }
-
-        for (int i = 0; i < deoptInline.size(); i++) {
-            Invoke invoke = deoptInline.get(i);
-            RiMethod method = deoptMethods.get(i);
-            if (inlineMethod(invoke, method)) {
-                if (C1XOptions.TraceInlining) {
-                    System.out.println("registering concrete method assumption...");
-                }
-                compilation.assumptions.recordConcreteMethod(invoke.target, method);
-                if (--allowedInlinings <= 0) {
-                    break;
-                }
-            }
+        if (C1XOptions.Inline) {
+            inlineMethods();
         }
 
         if (C1XOptions.PrintCompilation) {
@@ -217,23 +174,100 @@
         }
     }
 
+    private void inlineMethods() {
+        int inliningSize = compilation.method.code().length;
+        boolean inlined;
+        int iterations = C1XOptions.MaximumRecursiveInlineLevel;
+        do {
+            inlined = false;
+
+            List<Invoke> trivialInline = new ArrayList<Invoke>();
+            List<Invoke> deoptInline = new ArrayList<Invoke>();
+            List<RiMethod> deoptMethods = new ArrayList<RiMethod>();
+            for (Node node : compilation.graph.getNodes()) {
+                if (node instanceof Invoke) {
+                    Invoke invoke = (Invoke) node;
+                    RiMethod target = invoke.target;
+                    if (target.isResolved() && !Modifier.isNative(target.accessFlags())) {
+                        if (target.canBeStaticallyBound()) {
+                            trivialInline.add(invoke);
+                        } else {
+                            RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target);
+                            if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) {
+                                deoptInline.add(invoke);
+                                deoptMethods.add(concrete);
+                            }
+                        }
+                    }
+                }
+            }
+
+            for (Invoke invoke : trivialInline) {
+                if (inlineMethod(invoke, invoke.target)) {
+                    inlined = true;
+                    inliningSize += invoke.target.code().length;
+                    if (inliningSize > C1XOptions.MaximumInstructionCount) {
+                        break;
+                    }
+                }
+            }
+
+            for (int i = 0; i < deoptInline.size(); i++) {
+                Invoke invoke = deoptInline.get(i);
+                RiMethod method = deoptMethods.get(i);
+                if (inlineMethod(invoke, method)) {
+                    if (C1XOptions.TraceInlining) {
+                        System.out.println("registering concrete method assumption...");
+                    }
+                    compilation.assumptions.recordConcreteMethod(invoke.target, method);
+                    inlined = true;
+                    inliningSize += method.code().length;
+                    if (inliningSize > C1XOptions.MaximumInstructionCount) {
+                        break;
+                    }
+                }
+            }
+
+            if (inlined) {
+                DeadCodeElimination dce = new DeadCodeElimination();
+                dce.apply(compilation.graph);
+                if (dce.deletedNodeCount > 0) {
+                    verifyAndPrint("After dead code elimination");
+                }
+                verifyAndPrint("After inlining iteration");
+            }
+
+            if (inliningSize > C1XOptions.MaximumInstructionCount) {
+                break;
+            }
+        } while(inlined && (--iterations > 0));
+    }
+
     private boolean inlineMethod(Invoke invoke, RiMethod method) {
         String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
+        FrameState stateAfter = invoke.stateAfter();
 
-        if (method.code().length > 50) {
+        if (method.code().length > C1XOptions.MaximumInlineSize) {
             if (C1XOptions.TraceInlining) {
                 System.out.println("not inlining " + name + " because of code size");
             }
             return false;
         }
 
-        Instruction exceptionEdge = invoke.exceptionEdge();
-        if (exceptionEdge != null) {
+        if (invoke.predecessors().size() == 0) {
             if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of exceptionEdge");
+                System.out.println("not inlining " + name + " because the invoke is dead code");
             }
             return false;
         }
+
+        Instruction exceptionEdge = invoke.exceptionEdge();
+//        if (exceptionEdge != null) {
+//            if (C1XOptions.TraceInlining) {
+//                System.out.println("not inlining " + name + " because of exceptionEdge");
+//            }
+//            return false;
+//        }
         if (!method.holder().isInitialized()) {
             if (C1XOptions.TraceInlining) {
                 System.out.println("not inlining " + name + " because of non-initialized class");
@@ -242,10 +276,11 @@
         }
 
         if (C1XOptions.TraceInlining) {
-            System.out.println("building graph: " + name);
+            System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize());
         }
+
         CompilerGraph graph = new CompilerGraph();
-        new GraphBuilder(compilation, method, graph).build();
+        new GraphBuilder(compilation, method, graph).build(true);
 
         boolean withReceiver = !Modifier.isStatic(method.accessFlags());
 
@@ -266,12 +301,11 @@
         ArrayList<Node> frameStates = new ArrayList<Node>();
         Return returnNode = null;
         Unwind unwindNode = null;
-        StartNode startNode = null;
-        boolean invokes = false;
+        StartNode startNode = graph.start();
         for (Node node : graph.getNodes()) {
             if (node != null) {
                 if (node instanceof StartNode) {
-                    startNode = (StartNode) node;
+                    assert startNode == node;
                 } else if (node instanceof Local) {
                     replacements.put(node, parameters[((Local) node).index()]);
                 } else {
@@ -286,30 +320,19 @@
                 }
             }
         }
-        if (unwindNode != null) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of unwind node");
-            }
-            return false;
-        }
-        if (invokes) {
-            if (C1XOptions.TraceInlining) {
-                System.out.println("not inlining " + name + " because of invokes");
-            }
-            return false;
-        }
 
         if (C1XOptions.TraceInlining) {
+            printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph);
             System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
         }
 
+        assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
         Instruction pred;
         if (withReceiver) {
             pred = new NullCheck(parameters[0], compilation.graph);
         } else {
             pred = new Merge(compilation.graph);
         }
-        assert invoke.predecessors().size() == 1;
         invoke.predecessors().get(0).successors().replace(invoke, pred);
         replacements.put(startNode, pred);
 
@@ -331,10 +354,48 @@
             Node returnPred = returnDuplicate.predecessors().get(0);
             int index = returnDuplicate.predecessorsIndex().get(0);
             returnPred.successors().setAndClear(index, invoke, 0);
-
             returnDuplicate.delete();
         }
-        FrameState stateAfter = invoke.stateAfter();
+
+//        if (invoke.next() instanceof Merge) {
+//            ((Merge) invoke.next()).removePhiPredecessor(invoke);
+//        }
+//        invoke.successors().clearAll();
+        invoke.inputs().clearAll();
+        invoke.setExceptionEdge(null);
+//        invoke.delete();
+
+
+        if (exceptionEdge != null) {
+            if (unwindNode != null) {
+                assert unwindNode.predecessors().size() == 1;
+                assert exceptionEdge.successors().size() == 1;
+                ExceptionObject obj = (ExceptionObject) exceptionEdge;
+
+                List<Node> usages = new ArrayList<Node>(obj.usages());
+                for (Node usage : usages) {
+                    if (replacements.containsKey(unwindNode.exception())) {
+                        usage.inputs().replace(obj, replacements.get(unwindNode.exception()));
+                    } else {
+                        usage.inputs().replace(obj, duplicates.get(unwindNode.exception()));
+                    }
+                }
+                Node unwindDuplicate = duplicates.get(unwindNode);
+                unwindDuplicate.inputs().clearAll();
+
+                assert unwindDuplicate.predecessors().size() == 1;
+                Node unwindPred = unwindDuplicate.predecessors().get(0);
+                int index = unwindDuplicate.predecessorsIndex().get(0);
+                unwindPred.successors().setAndClear(index, obj, 0);
+
+                obj.inputs().clearAll();
+                obj.delete();
+                unwindDuplicate.delete();
+
+            }
+        }
+
+        // adjust all frame states that were copied
         if (frameStates.size() > 0) {
             FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind);
             for (Node frameState : frameStates) {
@@ -342,52 +403,12 @@
             }
         }
 
-        invoke.successors().clearAll();
-        invoke.inputs().clearAll();
-        invoke.delete();
-
-        stateAfter.delete();
-
-        deleteUnused(exceptionEdge);
-
-        verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false));
+        if (C1XOptions.TraceInlining) {
+            verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false));
+        }
         return true;
     }
 
-    private void deleteUnused(Node node) {
-        if (node != null && node.predecessors().size() == 0) {
-            if (node instanceof ExceptionObject) {
-                Node successor = node.successors().get(0);
-                node.successors().clearAll();
-                if (successor instanceof ExceptionDispatch) {
-                    ExceptionDispatch dispatch = (ExceptionDispatch) successor;
-                    Node succ1 = dispatch.catchSuccessor();
-                    Node succ2 = dispatch.otherSuccessor();
-                    if (succ1 instanceof Merge) {
-                        ((Merge) succ1).removePhiPredecessor(dispatch);
-                    }
-                    if (succ2 instanceof Merge) {
-                        ((Merge) succ2).removePhiPredecessor(dispatch);
-                    }
-                    dispatch.successors().clearAll();
-                    deleteUnused(succ1);
-                    deleteUnused(succ2);
-                    dispatch.delete();
-                } else {
-                    assert successor instanceof Merge;
-                    System.out.println("succ: " + successor.successors().get(0));
-                    Node next = successor.successors().get(0);
-                    successor.successors().clearAll();
-                    deleteUnused(next);
-                    successor.delete();
-                }
-                node.delete();
-            } else if (node instanceof Unwind) {
-                node.delete();
-            }
-        }
-    }
-
     /**
      * Gets the linear scan ordering of blocks as a list.
      * @return the blocks in linear scan order
@@ -420,6 +441,17 @@
         }
     }
 
+    public void printGraph(String phase, Graph graph) {
+        if (C1XOptions.PrintHIR && !TTY.isSuppressed()) {
+            TTY.println(phase);
+            print(false);
+        }
+
+        if (compilation.compiler.isObserved()) {
+            compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, phase, graph, true, false));
+        }
+    }
+
     public int numLoops() {
         return compilation.stats.loopCount;
     }