comparison graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java @ 2919:5429750cb94c

Merge
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Thu, 09 Jun 2011 11:30:58 +0200
parents e7ba2bad98fb 35fb2fef44f1
children a6d0743f3380
comparison
equal deleted inserted replaced
2918:e7ba2bad98fb 2919:5429750cb94c
40 private final IR ir; 40 private final IR ir;
41 41
42 private final Queue<Invoke> invokes = new ArrayDeque<Invoke>(); 42 private final Queue<Invoke> invokes = new ArrayDeque<Invoke>();
43 private final Queue<RiMethod> methods = new ArrayDeque<RiMethod>(); 43 private final Queue<RiMethod> methods = new ArrayDeque<RiMethod>();
44 private int inliningSize; 44 private int inliningSize;
45 45 private final boolean trace;
46 public InliningPhase(GraalCompilation compilation, IR ir) { 46
47 public InliningPhase(GraalCompilation compilation, IR ir, boolean trace) {
47 this.compilation = compilation; 48 this.compilation = compilation;
48 this.ir = ir; 49 this.ir = ir;
50 this.trace = trace;
49 } 51 }
50 52
51 private void addToQueue(Invoke invoke, RiMethod method) { 53 private void addToQueue(Invoke invoke, RiMethod method) {
52 invokes.add(invoke); 54 invokes.add(invoke);
53 methods.add(method); 55 methods.add(method);
54 inliningSize += method.code().length; 56 inliningSize += method.code().length;
55 } 57 }
56 58
59 static HashMap<RiMethod, Integer> methodCount = new HashMap<RiMethod, Integer>();
57 @Override 60 @Override
58 protected void run(Graph graph) { 61 protected void run(Graph graph) {
59 inliningSize = compilation.method.code().length; 62 inliningSize = compilation.method.code().length;
60 int iterations = GraalOptions.MaximumRecursiveInlineLevel; 63 for (int iterations = 0; iterations < GraalOptions.MaximumInlineLevel; iterations++) {
61 do { 64 for (Invoke invoke : graph.getNodes(Invoke.class)) {
62 for (Node node : graph.getNodes()) { 65 RiMethod target = invoke.target;
63 if (node instanceof Invoke) { 66 if (invoke.stateAfter() == null || invoke.stateAfter().locksSize() > 0) {
64 Invoke invoke = (Invoke) node; 67 if (trace) {
65 RiMethod target = invoke.target; 68 System.out.println("lock...");
66 if (!checkInliningConditions(invoke) || !target.isResolved() || Modifier.isNative(target.accessFlags())) {
67 continue;
68 } 69 }
69 if (target.canBeStaticallyBound()) { 70 continue;
70 if (checkInliningConditions(invoke.target)) { 71 }
71 addToQueue(invoke, invoke.target); 72 if (!checkInliningConditions(invoke) || !target.isResolved() || Modifier.isNative(target.accessFlags())) {
72 } 73 continue;
73 } else { 74 }
74 RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target); 75 if (target.canBeStaticallyBound()) {
75 if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) { 76 if (checkInliningConditions(invoke.target, iterations)) {
76 if (checkInliningConditions(concrete)) { 77 addToQueue(invoke, invoke.target);
77 if (GraalOptions.TraceInlining) { 78 }
78 System.out.println("registering concrete method assumption..."); 79 } else {
79 } 80 RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target);
80 compilation.assumptions.recordConcreteMethod(invoke.target, concrete); 81 if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) {
81 addToQueue(invoke, concrete); 82 if (checkInliningConditions(concrete, iterations)) {
83 if (trace) {
84 System.out.println("recording concrete method assumption...");
82 } 85 }
86 compilation.assumptions.recordConcreteMethod(invoke.target, concrete);
87 addToQueue(invoke, concrete);
83 } 88 }
84 } 89 }
85 if (inliningSize > GraalOptions.MaximumInstructionCount) { 90 }
86 break; 91 if (inliningSize > GraalOptions.MaximumInstructionCount) {
87 } 92 break;
88 } 93 }
89 } 94 }
90 95
91 assert invokes.size() == methods.size(); 96 assert invokes.size() == methods.size();
92 if (invokes.isEmpty()) { 97 if (invokes.isEmpty()) {
95 100
96 Invoke invoke; 101 Invoke invoke;
97 while ((invoke = invokes.poll()) != null) { 102 while ((invoke = invokes.poll()) != null) {
98 RiMethod method = methods.remove(); 103 RiMethod method = methods.remove();
99 inlineMethod(invoke, method); 104 inlineMethod(invoke, method);
105
106 if (methodCount.get(method) == null) {
107 methodCount.put(method, 1);
108 } else {
109 methodCount.put(method, methodCount.get(method) + 1);
110 }
100 } 111 }
101 DeadCodeEliminationPhase dce = new DeadCodeEliminationPhase(); 112 DeadCodeEliminationPhase dce = new DeadCodeEliminationPhase();
102 dce.apply(graph); 113 dce.apply(graph);
103 114
104 if (inliningSize > GraalOptions.MaximumInstructionCount) { 115 if (inliningSize > GraalOptions.MaximumInstructionCount) {
105 if (GraalOptions.TraceInlining) { 116 if (trace) {
106 System.out.println("inlining stopped: MaximumInstructionCount reached"); 117 System.out.println("inlining stopped: MaximumInstructionCount reached");
107 } 118 }
108 break; 119 break;
109 } 120 }
110 } while(--iterations > 0); 121 }
122
123 if (trace) {
124 int inlined = 0;
125 int duplicate = 0;
126 for (Map.Entry<RiMethod, Integer> entry : methodCount.entrySet()) {
127 inlined += entry.getValue();
128 duplicate += entry.getValue() - 1;
129 }
130 if (inlined > 0) {
131 System.out.printf("overhead_: %d (%5.3f %%)\n", duplicate, duplicate * 100.0 / inlined);
132 }
133 }
111 } 134 }
112 135
113 private boolean checkInliningConditions(Invoke invoke) { 136 private boolean checkInliningConditions(Invoke invoke) {
114 String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false); 137 String name = !trace ? null : invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", invoke.target, false);
115 if (invoke.predecessors().size() == 0) { 138 if (invoke.predecessors().size() == 0) {
116 if (GraalOptions.TraceInlining) { 139 if (trace) {
117 System.out.println("not inlining " + name + " because the invoke is dead code"); 140 System.out.println("not inlining " + name + " because the invoke is dead code");
118 } 141 }
119 return false; 142 return false;
120 } 143 }
144 if (invoke.stateAfter() == null) {
145 if (trace) {
146 System.out.println("not inlining " + name + " because of missing frame state");
147 }
148 }
121 return true; 149 return true;
122 } 150 }
123 151
124 private boolean checkInliningConditions(RiMethod method) { 152 private boolean checkInliningConditions(RiMethod method, int iterations) {
125 String name = null; 153 String name = !trace ? null : CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
126 if (GraalOptions.TraceInlining) {
127 name = CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
128 }
129 if (method.code().length > GraalOptions.MaximumInlineSize) { 154 if (method.code().length > GraalOptions.MaximumInlineSize) {
130 if (GraalOptions.TraceInlining) { 155 if (trace) {
131 System.out.println("not inlining " + name + " because of code size"); 156 System.out.println("not inlining " + name + " because of code size");
132 } 157 }
133 return false; 158 return false;
134 } 159 }
135 if (!method.holder().isInitialized()) { 160 if (!method.holder().isInitialized()) {
136 if (GraalOptions.TraceInlining) { 161 if (trace) {
137 System.out.println("not inlining " + name + " because of non-initialized class"); 162 System.out.println("not inlining " + name + " because of non-initialized class");
138 } 163 }
139 return false; 164 return false;
140 } 165 }
166 if (method == compilation.method && iterations > GraalOptions.MaximumRecursiveInlineLevel) {
167 if (trace) {
168 System.out.println("not inlining " + name + " because of recursive inlining limit");
169 }
170 return false;
171 }
141 return true; 172 return true;
142 } 173 }
143 174
144 private void inlineMethod(Invoke invoke, RiMethod method) { 175 private void inlineMethod(Invoke invoke, RiMethod method) {
145 String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)"; 176 String name = !trace ? null : invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
146 FrameState stateAfter = invoke.stateAfter(); 177 FrameState stateAfter = invoke.stateAfter();
147 Instruction exceptionEdge = invoke.exceptionEdge(); 178 Instruction exceptionEdge = invoke.exceptionEdge();
148 179
149 if (GraalOptions.TraceInlining) { 180 if (trace) {
150 System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize()); 181 System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize());
151 } 182 }
152 183
153 CompilerGraph graph = new CompilerGraph(compilation); 184 CompilerGraph graph = new CompilerGraph(compilation);
154 new GraphBuilderPhase(compilation, method, true, true).apply(graph); 185 new GraphBuilderPhase(compilation, method, true, true).apply(graph);
164 slot += method.signature().argumentKindAt(i).sizeInSlots(); 195 slot += method.signature().argumentKindAt(i).sizeInSlots();
165 } 196 }
166 if (withReceiver) { 197 if (withReceiver) {
167 parameters[0] = invoke.argument(0); 198 parameters[0] = invoke.argument(0);
168 } 199 }
200
201 invoke.inputs().clearAll();
169 202
170 HashMap<Node, Node> replacements = new HashMap<Node, Node>(); 203 HashMap<Node, Node> replacements = new HashMap<Node, Node>();
171 ArrayList<Node> nodes = new ArrayList<Node>(); 204 ArrayList<Node> nodes = new ArrayList<Node>();
172 ArrayList<Node> frameStates = new ArrayList<Node>(); 205 ArrayList<Node> frameStates = new ArrayList<Node>();
173 Return returnNode = null; 206 Return returnNode = null;
190 } 223 }
191 } 224 }
192 } 225 }
193 } 226 }
194 227
195 if (GraalOptions.TraceInlining) { 228 if (trace) {
196 ir.printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph); 229 ir.printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph);
197 System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes"); 230 System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
198 } 231 }
199 232
200 assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size(); 233 assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
206 } 239 }
207 invoke.predecessors().get(0).successors().replace(invoke, pred); 240 invoke.predecessors().get(0).successors().replace(invoke, pred);
208 replacements.put(startNode, pred); 241 replacements.put(startNode, pred);
209 242
210 Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements); 243 Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
244
245 int monitorIndexDelta = stateAfter.locksSize();
246 if (monitorIndexDelta > 0) {
247 for (Map.Entry<Node, Node> entry : duplicates.entrySet()) {
248 if (entry.getValue() instanceof MonitorAddress) {
249 System.out.println("Adjusting monitor index");
250 MonitorAddress address = (MonitorAddress) entry.getValue();
251 address.setMonitorIndex(address.monitorIndex() + monitorIndexDelta);
252 }
253 }
254 }
211 255
212 if (returnNode != null) { 256 if (returnNode != null) {
213 List<Node> usages = new ArrayList<Node>(invoke.usages()); 257 List<Node> usages = new ArrayList<Node>(invoke.usages());
214 for (Node usage : usages) { 258 for (Node usage : usages) {
215 if (returnNode.result() instanceof Local) { 259 if (returnNode.result() instanceof Local) {
226 int index = returnDuplicate.predecessorsIndex().get(0); 270 int index = returnDuplicate.predecessorsIndex().get(0);
227 returnPred.successors().setAndClear(index, invoke, 0); 271 returnPred.successors().setAndClear(index, invoke, 0);
228 returnDuplicate.delete(); 272 returnDuplicate.delete();
229 } 273 }
230 274
231 // if (invoke.next() instanceof Merge) {
232 // ((Merge) invoke.next()).removePhiPredecessor(invoke);
233 // }
234 // invoke.successors().clearAll();
235 invoke.inputs().clearAll();
236 invoke.setExceptionEdge(null);
237 // invoke.delete();
238
239
240 if (exceptionEdge != null) { 275 if (exceptionEdge != null) {
241 if (unwindNode != null) { 276 if (unwindNode != null) {
242 assert unwindNode.predecessors().size() == 1; 277 assert unwindNode.predecessors().size() == 1;
243 assert exceptionEdge.successors().size() == 1; 278 assert exceptionEdge.successors().size() == 1;
244 ExceptionObject obj = (ExceptionObject) exceptionEdge; 279 ExceptionObject obj = (ExceptionObject) exceptionEdge;
245 280
281 Unwind unwindDuplicate = (Unwind) duplicates.get(unwindNode);
246 List<Node> usages = new ArrayList<Node>(obj.usages()); 282 List<Node> usages = new ArrayList<Node>(obj.usages());
247 for (Node usage : usages) { 283 for (Node usage : usages) {
248 if (replacements.containsKey(unwindNode.exception())) { 284 usage.inputs().replace(obj, unwindDuplicate.exception());
249 usage.inputs().replace(obj, replacements.get(unwindNode.exception())); 285 }
250 } else {
251 usage.inputs().replace(obj, duplicates.get(unwindNode.exception()));
252 }
253 }
254 Node unwindDuplicate = duplicates.get(unwindNode);
255 unwindDuplicate.inputs().clearAll(); 286 unwindDuplicate.inputs().clearAll();
256 287
257 assert unwindDuplicate.predecessors().size() == 1; 288 assert unwindDuplicate.predecessors().size() == 1;
258 Node unwindPred = unwindDuplicate.predecessors().get(0); 289 Node unwindPred = unwindDuplicate.predecessors().get(0);
259 int index = unwindDuplicate.predecessorsIndex().get(0); 290 int index = unwindDuplicate.predecessorsIndex().get(0);
260 unwindPred.successors().setAndClear(index, obj, 0); 291 unwindPred.successors().setAndClear(index, obj, 0);
261 292
262 obj.inputs().clearAll(); 293 obj.inputs().clearAll();
263 obj.delete();
264 unwindDuplicate.delete(); 294 unwindDuplicate.delete();
265
266 } 295 }
267 } 296 }
268 297
269 // adjust all frame states that were copied 298 // adjust all frame states that were copied
270 if (frameStates.size() > 0) { 299 if (frameStates.size() > 0) {
272 for (Node frameState : frameStates) { 301 for (Node frameState : frameStates) {
273 ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState); 302 ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState);
274 } 303 }
275 } 304 }
276 305
277 if (GraalOptions.TraceInlining) { 306 if (trace) {
278 ir.printGraph("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false), compilation.graph); 307 ir.printGraph("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false), compilation.graph);
279 } 308 }
280 } 309 }
281 } 310 }