src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java

Print this page




   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                 }


src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File