31 import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.Options.MitigateSpeculativeExecutionAttacks;
32 import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions;
33 import static org.graalvm.compiler.debug.DebugOptions.LogVerbose;
34 import static org.graalvm.compiler.lir.LIR.verifyBlock;
35
36 import java.util.ArrayList;
37 import java.util.Collection;
38 import java.util.List;
39
40 import jdk.internal.vm.compiler.collections.EconomicMap;
41 import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
42 import org.graalvm.compiler.core.common.LIRKind;
43 import org.graalvm.compiler.core.common.calc.Condition;
44 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
45 import org.graalvm.compiler.core.common.cfg.BlockMap;
46 import org.graalvm.compiler.core.common.type.Stamp;
47 import org.graalvm.compiler.core.match.ComplexMatchValue;
48 import org.graalvm.compiler.core.match.MatchPattern;
49 import org.graalvm.compiler.core.match.MatchRuleRegistry;
50 import org.graalvm.compiler.core.match.MatchStatement;
51 import org.graalvm.compiler.debug.DebugContext;
52 import org.graalvm.compiler.debug.GraalError;
53 import org.graalvm.compiler.debug.TTY;
54 import org.graalvm.compiler.graph.GraalGraphError;
55 import org.graalvm.compiler.graph.Node;
56 import org.graalvm.compiler.graph.NodeMap;
57 import org.graalvm.compiler.graph.NodeSourcePosition;
58 import org.graalvm.compiler.graph.iterators.NodeIterable;
59 import org.graalvm.compiler.lir.FullInfopointOp;
60 import org.graalvm.compiler.lir.LIRFrameState;
61 import org.graalvm.compiler.lir.LIRInstruction;
62 import org.graalvm.compiler.lir.LabelRef;
63 import org.graalvm.compiler.lir.StandardOp.JumpOp;
64 import org.graalvm.compiler.lir.StandardOp.LabelOp;
65 import org.graalvm.compiler.lir.SwitchStrategy;
66 import org.graalvm.compiler.lir.Variable;
67 import org.graalvm.compiler.lir.debug.LIRGenerationDebugContext;
68 import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
69 import org.graalvm.compiler.lir.gen.LIRGenerator;
70 import org.graalvm.compiler.lir.gen.LIRGenerator.Options;
238 public final void append(LIRInstruction op) {
239 if (Options.PrintIRWithLIR.getValue(nodeOperands.graph().getOptions()) && !TTY.isSuppressed()) {
240 if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
241 lastInstructionPrinted = currentInstruction;
242 InstructionPrinter ip = new InstructionPrinter(TTY.out());
243 ip.printInstructionListing(currentInstruction);
244 }
245 }
246 gen.append(op);
247 }
248
249 protected LIRKind getExactPhiKind(PhiNode phi) {
250 LIRKind derivedKind = gen.toRegisterKind(gen.getLIRKind(phi.stamp(NodeView.DEFAULT)));
251 /* Collect reference information. */
252 for (int i = 0; i < phi.valueCount() && !derivedKind.isUnknownReference(); i++) {
253 ValueNode node = phi.valueAt(i);
254 Value value = getOperand(node);
255
256 // get ValueKind for input
257 final LIRKind valueKind;
258 if (value != null) {
259 valueKind = value.getValueKind(LIRKind.class);
260 } else {
261 assert isPhiInputFromBackedge(phi, i) : String.format("Input %s to phi node %s is not yet available although it is not coming from a loop back edge", node, phi);
262 LIRKind kind = gen.getLIRKind(node.stamp(NodeView.DEFAULT));
263 valueKind = gen.toRegisterKind(kind);
264 }
265 /* Merge the reference information of the derived kind and the input. */
266 derivedKind = LIRKind.mergeReferenceInformation(derivedKind, valueKind);
267 }
268 return derivedKind;
269 }
270
271 private static boolean isPhiInputFromBackedge(PhiNode phi, int index) {
272 AbstractMergeNode merge = phi.merge();
273 AbstractEndNode end = merge.phiPredecessorAt(index);
274 return end instanceof LoopEndNode && ((LoopEndNode) end).loopBegin().equals(merge);
275 }
276
277 private Value[] createPhiIn(AbstractMergeNode merge) {
278 List<Value> values = new ArrayList<>();
341 assert block.getPredecessorCount() == 0;
342 emitPrologue(graph);
343 } else {
344 assert block.getPredecessorCount() > 0;
345 // create phi-in value array
346 AbstractBeginNode begin = block.getBeginNode();
347 if (begin instanceof AbstractMergeNode) {
348 AbstractMergeNode merge = (AbstractMergeNode) begin;
349 LabelOp label = (LabelOp) gen.getResult().getLIR().getLIRforBlock(block).get(0);
350 label.setPhiValues(createPhiIn(merge));
351 if (Options.PrintIRWithLIR.getValue(options) && !TTY.isSuppressed()) {
352 TTY.println("Created PhiIn: " + label);
353
354 }
355 }
356 }
357 doBlockPrologue(block, options);
358
359 List<Node> nodes = blockMap.get(block);
360
361 // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups
362 // of instructions
363 matchComplexExpressions(nodes);
364
365 boolean trace = traceLIRGeneratorLevel >= 3;
366 for (int i = 0; i < nodes.size(); i++) {
367 Node node = nodes.get(i);
368 if (node instanceof ValueNode) {
369 setSourcePosition(node.getNodeSourcePosition());
370 DebugContext debug = node.getDebug();
371 ValueNode valueNode = (ValueNode) node;
372 if (trace) {
373 TTY.println("LIRGen for " + valueNode);
374 }
375 Value operand = getOperand(valueNode);
376 if (operand == null) {
377 if (!peephole(valueNode)) {
378 try {
379 doRoot(valueNode);
380 } catch (GraalError e) {
381 throw GraalGraphError.transformAndAddContext(e, valueNode);
382 } catch (Throwable e) {
383 throw new GraalGraphError(e).addContext(valueNode);
384 }
402 }
403 }
404
405 if (!gen.hasBlockEnd(block)) {
406 NodeIterable<Node> successors = block.getEndNode().successors();
407 assert successors.count() == block.getSuccessorCount();
408 if (block.getSuccessorCount() != 1) {
409 /*
410 * If we have more than one successor, we cannot just use the first one. Since
411 * successors are unordered, this would be a random choice.
412 */
413 throw new GraalError("Block without BlockEndOp: " + block.getEndNode());
414 }
415 gen.emitJump(getLIRBlock((FixedNode) successors.first()));
416 }
417
418 assert verifyBlock(gen.getResult().getLIR(), block);
419 }
420 }
421
422 @SuppressWarnings("try")
423 protected void matchComplexExpressions(List<Node> nodes) {
424 if (matchRules != null) {
425 DebugContext debug = gen.getResult().getLIR().getDebug();
426 try (DebugContext.Scope s = debug.scope("MatchComplexExpressions")) {
427 if (LogVerbose.getValue(nodeOperands.graph().getOptions())) {
428 int i = 0;
429 for (Node node : nodes) {
430 debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node);
431 }
432 }
433
434 // Match the nodes in backwards order to encourage longer matches.
435 for (int index = nodes.size() - 1; index >= 0; index--) {
436 Node node = nodes.get(index);
437 if (getOperand(node) != null) {
438 continue;
439 }
440 // See if this node is the root of any MatchStatements
441 List<MatchStatement> statements = matchRules.get(node.getClass());
442 if (statements != null) {
443 for (MatchStatement statement : statements) {
444 if (statement.generate(this, index, node, nodes)) {
445 // Found a match so skip to the next
446 break;
447 }
448 }
449 }
450 }
451 }
452 }
453 }
454
455 protected abstract boolean peephole(ValueNode valueNode);
456
457 private void doRoot(ValueNode instr) {
458 if (traceLIRGeneratorLevel >= 2) {
459 TTY.println("Emitting LIR for instruction " + instr);
460 }
461 currentInstruction = instr;
462 DebugContext debug = instr.getDebug();
463 debug.log("Visiting %s", instr);
464 emitNode(instr);
|
31 import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.Options.MitigateSpeculativeExecutionAttacks;
32 import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions;
33 import static org.graalvm.compiler.debug.DebugOptions.LogVerbose;
34 import static org.graalvm.compiler.lir.LIR.verifyBlock;
35
36 import java.util.ArrayList;
37 import java.util.Collection;
38 import java.util.List;
39
40 import jdk.internal.vm.compiler.collections.EconomicMap;
41 import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
42 import org.graalvm.compiler.core.common.LIRKind;
43 import org.graalvm.compiler.core.common.calc.Condition;
44 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
45 import org.graalvm.compiler.core.common.cfg.BlockMap;
46 import org.graalvm.compiler.core.common.type.Stamp;
47 import org.graalvm.compiler.core.match.ComplexMatchValue;
48 import org.graalvm.compiler.core.match.MatchPattern;
49 import org.graalvm.compiler.core.match.MatchRuleRegistry;
50 import org.graalvm.compiler.core.match.MatchStatement;
51 import org.graalvm.compiler.debug.DebugCloseable;
52 import org.graalvm.compiler.debug.DebugContext;
53 import org.graalvm.compiler.debug.GraalError;
54 import org.graalvm.compiler.debug.TTY;
55 import org.graalvm.compiler.graph.GraalGraphError;
56 import org.graalvm.compiler.graph.Node;
57 import org.graalvm.compiler.graph.NodeMap;
58 import org.graalvm.compiler.graph.NodeSourcePosition;
59 import org.graalvm.compiler.graph.iterators.NodeIterable;
60 import org.graalvm.compiler.lir.FullInfopointOp;
61 import org.graalvm.compiler.lir.LIRFrameState;
62 import org.graalvm.compiler.lir.LIRInstruction;
63 import org.graalvm.compiler.lir.LabelRef;
64 import org.graalvm.compiler.lir.StandardOp.JumpOp;
65 import org.graalvm.compiler.lir.StandardOp.LabelOp;
66 import org.graalvm.compiler.lir.SwitchStrategy;
67 import org.graalvm.compiler.lir.Variable;
68 import org.graalvm.compiler.lir.debug.LIRGenerationDebugContext;
69 import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
70 import org.graalvm.compiler.lir.gen.LIRGenerator;
71 import org.graalvm.compiler.lir.gen.LIRGenerator.Options;
239 public final void append(LIRInstruction op) {
240 if (Options.PrintIRWithLIR.getValue(nodeOperands.graph().getOptions()) && !TTY.isSuppressed()) {
241 if (currentInstruction != null && lastInstructionPrinted != currentInstruction) {
242 lastInstructionPrinted = currentInstruction;
243 InstructionPrinter ip = new InstructionPrinter(TTY.out());
244 ip.printInstructionListing(currentInstruction);
245 }
246 }
247 gen.append(op);
248 }
249
250 protected LIRKind getExactPhiKind(PhiNode phi) {
251 LIRKind derivedKind = gen.toRegisterKind(gen.getLIRKind(phi.stamp(NodeView.DEFAULT)));
252 /* Collect reference information. */
253 for (int i = 0; i < phi.valueCount() && !derivedKind.isUnknownReference(); i++) {
254 ValueNode node = phi.valueAt(i);
255 Value value = getOperand(node);
256
257 // get ValueKind for input
258 final LIRKind valueKind;
259 if (value != null && !(value instanceof ComplexMatchValue)) {
260 valueKind = value.getValueKind(LIRKind.class);
261 } else {
262 assert isPhiInputFromBackedge(phi, i) : String.format("Input %s to phi node %s is not yet available although it is not coming from a loop back edge", node, phi);
263 LIRKind kind = gen.getLIRKind(node.stamp(NodeView.DEFAULT));
264 valueKind = gen.toRegisterKind(kind);
265 }
266 /* Merge the reference information of the derived kind and the input. */
267 derivedKind = LIRKind.mergeReferenceInformation(derivedKind, valueKind);
268 }
269 return derivedKind;
270 }
271
272 private static boolean isPhiInputFromBackedge(PhiNode phi, int index) {
273 AbstractMergeNode merge = phi.merge();
274 AbstractEndNode end = merge.phiPredecessorAt(index);
275 return end instanceof LoopEndNode && ((LoopEndNode) end).loopBegin().equals(merge);
276 }
277
278 private Value[] createPhiIn(AbstractMergeNode merge) {
279 List<Value> values = new ArrayList<>();
342 assert block.getPredecessorCount() == 0;
343 emitPrologue(graph);
344 } else {
345 assert block.getPredecessorCount() > 0;
346 // create phi-in value array
347 AbstractBeginNode begin = block.getBeginNode();
348 if (begin instanceof AbstractMergeNode) {
349 AbstractMergeNode merge = (AbstractMergeNode) begin;
350 LabelOp label = (LabelOp) gen.getResult().getLIR().getLIRforBlock(block).get(0);
351 label.setPhiValues(createPhiIn(merge));
352 if (Options.PrintIRWithLIR.getValue(options) && !TTY.isSuppressed()) {
353 TTY.println("Created PhiIn: " + label);
354
355 }
356 }
357 }
358 doBlockPrologue(block, options);
359
360 List<Node> nodes = blockMap.get(block);
361
362 boolean trace = traceLIRGeneratorLevel >= 3;
363 for (int i = 0; i < nodes.size(); i++) {
364 Node node = nodes.get(i);
365 if (node instanceof ValueNode) {
366 setSourcePosition(node.getNodeSourcePosition());
367 DebugContext debug = node.getDebug();
368 ValueNode valueNode = (ValueNode) node;
369 if (trace) {
370 TTY.println("LIRGen for " + valueNode);
371 }
372 Value operand = getOperand(valueNode);
373 if (operand == null) {
374 if (!peephole(valueNode)) {
375 try {
376 doRoot(valueNode);
377 } catch (GraalError e) {
378 throw GraalGraphError.transformAndAddContext(e, valueNode);
379 } catch (Throwable e) {
380 throw new GraalGraphError(e).addContext(valueNode);
381 }
399 }
400 }
401
402 if (!gen.hasBlockEnd(block)) {
403 NodeIterable<Node> successors = block.getEndNode().successors();
404 assert successors.count() == block.getSuccessorCount();
405 if (block.getSuccessorCount() != 1) {
406 /*
407 * If we have more than one successor, we cannot just use the first one. Since
408 * successors are unordered, this would be a random choice.
409 */
410 throw new GraalError("Block without BlockEndOp: " + block.getEndNode());
411 }
412 gen.emitJump(getLIRBlock((FixedNode) successors.first()));
413 }
414
415 assert verifyBlock(gen.getResult().getLIR(), block);
416 }
417 }
418
419 @Override
420 @SuppressWarnings("try")
421 public void matchBlock(Block block, StructuredGraph graph, StructuredGraph.ScheduleResult schedule) {
422 try (DebugCloseable matchScope = gen.getMatchScope(block)) {
423 // Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups
424 // of instructions
425 matchComplexExpressions(block, schedule);
426 }
427 }
428
429 @SuppressWarnings("try")
430 protected void matchComplexExpressions(Block block, StructuredGraph.ScheduleResult schedule) {
431
432 if (matchRules != null) {
433 DebugContext debug = gen.getResult().getLIR().getDebug();
434 try (DebugContext.Scope s = debug.scope("MatchComplexExpressions")) {
435 List<Node> nodes = schedule.getBlockToNodesMap().get(block);
436 if (LogVerbose.getValue(nodeOperands.graph().getOptions())) {
437 int i = 0;
438 for (Node node : nodes) {
439 debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node);
440 }
441 }
442
443 // Match the nodes in backwards order to encourage longer matches.
444 for (int index = nodes.size() - 1; index >= 0; index--) {
445 Node node = nodes.get(index);
446 if (getOperand(node) != null) {
447 continue;
448 }
449 // See if this node is the root of any MatchStatements
450 List<MatchStatement> statements = matchRules.get(node.getClass());
451 if (statements != null) {
452 for (MatchStatement statement : statements) {
453 if (statement.generate(this, index, node, block, schedule)) {
454 // Found a match so skip to the next
455 break;
456 }
457 }
458 }
459 }
460 }
461 }
462 }
463
464 protected abstract boolean peephole(ValueNode valueNode);
465
466 private void doRoot(ValueNode instr) {
467 if (traceLIRGeneratorLevel >= 2) {
468 TTY.println("Emitting LIR for instruction " + instr);
469 }
470 currentInstruction = instr;
471 DebugContext debug = instr.getDebug();
472 debug.log("Visiting %s", instr);
473 emitNode(instr);
|