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 org.graalvm.compiler.core.gen; 24 25 import static jdk.vm.ci.code.ValueUtil.asRegister; 26 import static jdk.vm.ci.code.ValueUtil.isLegal; 27 import static jdk.vm.ci.code.ValueUtil.isRegister; 28 import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; 29 import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; 30 import static org.graalvm.compiler.lir.LIR.verifyBlock; 31 32 import java.util.ArrayList; 33 import java.util.Collection; 34 import java.util.List; 35 import org.graalvm.compiler.core.common.LIRKind; 36 import org.graalvm.compiler.core.common.calc.Condition; 37 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 38 import org.graalvm.compiler.core.common.cfg.BlockMap; 39 import org.graalvm.compiler.core.common.type.Stamp; 40 import org.graalvm.compiler.core.match.ComplexMatchValue; 41 import org.graalvm.compiler.core.match.MatchPattern; 42 import org.graalvm.compiler.core.match.MatchRuleRegistry; 43 import org.graalvm.compiler.core.match.MatchStatement; 44 import org.graalvm.compiler.debug.Debug; 45 import org.graalvm.compiler.debug.Debug.Scope; 46 import org.graalvm.compiler.debug.GraalError; 47 import org.graalvm.compiler.debug.TTY; 48 import org.graalvm.compiler.graph.GraalGraphError; 49 import org.graalvm.compiler.graph.Node; 50 import org.graalvm.compiler.graph.NodeMap; 51 import org.graalvm.compiler.graph.NodeSourcePosition; 52 import org.graalvm.compiler.graph.iterators.NodeIterable; 53 import org.graalvm.compiler.lir.FullInfopointOp; 54 import org.graalvm.compiler.lir.LIRFrameState; 55 import org.graalvm.compiler.lir.LIRInstruction; 56 import org.graalvm.compiler.lir.LabelRef; 57 import org.graalvm.compiler.lir.StandardOp.JumpOp; 58 import org.graalvm.compiler.lir.StandardOp.LabelOp; 59 import org.graalvm.compiler.lir.SwitchStrategy; 60 import org.graalvm.compiler.lir.Variable; 61 import org.graalvm.compiler.lir.debug.LIRGenerationDebugContext; 62 import org.graalvm.compiler.lir.gen.LIRGenerator; 63 import org.graalvm.compiler.lir.gen.LIRGenerator.Options; 64 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 65 import org.graalvm.compiler.lir.gen.LIRGeneratorTool.BlockScope; 118 119 private final NodeMap<Value> nodeOperands; 120 private final DebugInfoBuilder debugInfoBuilder; 121 private final int traceLIRGeneratorLevel; 122 123 protected final LIRGenerator gen; 124 125 private ValueNode currentInstruction; 126 private ValueNode lastInstructionPrinted; // Debugging only 127 128 private final NodeMatchRules nodeMatchRules; 129 private EconomicMap<Class<? extends Node>, List<MatchStatement>> matchRules; 130 131 public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, NodeMatchRules nodeMatchRules) { 132 this.gen = (LIRGenerator) gen; 133 this.nodeMatchRules = nodeMatchRules; 134 this.nodeOperands = graph.createNodeMap(); 135 this.debugInfoBuilder = createDebugInfoBuilder(graph, this); 136 OptionValues options = graph.getOptions(); 137 if (MatchExpressions.getValue(options)) { 138 matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass(), options); 139 } 140 traceLIRGeneratorLevel = TTY.isSuppressed() ? 0 : Options.TraceLIRGeneratorLevel.getValue(options); 141 142 assert nodeMatchRules.lirBuilder == null; 143 nodeMatchRules.lirBuilder = this; 144 } 145 146 public NodeMatchRules getNodeMatchRules() { 147 return nodeMatchRules; 148 } 149 150 @SuppressWarnings({"unused"}) 151 protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { 152 return new DebugInfoBuilder(nodeValueMap); 153 } 154 155 /** 156 * Returns the operand that has been previously initialized by 157 * {@link #setResult(ValueNode, Value)} with the result of an instruction. It's a code 158 * generation error to ask for the operand of ValueNode that doesn't have one yet. 159 * 160 * @param node A node that produces a result value. 161 */ 162 @Override 163 public Value operand(Node node) { 164 Value operand = getOperand(node); 165 assert operand != null : String.format("missing operand for %1s", node); 166 return operand; 167 } 168 169 @Override 170 public boolean hasOperand(Node node) { 171 return getOperand(node) != null; 172 } 334 AbstractMergeNode merge = (AbstractMergeNode) begin; 335 LabelOp label = (LabelOp) gen.getResult().getLIR().getLIRforBlock(block).get(0); 336 label.setPhiValues(createPhiIn(merge)); 337 if (Options.PrintIRWithLIR.getValue(options) && !TTY.isSuppressed()) { 338 TTY.println("Created PhiIn: " + label); 339 340 } 341 } 342 } 343 344 List<Node> nodes = blockMap.get(block); 345 346 // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups 347 // of instructions 348 matchComplexExpressions(nodes); 349 350 boolean trace = traceLIRGeneratorLevel >= 3; 351 for (int i = 0; i < nodes.size(); i++) { 352 Node node = nodes.get(i); 353 if (node instanceof ValueNode) { 354 ValueNode valueNode = (ValueNode) node; 355 if (trace) { 356 TTY.println("LIRGen for " + valueNode); 357 } 358 Value operand = getOperand(valueNode); 359 if (operand == null) { 360 if (!peephole(valueNode)) { 361 try { 362 doRoot(valueNode); 363 } catch (GraalError e) { 364 throw GraalGraphError.transformAndAddContext(e, valueNode); 365 } catch (Throwable e) { 366 throw new GraalGraphError(e).addContext(valueNode); 367 } 368 } 369 } else if (ComplexMatchValue.INTERIOR_MATCH.equals(operand)) { 370 // Doesn't need to be evaluated 371 Debug.log("interior match for %s", valueNode); 372 } else if (operand instanceof ComplexMatchValue) { 373 Debug.log("complex match for %s", valueNode); 374 ComplexMatchValue match = (ComplexMatchValue) operand; 375 operand = match.evaluate(this); 376 if (operand != null) { 377 setResult(valueNode, operand); 378 } 379 } else { 380 // There can be cases in which the result of an instruction is already set 381 // before by other instructions. 382 } 383 } 384 } 385 386 if (!gen.hasBlockEnd(block)) { 387 NodeIterable<Node> successors = block.getEndNode().successors(); 388 assert successors.count() == block.getSuccessorCount(); 389 if (block.getSuccessorCount() != 1) { 390 /* 391 * If we have more than one successor, we cannot just use the first one. Since 392 * successors are unordered, this would be a random choice. 393 */ 394 throw new GraalError("Block without BlockEndOp: " + block.getEndNode()); 395 } 396 gen.emitJump(getLIRBlock((FixedNode) successors.first())); 397 } 398 399 assert verifyBlock(gen.getResult().getLIR(), block); 400 } 401 } 402 403 @SuppressWarnings("try") 404 protected void matchComplexExpressions(List<Node> nodes) { 405 if (matchRules != null) { 406 try (Scope s = Debug.scope("MatchComplexExpressions")) { 407 if (LogVerbose.getValue(nodeOperands.graph().getOptions())) { 408 int i = 0; 409 for (Node node : nodes) { 410 Debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node); 411 } 412 } 413 414 // Match the nodes in backwards order to encourage longer matches. 415 for (int index = nodes.size() - 1; index >= 0; index--) { 416 Node node = nodes.get(index); 417 if (getOperand(node) != null) { 418 continue; 419 } 420 // See if this node is the root of any MatchStatements 421 List<MatchStatement> statements = matchRules.get(node.getClass()); 422 if (statements != null) { 423 for (MatchStatement statement : statements) { 424 if (statement.generate(this, index, node, nodes)) { 425 // Found a match so skip to the next 426 break; 427 } 428 } 429 } 430 } 431 } 432 } 433 } 434 435 protected abstract boolean peephole(ValueNode valueNode); 436 437 private void doRoot(ValueNode instr) { 438 if (traceLIRGeneratorLevel >= 2) { 439 TTY.println("Emitting LIR for instruction " + instr); 440 } 441 currentInstruction = instr; 442 443 Debug.log("Visiting %s", instr); 444 emitNode(instr); 445 Debug.log("Operand for %s = %s", instr, getOperand(instr)); 446 } 447 448 protected void emitNode(ValueNode node) { 449 if (Debug.isLogEnabled() && node.stamp().isEmpty()) { 450 Debug.log("This node has an empty stamp, we are emitting dead code(?): %s", node); 451 } 452 setSourcePosition(node.getNodeSourcePosition()); 453 if (node instanceof LIRLowerable) { 454 ((LIRLowerable) node).generate(this); 455 } else { 456 throw GraalError.shouldNotReachHere("node is not LIRLowerable: " + node); 457 } 458 } 459 460 protected void emitPrologue(StructuredGraph graph) { 461 CallingConvention incomingArguments = gen.getResult().getCallingConvention(); 462 463 Value[] params = new Value[incomingArguments.getArgumentCount()]; 464 for (int i = 0; i < params.length; i++) { 465 params[i] = incomingArguments.getArgument(i); 466 if (ValueUtil.isStackSlot(params[i])) { 467 StackSlot slot = ValueUtil.asStackSlot(params[i]); 468 if (slot.isInCallerFrame() && !gen.getResult().getLIR().hasArgInCallerFrame()) { 469 gen.getResult().getLIR().setHasArgInCallerFrame(); 470 } | 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 org.graalvm.compiler.core.gen; 24 25 import static jdk.vm.ci.code.ValueUtil.asRegister; 26 import static jdk.vm.ci.code.ValueUtil.isLegal; 27 import static jdk.vm.ci.code.ValueUtil.isRegister; 28 import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; 29 import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; 30 import static org.graalvm.compiler.lir.LIR.verifyBlock; 31 32 import java.util.ArrayList; 33 import java.util.Collection; 34 import java.util.List; 35 36 import org.graalvm.compiler.core.common.LIRKind; 37 import org.graalvm.compiler.core.common.calc.Condition; 38 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 39 import org.graalvm.compiler.core.common.cfg.BlockMap; 40 import org.graalvm.compiler.core.common.type.Stamp; 41 import org.graalvm.compiler.core.match.ComplexMatchValue; 42 import org.graalvm.compiler.core.match.MatchPattern; 43 import org.graalvm.compiler.core.match.MatchRuleRegistry; 44 import org.graalvm.compiler.core.match.MatchStatement; 45 import org.graalvm.compiler.debug.DebugContext; 46 import org.graalvm.compiler.debug.GraalError; 47 import org.graalvm.compiler.debug.TTY; 48 import org.graalvm.compiler.graph.GraalGraphError; 49 import org.graalvm.compiler.graph.Node; 50 import org.graalvm.compiler.graph.NodeMap; 51 import org.graalvm.compiler.graph.NodeSourcePosition; 52 import org.graalvm.compiler.graph.iterators.NodeIterable; 53 import org.graalvm.compiler.lir.FullInfopointOp; 54 import org.graalvm.compiler.lir.LIRFrameState; 55 import org.graalvm.compiler.lir.LIRInstruction; 56 import org.graalvm.compiler.lir.LabelRef; 57 import org.graalvm.compiler.lir.StandardOp.JumpOp; 58 import org.graalvm.compiler.lir.StandardOp.LabelOp; 59 import org.graalvm.compiler.lir.SwitchStrategy; 60 import org.graalvm.compiler.lir.Variable; 61 import org.graalvm.compiler.lir.debug.LIRGenerationDebugContext; 62 import org.graalvm.compiler.lir.gen.LIRGenerator; 63 import org.graalvm.compiler.lir.gen.LIRGenerator.Options; 64 import org.graalvm.compiler.lir.gen.LIRGeneratorTool; 65 import org.graalvm.compiler.lir.gen.LIRGeneratorTool.BlockScope; 118 119 private final NodeMap<Value> nodeOperands; 120 private final DebugInfoBuilder debugInfoBuilder; 121 private final int traceLIRGeneratorLevel; 122 123 protected final LIRGenerator gen; 124 125 private ValueNode currentInstruction; 126 private ValueNode lastInstructionPrinted; // Debugging only 127 128 private final NodeMatchRules nodeMatchRules; 129 private EconomicMap<Class<? extends Node>, List<MatchStatement>> matchRules; 130 131 public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, NodeMatchRules nodeMatchRules) { 132 this.gen = (LIRGenerator) gen; 133 this.nodeMatchRules = nodeMatchRules; 134 this.nodeOperands = graph.createNodeMap(); 135 this.debugInfoBuilder = createDebugInfoBuilder(graph, this); 136 OptionValues options = graph.getOptions(); 137 if (MatchExpressions.getValue(options)) { 138 matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass(), options, graph.getDebug()); 139 } 140 traceLIRGeneratorLevel = TTY.isSuppressed() ? 0 : Options.TraceLIRGeneratorLevel.getValue(options); 141 142 assert nodeMatchRules.lirBuilder == null; 143 nodeMatchRules.lirBuilder = this; 144 } 145 146 public NodeMatchRules getNodeMatchRules() { 147 return nodeMatchRules; 148 } 149 150 protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { 151 return new DebugInfoBuilder(nodeValueMap, graph.getDebug()); 152 } 153 154 /** 155 * Returns the operand that has been previously initialized by 156 * {@link #setResult(ValueNode, Value)} with the result of an instruction. It's a code 157 * generation error to ask for the operand of ValueNode that doesn't have one yet. 158 * 159 * @param node A node that produces a result value. 160 */ 161 @Override 162 public Value operand(Node node) { 163 Value operand = getOperand(node); 164 assert operand != null : String.format("missing operand for %1s", node); 165 return operand; 166 } 167 168 @Override 169 public boolean hasOperand(Node node) { 170 return getOperand(node) != null; 171 } 333 AbstractMergeNode merge = (AbstractMergeNode) begin; 334 LabelOp label = (LabelOp) gen.getResult().getLIR().getLIRforBlock(block).get(0); 335 label.setPhiValues(createPhiIn(merge)); 336 if (Options.PrintIRWithLIR.getValue(options) && !TTY.isSuppressed()) { 337 TTY.println("Created PhiIn: " + label); 338 339 } 340 } 341 } 342 343 List<Node> nodes = blockMap.get(block); 344 345 // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups 346 // of instructions 347 matchComplexExpressions(nodes); 348 349 boolean trace = traceLIRGeneratorLevel >= 3; 350 for (int i = 0; i < nodes.size(); i++) { 351 Node node = nodes.get(i); 352 if (node instanceof ValueNode) { 353 DebugContext debug = node.getDebug(); 354 ValueNode valueNode = (ValueNode) node; 355 if (trace) { 356 TTY.println("LIRGen for " + valueNode); 357 } 358 Value operand = getOperand(valueNode); 359 if (operand == null) { 360 if (!peephole(valueNode)) { 361 try { 362 doRoot(valueNode); 363 } catch (GraalError e) { 364 throw GraalGraphError.transformAndAddContext(e, valueNode); 365 } catch (Throwable e) { 366 throw new GraalGraphError(e).addContext(valueNode); 367 } 368 } 369 } else if (ComplexMatchValue.INTERIOR_MATCH.equals(operand)) { 370 // Doesn't need to be evaluated 371 debug.log("interior match for %s", valueNode); 372 } else if (operand instanceof ComplexMatchValue) { 373 debug.log("complex match for %s", valueNode); 374 ComplexMatchValue match = (ComplexMatchValue) operand; 375 operand = match.evaluate(this); 376 if (operand != null) { 377 setResult(valueNode, operand); 378 } 379 } else { 380 // There can be cases in which the result of an instruction is already set 381 // before by other instructions. 382 } 383 } 384 } 385 386 if (!gen.hasBlockEnd(block)) { 387 NodeIterable<Node> successors = block.getEndNode().successors(); 388 assert successors.count() == block.getSuccessorCount(); 389 if (block.getSuccessorCount() != 1) { 390 /* 391 * If we have more than one successor, we cannot just use the first one. Since 392 * successors are unordered, this would be a random choice. 393 */ 394 throw new GraalError("Block without BlockEndOp: " + block.getEndNode()); 395 } 396 gen.emitJump(getLIRBlock((FixedNode) successors.first())); 397 } 398 399 assert verifyBlock(gen.getResult().getLIR(), block); 400 } 401 } 402 403 @SuppressWarnings("try") 404 protected void matchComplexExpressions(List<Node> nodes) { 405 if (matchRules != null) { 406 DebugContext debug = gen.getResult().getLIR().getDebug(); 407 try (DebugContext.Scope s = debug.scope("MatchComplexExpressions")) { 408 if (LogVerbose.getValue(nodeOperands.graph().getOptions())) { 409 int i = 0; 410 for (Node node : nodes) { 411 debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node); 412 } 413 } 414 415 // Match the nodes in backwards order to encourage longer matches. 416 for (int index = nodes.size() - 1; index >= 0; index--) { 417 Node node = nodes.get(index); 418 if (getOperand(node) != null) { 419 continue; 420 } 421 // See if this node is the root of any MatchStatements 422 List<MatchStatement> statements = matchRules.get(node.getClass()); 423 if (statements != null) { 424 for (MatchStatement statement : statements) { 425 if (statement.generate(this, index, node, nodes)) { 426 // Found a match so skip to the next 427 break; 428 } 429 } 430 } 431 } 432 } 433 } 434 } 435 436 protected abstract boolean peephole(ValueNode valueNode); 437 438 private void doRoot(ValueNode instr) { 439 if (traceLIRGeneratorLevel >= 2) { 440 TTY.println("Emitting LIR for instruction " + instr); 441 } 442 currentInstruction = instr; 443 DebugContext debug = instr.getDebug(); 444 debug.log("Visiting %s", instr); 445 emitNode(instr); 446 debug.log("Operand for %s = %s", instr, getOperand(instr)); 447 } 448 449 protected void emitNode(ValueNode node) { 450 if (node.getDebug().isLogEnabled() && node.stamp().isEmpty()) { 451 node.getDebug().log("This node has an empty stamp, we are emitting dead code(?): %s", node); 452 } 453 setSourcePosition(node.getNodeSourcePosition()); 454 if (node instanceof LIRLowerable) { 455 ((LIRLowerable) node).generate(this); 456 } else { 457 throw GraalError.shouldNotReachHere("node is not LIRLowerable: " + node); 458 } 459 } 460 461 protected void emitPrologue(StructuredGraph graph) { 462 CallingConvention incomingArguments = gen.getResult().getCallingConvention(); 463 464 Value[] params = new Value[incomingArguments.getArgumentCount()]; 465 for (int i = 0; i < params.length; i++) { 466 params[i] = incomingArguments.getArgument(i); 467 if (ValueUtil.isStackSlot(params[i])) { 468 StackSlot slot = ValueUtil.asStackSlot(params[i]); 469 if (slot.isInCallerFrame() && !gen.getResult().getLIR().hasArgInCallerFrame()) { 470 gen.getResult().getLIR().setHasArgInCallerFrame(); 471 } |