Mercurial > hg > truffle
comparison graal/Compiler/src/com/sun/c1x/graph/IR.java @ 2507:9ec15d6914ca
Pull over of compiler from maxine repository.
author | Thomas Wuerthinger <thomas@wuerthinger.net> |
---|---|
date | Wed, 27 Apr 2011 11:43:22 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2506:4a3bf8a5bf41 | 2507:9ec15d6914ca |
---|---|
1 /* | |
2 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
20 * or visit www.oracle.com if you need additional information or have any | |
21 * questions. | |
22 */ | |
23 package com.sun.c1x.graph; | |
24 | |
25 import java.util.*; | |
26 | |
27 import com.sun.c1x.*; | |
28 import com.sun.c1x.debug.*; | |
29 import com.sun.c1x.ir.*; | |
30 import com.sun.c1x.observer.*; | |
31 import com.sun.c1x.opt.*; | |
32 import com.sun.c1x.value.*; | |
33 | |
34 /** | |
35 * This class implements the overall container for the HIR (high-level IR) graph | |
36 * and directs its construction, optimization, and finalization. | |
37 * | |
38 * @author Thomas Wuerthinger | |
39 * @author Ben L. Titzer | |
40 */ | |
41 public class IR { | |
42 | |
43 /** | |
44 * The compilation associated with this IR. | |
45 */ | |
46 public final C1XCompilation compilation; | |
47 | |
48 /** | |
49 * The start block of this IR. | |
50 */ | |
51 public BlockBegin startBlock; | |
52 | |
53 /** | |
54 * The entry block for an OSR compile. | |
55 */ | |
56 public BlockBegin osrEntryBlock; | |
57 | |
58 /** | |
59 * The top IRScope. | |
60 */ | |
61 public IRScope topScope; | |
62 | |
63 /** | |
64 * The linear-scan ordered list of blocks. | |
65 */ | |
66 private List<BlockBegin> orderedBlocks; | |
67 | |
68 /** | |
69 * Creates a new IR instance for the specified compilation. | |
70 * @param compilation the compilation | |
71 */ | |
72 public IR(C1XCompilation compilation) { | |
73 this.compilation = compilation; | |
74 } | |
75 | |
76 /** | |
77 * Builds the graph, optimizes it, and computes the linear scan block order. | |
78 */ | |
79 public void build() { | |
80 if (C1XOptions.PrintTimers) { | |
81 C1XTimers.HIR_CREATE.start(); | |
82 } | |
83 | |
84 buildGraph(); | |
85 | |
86 if (C1XOptions.PrintTimers) { | |
87 C1XTimers.HIR_CREATE.stop(); | |
88 C1XTimers.HIR_OPTIMIZE.start(); | |
89 } | |
90 | |
91 optimize1(); | |
92 computeLinearScanOrder(); | |
93 optimize2(); | |
94 | |
95 if (C1XOptions.PrintTimers) { | |
96 C1XTimers.HIR_OPTIMIZE.stop(); | |
97 } | |
98 } | |
99 | |
100 private void buildGraph() { | |
101 topScope = new IRScope(null, null, compilation.method, compilation.osrBCI); | |
102 | |
103 // Graph builder must set the startBlock and the osrEntryBlock | |
104 new GraphBuilder(compilation, this).build(topScope); | |
105 assert startBlock != null; | |
106 verifyAndPrint("After graph building"); | |
107 | |
108 if (C1XOptions.PrintCompilation) { | |
109 TTY.print(String.format("%3d blocks | ", this.numberOfBlocks())); | |
110 } | |
111 } | |
112 | |
113 private void optimize1() { | |
114 if (!compilation.isTypesafe()) { | |
115 new UnsafeCastEliminator(this); | |
116 verifyAndPrint("After unsafe cast elimination"); | |
117 } | |
118 | |
119 // do basic optimizations | |
120 if (C1XOptions.PhiSimplify) { | |
121 new PhiSimplifier(this); | |
122 verifyAndPrint("After phi simplification"); | |
123 } | |
124 if (C1XOptions.OptNullCheckElimination) { | |
125 new NullCheckEliminator(this); | |
126 verifyAndPrint("After null check elimination"); | |
127 } | |
128 if (C1XOptions.OptDeadCodeElimination1) { | |
129 new LivenessMarker(this).removeDeadCode(); | |
130 verifyAndPrint("After dead code elimination 1"); | |
131 } | |
132 if (C1XOptions.OptCEElimination) { | |
133 new CEEliminator(this); | |
134 verifyAndPrint("After CEE elimination"); | |
135 } | |
136 if (C1XOptions.OptBlockMerging) { | |
137 new BlockMerger(this); | |
138 verifyAndPrint("After block merging"); | |
139 } | |
140 | |
141 if (compilation.compiler.extensions != null) { | |
142 for (C1XCompilerExtension ext : compilation.compiler.extensions) { | |
143 ext.run(this); | |
144 } | |
145 } | |
146 } | |
147 | |
148 private void computeLinearScanOrder() { | |
149 if (C1XOptions.GenLIR) { | |
150 makeLinearScanOrder(); | |
151 verifyAndPrint("After linear scan order"); | |
152 } | |
153 } | |
154 | |
155 private void makeLinearScanOrder() { | |
156 if (orderedBlocks == null) { | |
157 CriticalEdgeFinder finder = new CriticalEdgeFinder(this); | |
158 startBlock.iteratePreOrder(finder); | |
159 finder.splitCriticalEdges(); | |
160 ComputeLinearScanOrder computeLinearScanOrder = new ComputeLinearScanOrder(compilation.stats.blockCount, startBlock); | |
161 orderedBlocks = computeLinearScanOrder.linearScanOrder(); | |
162 compilation.stats.loopCount = computeLinearScanOrder.numLoops(); | |
163 computeLinearScanOrder.printBlocks(); | |
164 } | |
165 } | |
166 | |
167 private void optimize2() { | |
168 // do more advanced, dominator-based optimizations | |
169 if (C1XOptions.OptGlobalValueNumbering) { | |
170 makeLinearScanOrder(); | |
171 new GlobalValueNumberer(this); | |
172 verifyAndPrint("After global value numbering"); | |
173 } | |
174 if (C1XOptions.OptDeadCodeElimination2) { | |
175 new LivenessMarker(this).removeDeadCode(); | |
176 verifyAndPrint("After dead code elimination 2"); | |
177 } | |
178 | |
179 } | |
180 | |
181 /** | |
182 * Gets the linear scan ordering of blocks as a list. | |
183 * @return the blocks in linear scan order | |
184 */ | |
185 public List<BlockBegin> linearScanOrder() { | |
186 return orderedBlocks; | |
187 } | |
188 | |
189 private void print(boolean cfgOnly) { | |
190 if (!TTY.isSuppressed()) { | |
191 TTY.println("IR for " + compilation.method); | |
192 final InstructionPrinter ip = new InstructionPrinter(TTY.out()); | |
193 final BlockPrinter bp = new BlockPrinter(this, ip, cfgOnly, false); | |
194 startBlock.iteratePreOrder(bp); | |
195 } | |
196 } | |
197 | |
198 /** | |
199 * Verifies the IR and prints it out if the relevant options are set. | |
200 * @param phase the name of the phase for printing | |
201 */ | |
202 public void verifyAndPrint(String phase) { | |
203 printToTTY(phase); | |
204 | |
205 if (compilation.compiler.isObserved()) { | |
206 compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, phase, startBlock, true, false)); | |
207 } | |
208 } | |
209 | |
210 private void printToTTY(String phase) { | |
211 if (C1XOptions.PrintHIR && !TTY.isSuppressed()) { | |
212 TTY.println(phase); | |
213 print(false); | |
214 } | |
215 } | |
216 | |
217 /** | |
218 * Creates and inserts a new block between this block and the specified successor, | |
219 * altering the successor and predecessor lists of involved blocks appropriately. | |
220 * @param source the source of the edge | |
221 * @param target the successor before which to insert a block | |
222 * @return the new block inserted | |
223 */ | |
224 public BlockBegin splitEdge(BlockBegin source, BlockBegin target) { | |
225 int bci; | |
226 if (target.predecessors().size() == 1) { | |
227 bci = target.bci(); | |
228 } else { | |
229 bci = source.end().bci(); | |
230 } | |
231 | |
232 // create new successor and mark it for special block order treatment | |
233 BlockBegin newSucc = new BlockBegin(bci, nextBlockNumber()); | |
234 | |
235 newSucc.setCriticalEdgeSplit(true); | |
236 | |
237 // This goto is not a safepoint. | |
238 Goto e = new Goto(target, null, false); | |
239 newSucc.setNext(e, bci); | |
240 newSucc.setEnd(e); | |
241 // setup states | |
242 FrameState s = source.end().stateAfter(); | |
243 newSucc.setStateBefore(s); | |
244 e.setStateAfter(s); | |
245 assert newSucc.stateBefore().localsSize() == s.localsSize(); | |
246 assert newSucc.stateBefore().stackSize() == s.stackSize(); | |
247 assert newSucc.stateBefore().locksSize() == s.locksSize(); | |
248 // link predecessor to new block | |
249 source.end().substituteSuccessor(target, newSucc); | |
250 | |
251 // The ordering needs to be the same, so remove the link that the | |
252 // set_end call above added and substitute the new_sux for this | |
253 // block. | |
254 target.removePredecessor(newSucc); | |
255 | |
256 // the successor could be the target of a switch so it might have | |
257 // multiple copies of this predecessor, so substitute the new_sux | |
258 // for the first and delete the rest. | |
259 List<BlockBegin> list = target.predecessors(); | |
260 int x = list.indexOf(source); | |
261 assert x >= 0; | |
262 list.set(x, newSucc); | |
263 newSucc.addPredecessor(source); | |
264 Iterator<BlockBegin> iterator = list.iterator(); | |
265 while (iterator.hasNext()) { | |
266 if (iterator.next() == source) { | |
267 iterator.remove(); | |
268 newSucc.addPredecessor(source); | |
269 } | |
270 } | |
271 return newSucc; | |
272 } | |
273 | |
274 public void replaceBlock(BlockBegin oldBlock, BlockBegin newBlock) { | |
275 assert !oldBlock.isExceptionEntry() : "cannot replace exception handler blocks (yet)"; | |
276 for (BlockBegin succ : oldBlock.end().successors()) { | |
277 succ.removePredecessor(oldBlock); | |
278 } | |
279 for (BlockBegin pred : oldBlock.predecessors()) { | |
280 // substitute the new successor for this block in each predecessor | |
281 pred.end().substituteSuccessor(oldBlock, newBlock); | |
282 // and add each predecessor to the successor | |
283 newBlock.addPredecessor(pred); | |
284 } | |
285 // this block is now disconnected; remove all its incoming and outgoing edges | |
286 oldBlock.predecessors().clear(); | |
287 oldBlock.end().successors().clear(); | |
288 } | |
289 | |
290 /** | |
291 * Disconnects the specified block from all other blocks. | |
292 * @param block the block to remove from the graph | |
293 */ | |
294 public void disconnectFromGraph(BlockBegin block) { | |
295 for (BlockBegin p : block.predecessors()) { | |
296 p.end().successors().remove(block); | |
297 } | |
298 for (BlockBegin s : block.end().successors()) { | |
299 s.predecessors().remove(block); | |
300 } | |
301 } | |
302 | |
303 public int nextBlockNumber() { | |
304 return compilation.stats.blockCount++; | |
305 } | |
306 | |
307 public int numberOfBlocks() { | |
308 return compilation.stats.blockCount; | |
309 } | |
310 | |
311 public int numLoops() { | |
312 return compilation.stats.loopCount; | |
313 } | |
314 } |