comparison graal/GraalCompiler/src/com/sun/c1x/graph/IR.java @ 2868:6d24c27902a2

turned inlining into a phase, some node cloning fixes, added NodeWorklist
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 07 Jun 2011 19:19:14 +0200
parents 5c545fef2c81
children fc75fd3fa5e4
comparison
equal deleted inserted replaced
2867:5c545fef2c81 2868:6d24c27902a2
27 27
28 import com.oracle.graal.graph.*; 28 import com.oracle.graal.graph.*;
29 import com.oracle.max.graal.schedule.*; 29 import com.oracle.max.graal.schedule.*;
30 import com.sun.c1x.*; 30 import com.sun.c1x.*;
31 import com.sun.c1x.debug.*; 31 import com.sun.c1x.debug.*;
32 import com.sun.c1x.gen.*;
33 import com.sun.c1x.ir.*; 32 import com.sun.c1x.ir.*;
34 import com.sun.c1x.lir.*; 33 import com.sun.c1x.lir.*;
35 import com.sun.c1x.observer.*; 34 import com.sun.c1x.observer.*;
36 import com.sun.c1x.value.*; 35 import com.sun.c1x.value.*;
37 import com.sun.cri.ci.*; 36 import com.sun.cri.ci.*;
155 154
156 private void buildGraph() { 155 private void buildGraph() {
157 // Graph builder must set the startBlock and the osrEntryBlock 156 // Graph builder must set the startBlock and the osrEntryBlock
158 new GraphBuilder(compilation, compilation.method, compilation.graph).build(false); 157 new GraphBuilder(compilation, compilation.method, compilation.graph).build(false);
159 158
159 // CompilerGraph duplicate = new CompilerGraph();
160 // Map<Node, Node> replacements = new HashMap<Node, Node>();
161 // replacements.put(compilation.graph.start(), duplicate.start());
162 // duplicate.addDuplicate(compilation.graph.getNodes(), replacements);
163 // compilation.graph = duplicate;
164
160 verifyAndPrint("After graph building"); 165 verifyAndPrint("After graph building");
161 166
162 DeadCodeElimination dce = new DeadCodeElimination(); 167 DeadCodeElimination dce = new DeadCodeElimination();
163 dce.apply(compilation.graph); 168 dce.apply(compilation.graph);
164 if (dce.deletedNodeCount > 0) { 169 if (dce.deletedNodeCount > 0) {
165 verifyAndPrint("After dead code elimination"); 170 verifyAndPrint("After dead code elimination");
166 } 171 }
167 172
168 if (C1XOptions.Inline) { 173 if (C1XOptions.Inline) {
169 inlineMethods(); 174 new Inlining(compilation, this).apply(compilation.graph);
170 } 175 }
171 176
172 if (C1XOptions.PrintCompilation) { 177 if (C1XOptions.PrintCompilation) {
173 TTY.print(String.format("%3d blocks | ", compilation.stats.blockCount)); 178 TTY.print(String.format("%3d blocks | ", compilation.stats.blockCount));
174 } 179 }
175 }
176
177 private void inlineMethods() {
178 int inliningSize = compilation.method.code().length;
179 boolean inlined;
180 int iterations = C1XOptions.MaximumRecursiveInlineLevel;
181 do {
182 inlined = false;
183
184 List<Invoke> trivialInline = new ArrayList<Invoke>();
185 List<Invoke> deoptInline = new ArrayList<Invoke>();
186 List<RiMethod> deoptMethods = new ArrayList<RiMethod>();
187 for (Node node : compilation.graph.getNodes()) {
188 if (node instanceof Invoke) {
189 Invoke invoke = (Invoke) node;
190 RiMethod target = invoke.target;
191 if (target.isResolved() && !Modifier.isNative(target.accessFlags())) {
192 if (target.canBeStaticallyBound()) {
193 trivialInline.add(invoke);
194 } else {
195 RiMethod concrete = invoke.target.holder().uniqueConcreteMethod(invoke.target);
196 if (concrete != null && concrete.isResolved() && !Modifier.isNative(concrete.accessFlags())) {
197 deoptInline.add(invoke);
198 deoptMethods.add(concrete);
199 }
200 }
201 }
202 }
203 }
204
205 for (Invoke invoke : trivialInline) {
206 if (inlineMethod(invoke, invoke.target)) {
207 inlined = true;
208 inliningSize += invoke.target.code().length;
209 if (inliningSize > C1XOptions.MaximumInstructionCount) {
210 break;
211 }
212 }
213 }
214
215 for (int i = 0; i < deoptInline.size(); i++) {
216 Invoke invoke = deoptInline.get(i);
217 RiMethod method = deoptMethods.get(i);
218 if (inlineMethod(invoke, method)) {
219 if (C1XOptions.TraceInlining) {
220 System.out.println("registering concrete method assumption...");
221 }
222 compilation.assumptions.recordConcreteMethod(invoke.target, method);
223 inlined = true;
224 inliningSize += method.code().length;
225 if (inliningSize > C1XOptions.MaximumInstructionCount) {
226 break;
227 }
228 }
229 }
230
231 if (inlined) {
232 DeadCodeElimination dce = new DeadCodeElimination();
233 dce.apply(compilation.graph);
234 if (dce.deletedNodeCount > 0) {
235 verifyAndPrint("After dead code elimination");
236 }
237 verifyAndPrint("After inlining iteration");
238 }
239
240 if (inliningSize > C1XOptions.MaximumInstructionCount) {
241 break;
242 }
243 } while(inlined && (--iterations > 0));
244 }
245
246 private boolean inlineMethod(Invoke invoke, RiMethod method) {
247 String name = invoke.id() + ": " + CiUtil.format("%H.%n(%p):%r", method, false) + " (" + method.code().length + " bytes)";
248 FrameState stateAfter = invoke.stateAfter();
249
250 if (method.code().length > C1XOptions.MaximumInlineSize) {
251 if (C1XOptions.TraceInlining) {
252 System.out.println("not inlining " + name + " because of code size");
253 }
254 return false;
255 }
256
257 if (invoke.predecessors().size() == 0) {
258 if (C1XOptions.TraceInlining) {
259 System.out.println("not inlining " + name + " because the invoke is dead code");
260 }
261 return false;
262 }
263
264 Instruction exceptionEdge = invoke.exceptionEdge();
265 // if (exceptionEdge != null) {
266 // if (C1XOptions.TraceInlining) {
267 // System.out.println("not inlining " + name + " because of exceptionEdge");
268 // }
269 // return false;
270 // }
271 if (!method.holder().isInitialized()) {
272 if (C1XOptions.TraceInlining) {
273 System.out.println("not inlining " + name + " because of non-initialized class");
274 }
275 return false;
276 }
277
278 if (C1XOptions.TraceInlining) {
279 System.out.printf("Building graph for %s, locals: %d, stack: %d\n", name, method.maxLocals(), method.maxStackSize());
280 }
281
282 CompilerGraph graph = new CompilerGraph();
283 new GraphBuilder(compilation, method, graph).build(true);
284
285 boolean withReceiver = !Modifier.isStatic(method.accessFlags());
286
287 int argumentCount = method.signature().argumentCount(false);
288 Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)];
289 int slot = withReceiver ? 1 : 0;
290 int param = withReceiver ? 1 : 0;
291 for (int i = 0; i < argumentCount; i++) {
292 parameters[param++] = invoke.argument(slot);
293 slot += method.signature().argumentKindAt(i).sizeInSlots();
294 }
295 if (withReceiver) {
296 parameters[0] = invoke.argument(0);
297 }
298
299 HashMap<Node, Node> replacements = new HashMap<Node, Node>();
300 ArrayList<Node> nodes = new ArrayList<Node>();
301 ArrayList<Node> frameStates = new ArrayList<Node>();
302 Return returnNode = null;
303 Unwind unwindNode = null;
304 StartNode startNode = graph.start();
305 for (Node node : graph.getNodes()) {
306 if (node != null) {
307 if (node instanceof StartNode) {
308 assert startNode == node;
309 } else if (node instanceof Local) {
310 replacements.put(node, parameters[((Local) node).index()]);
311 } else {
312 nodes.add(node);
313 if (node instanceof Return) {
314 returnNode = (Return) node;
315 } else if (node instanceof Unwind) {
316 unwindNode = (Unwind) node;
317 } else if (node instanceof FrameState) {
318 frameStates.add(node);
319 }
320 }
321 }
322 }
323
324 if (C1XOptions.TraceInlining) {
325 printGraph("Subgraph " + CiUtil.format("%H.%n(%p):%r", method, false), graph);
326 System.out.println("inlining " + name + ": " + frameStates.size() + " frame states, " + nodes.size() + " nodes");
327 }
328
329 assert invoke.predecessors().size() == 1 : "size: " + invoke.predecessors().size();
330 Instruction pred;
331 if (withReceiver) {
332 pred = new NullCheck(parameters[0], compilation.graph);
333 } else {
334 pred = new Merge(compilation.graph);
335 }
336 invoke.predecessors().get(0).successors().replace(invoke, pred);
337 replacements.put(startNode, pred);
338
339 Map<Node, Node> duplicates = compilation.graph.addDuplicate(nodes, replacements);
340
341 if (returnNode != null) {
342 List<Node> usages = new ArrayList<Node>(invoke.usages());
343 for (Node usage : usages) {
344 if (returnNode.result() instanceof Local) {
345 usage.inputs().replace(invoke, replacements.get(returnNode.result()));
346 } else {
347 usage.inputs().replace(invoke, duplicates.get(returnNode.result()));
348 }
349 }
350 Node returnDuplicate = duplicates.get(returnNode);
351 returnDuplicate.inputs().clearAll();
352
353 assert returnDuplicate.predecessors().size() == 1;
354 Node returnPred = returnDuplicate.predecessors().get(0);
355 int index = returnDuplicate.predecessorsIndex().get(0);
356 returnPred.successors().setAndClear(index, invoke, 0);
357 returnDuplicate.delete();
358 }
359
360 // if (invoke.next() instanceof Merge) {
361 // ((Merge) invoke.next()).removePhiPredecessor(invoke);
362 // }
363 // invoke.successors().clearAll();
364 invoke.inputs().clearAll();
365 invoke.setExceptionEdge(null);
366 // invoke.delete();
367
368
369 if (exceptionEdge != null) {
370 if (unwindNode != null) {
371 assert unwindNode.predecessors().size() == 1;
372 assert exceptionEdge.successors().size() == 1;
373 ExceptionObject obj = (ExceptionObject) exceptionEdge;
374
375 List<Node> usages = new ArrayList<Node>(obj.usages());
376 for (Node usage : usages) {
377 if (replacements.containsKey(unwindNode.exception())) {
378 usage.inputs().replace(obj, replacements.get(unwindNode.exception()));
379 } else {
380 usage.inputs().replace(obj, duplicates.get(unwindNode.exception()));
381 }
382 }
383 Node unwindDuplicate = duplicates.get(unwindNode);
384 unwindDuplicate.inputs().clearAll();
385
386 assert unwindDuplicate.predecessors().size() == 1;
387 Node unwindPred = unwindDuplicate.predecessors().get(0);
388 int index = unwindDuplicate.predecessorsIndex().get(0);
389 unwindPred.successors().setAndClear(index, obj, 0);
390
391 obj.inputs().clearAll();
392 obj.delete();
393 unwindDuplicate.delete();
394
395 }
396 }
397
398 // adjust all frame states that were copied
399 if (frameStates.size() > 0) {
400 FrameState outerFrameState = stateAfter.duplicateModified(invoke.bci, invoke.kind);
401 for (Node frameState : frameStates) {
402 ((FrameState) duplicates.get(frameState)).setOuterFrameState(outerFrameState);
403 }
404 }
405
406 if (C1XOptions.TraceInlining) {
407 verifyAndPrint("After inlining " + CiUtil.format("%H.%n(%p):%r", method, false));
408 }
409 return true;
410 } 180 }
411 181
412 /** 182 /**
413 * Gets the linear scan ordering of blocks as a list. 183 * Gets the linear scan ordering of blocks as a list.
414 * @return the blocks in linear scan order 184 * @return the blocks in linear scan order