use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class NodeLIRBuilder method doBlock.
@Override
@SuppressWarnings("try")
public void doBlock(Block block, StructuredGraph graph, BlockMap<List<Node>> blockMap) {
OptionValues options = graph.getOptions();
try (BlockScope blockScope = gen.getBlockScope(block)) {
setSourcePosition(null);
if (block == gen.getResult().getLIR().getControlFlowGraph().getStartBlock()) {
assert block.getPredecessorCount() == 0;
emitPrologue(graph);
} else {
assert block.getPredecessorCount() > 0;
// create phi-in value array
AbstractBeginNode begin = block.getBeginNode();
if (begin instanceof AbstractMergeNode) {
AbstractMergeNode merge = (AbstractMergeNode) begin;
LabelOp label = (LabelOp) gen.getResult().getLIR().getLIRforBlock(block).get(0);
label.setPhiValues(createPhiIn(merge));
if (Options.PrintIRWithLIR.getValue(options) && !TTY.isSuppressed()) {
TTY.println("Created PhiIn: " + label);
}
}
}
doBlockPrologue(block, options);
List<Node> nodes = blockMap.get(block);
// Allow NodeLIRBuilder subclass to specialize code generation of any interesting groups
// of instructions
matchComplexExpressions(nodes);
boolean trace = traceLIRGeneratorLevel >= 3;
for (int i = 0; i < nodes.size(); i++) {
Node node = nodes.get(i);
if (node instanceof ValueNode) {
DebugContext debug = node.getDebug();
ValueNode valueNode = (ValueNode) node;
if (trace) {
TTY.println("LIRGen for " + valueNode);
}
Value operand = getOperand(valueNode);
if (operand == null) {
if (!peephole(valueNode)) {
try {
doRoot(valueNode);
} catch (GraalError e) {
throw GraalGraphError.transformAndAddContext(e, valueNode);
} catch (Throwable e) {
throw new GraalGraphError(e).addContext(valueNode);
}
}
} else if (ComplexMatchValue.INTERIOR_MATCH.equals(operand)) {
// Doesn't need to be evaluated
debug.log("interior match for %s", valueNode);
} else if (operand instanceof ComplexMatchValue) {
debug.log("complex match for %s", valueNode);
ComplexMatchValue match = (ComplexMatchValue) operand;
operand = match.evaluate(this);
if (operand != null) {
setResult(valueNode, operand);
}
} else {
// There can be cases in which the result of an instruction is already set
// before by other instructions.
}
}
}
if (!gen.hasBlockEnd(block)) {
NodeIterable<Node> successors = block.getEndNode().successors();
assert successors.count() == block.getSuccessorCount();
if (block.getSuccessorCount() != 1) {
/*
* If we have more than one successor, we cannot just use the first one. Since
* successors are unordered, this would be a random choice.
*/
throw new GraalError("Block without BlockEndOp: " + block.getEndNode());
}
gen.emitJump(getLIRBlock((FixedNode) successors.first()));
}
assert verifyBlock(gen.getResult().getLIR(), block);
}
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class LoopTransformations method insertPrePostLoops.
// This function splits candidate loops into pre, main and post loops,
// dividing the iteration space to facilitate the majority of iterations
// being executed in a main loop, which will have RCE implemented upon it.
// The initial loop form is constrained to single entry/exit, but can have
// flow. The translation looks like:
//
// @formatter:off
//
// (Simple Loop entry) (Pre Loop Entry)
// | |
// (LoopBeginNode) (LoopBeginNode)
// | |
// (Loop Control Test)<------ ==> (Loop control Test)<------
// / \ \ / \ \
// (Loop Exit) (Loop Body) | (Loop Exit) (Loop Body) |
// | | | | | |
// (continue code) (Loop End) | if (M < length)* (Loop End) |
// \ / / \ \ /
// -----> / | ----->
// / if ( ... )*
// / / \
// / / \
// / / \
// | / (Main Loop Entry)
// | | |
// | | (LoopBeginNode)
// | | |
// | | (Loop Control Test)<------
// | | / \ \
// | | (Loop Exit) (Loop Body) |
// \ \ | | |
// \ \ | (Loop End) |
// \ \ | \ /
// \ \ | ------>
// \ \ |
// (Main Loop Merge)*
// |
// (Post Loop Entry)
// |
// (LoopBeginNode)
// |
// (Loop Control Test)<-----
// / \ \
// (Loop Exit) (Loop Body) |
// | | |
// (continue code) (Loop End) |
// \ /
// ----->
//
// Key: "*" = optional.
// @formatter:on
//
// The value "M" is the maximal value of the loop trip for the original
// loop. The value of "length" is applicable to the number of arrays found
// in the loop but is reduced if some or all of the arrays are known to be
// the same length as "M". The maximum number of tests can be equal to the
// number of arrays in the loop, where multiple instances of an array are
// subsumed into a single test for that arrays length.
//
// If the optional main loop entry tests are absent, the Pre Loop exit
// connects to the Main loops entry and there is no merge hanging off the
// main loops exit to converge flow from said tests. All split use data
// flow is mitigated through phi(s) in the main merge if present and
// passed through the main and post loop phi(s) from the originating pre
// loop with final phi(s) and data flow patched to the "continue code".
// The pre loop is constrained to one iteration for now and will likely
// be updated to produce vector alignment if applicable.
public static LoopBeginNode insertPrePostLoops(LoopEx loop) {
StructuredGraph graph = loop.loopBegin().graph();
graph.getDebug().log("LoopTransformations.insertPrePostLoops %s", loop);
LoopFragmentWhole preLoop = loop.whole();
CountedLoopInfo preCounted = loop.counted();
IfNode preLimit = preCounted.getLimitTest();
assert preLimit != null;
LoopBeginNode preLoopBegin = loop.loopBegin();
InductionVariable preIv = preCounted.getCounter();
LoopExitNode preLoopExitNode = preLoopBegin.getSingleLoopExit();
FixedNode continuationNode = preLoopExitNode.next();
// Each duplication is inserted after the original, ergo create the post loop first
LoopFragmentWhole mainLoop = preLoop.duplicate();
LoopFragmentWhole postLoop = preLoop.duplicate();
preLoopBegin.incrementSplits();
preLoopBegin.incrementSplits();
preLoopBegin.setPreLoop();
graph.getDebug().dump(DebugContext.VERBOSE_LEVEL, graph, "After duplication");
LoopBeginNode mainLoopBegin = mainLoop.getDuplicatedNode(preLoopBegin);
mainLoopBegin.setMainLoop();
LoopBeginNode postLoopBegin = postLoop.getDuplicatedNode(preLoopBegin);
postLoopBegin.setPostLoop();
EndNode postEndNode = getBlockEndAfterLoopExit(postLoopBegin);
AbstractMergeNode postMergeNode = postEndNode.merge();
LoopExitNode postLoopExitNode = postLoopBegin.getSingleLoopExit();
// Update the main loop phi initialization to carry from the pre loop
for (PhiNode prePhiNode : preLoopBegin.phis()) {
PhiNode mainPhiNode = mainLoop.getDuplicatedNode(prePhiNode);
mainPhiNode.setValueAt(0, prePhiNode);
}
EndNode mainEndNode = getBlockEndAfterLoopExit(mainLoopBegin);
AbstractMergeNode mainMergeNode = mainEndNode.merge();
AbstractEndNode postEntryNode = postLoopBegin.forwardEnd();
// In the case of no Bounds tests, we just flow right into the main loop
AbstractBeginNode mainLandingNode = BeginNode.begin(postEntryNode);
LoopExitNode mainLoopExitNode = mainLoopBegin.getSingleLoopExit();
mainLoopExitNode.setNext(mainLandingNode);
preLoopExitNode.setNext(mainLoopBegin.forwardEnd());
// Add and update any phi edges as per merge usage as needed and update usages
processPreLoopPhis(loop, mainLoop, postLoop);
continuationNode.predecessor().clearSuccessors();
postLoopExitNode.setNext(continuationNode);
cleanupMerge(postMergeNode, postLoopExitNode);
cleanupMerge(mainMergeNode, mainLandingNode);
// Change the preLoop to execute one iteration for now
updateMainLoopLimit(preLimit, preIv, mainLoop);
updatePreLoopLimit(preLimit, preIv, preCounted);
preLoopBegin.setLoopFrequency(1);
mainLoopBegin.setLoopFrequency(Math.max(0.0, mainLoopBegin.loopFrequency() - 2));
postLoopBegin.setLoopFrequency(Math.max(0.0, postLoopBegin.loopFrequency() - 1));
// The pre and post loops don't require safepoints at all
for (SafepointNode safepoint : preLoop.nodes().filter(SafepointNode.class)) {
graph.removeFixed(safepoint);
}
for (SafepointNode safepoint : postLoop.nodes().filter(SafepointNode.class)) {
graph.removeFixed(safepoint);
}
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "InsertPrePostLoops %s", loop);
return mainLoopBegin;
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class WriteBarrierVerificationTest method testPredicate.
@SuppressWarnings("try")
private void testPredicate(final String snippet, final GraphPredicate expectedBarriers, final int... removedBarrierIndices) {
DebugContext debug = getDebugContext();
try (DebugCloseable d = debug.disableIntercept();
DebugContext.Scope s = debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) {
final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug);
HighTierContext highTierContext = getDefaultHighTierContext();
new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext);
MidTierContext midTierContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo());
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext);
new GuardLoweringPhase().apply(graph, midTierContext);
new LoopSafepointInsertionPhase().apply(graph);
new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, highTierContext);
new WriteBarrierAdditionPhase(config).apply(graph);
int barriers = 0;
// First, the total number of expected barriers is checked.
if (config.useG1GC) {
barriers = graph.getNodes().filter(G1PreWriteBarrier.class).count() + graph.getNodes().filter(G1PostWriteBarrier.class).count() + graph.getNodes().filter(G1ArrayRangePreWriteBarrier.class).count() + graph.getNodes().filter(G1ArrayRangePostWriteBarrier.class).count();
Assert.assertTrue(expectedBarriers.apply(graph) * 2 == barriers);
} else {
barriers = graph.getNodes().filter(SerialWriteBarrier.class).count() + graph.getNodes().filter(SerialArrayRangeWriteBarrier.class).count();
Assert.assertTrue(expectedBarriers.apply(graph) == barriers);
}
ResolvedJavaField barrierIndexField = getMetaAccess().lookupJavaField(WriteBarrierVerificationTest.class.getDeclaredField("barrierIndex"));
LocationIdentity barrierIdentity = new FieldLocationIdentity(barrierIndexField);
// Iterate over all write nodes and remove barriers according to input indices.
NodeIteratorClosure<Boolean> closure = new NodeIteratorClosure<Boolean>() {
@Override
protected Boolean processNode(FixedNode node, Boolean currentState) {
if (node instanceof WriteNode) {
WriteNode write = (WriteNode) node;
LocationIdentity obj = write.getLocationIdentity();
if (obj.equals(barrierIdentity)) {
/*
* A "barrierIndex" variable was found and is checked against the input
* barrier array.
*/
if (eliminateBarrier(write.value().asJavaConstant().asInt(), removedBarrierIndices)) {
return true;
}
}
} else if (node instanceof SerialWriteBarrier || node instanceof G1PostWriteBarrier) {
// Remove flagged write barriers.
if (currentState) {
graph.removeFixed(((FixedWithNextNode) node));
return false;
}
}
return currentState;
}
private boolean eliminateBarrier(int index, int[] map) {
for (int i = 0; i < map.length; i++) {
if (map[i] == index) {
return true;
}
}
return false;
}
@Override
protected EconomicMap<LoopExitNode, Boolean> processLoop(LoopBeginNode loop, Boolean initialState) {
return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates;
}
@Override
protected Boolean merge(AbstractMergeNode merge, List<Boolean> states) {
return false;
}
@Override
protected Boolean afterSplit(AbstractBeginNode node, Boolean oldState) {
return false;
}
};
try (Scope disabled = debug.disable()) {
ReentrantNodeIterator.apply(closure, graph.start(), false);
new WriteBarrierVerificationPhase(config).apply(graph);
} catch (AssertionError error) {
/*
* Catch assertion, test for expected one and re-throw in order to validate unit
* test.
*/
Assert.assertTrue(error.getMessage().contains("Write barrier must be present"));
throw error;
}
} catch (Throwable e) {
throw debug.handle(e);
}
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class BinaryGraphPrinter method nodeProperties.
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void nodeProperties(GraphInfo info, Node node, Map<String, Object> props) {
node.getDebugProperties((Map) props);
Graph graph = info.graph;
ControlFlowGraph cfg = info.cfg;
NodeMap<Block> nodeToBlocks = info.nodeToBlocks;
if (cfg != null && DebugOptions.PrintGraphProbabilities.getValue(graph.getOptions()) && node instanceof FixedNode) {
try {
props.put("probability", cfg.blockFor(node).probability());
} catch (Throwable t) {
props.put("probability", 0.0);
props.put("probability-exception", t);
}
}
try {
props.put("NodeCost-Size", node.estimatedNodeSize());
props.put("NodeCost-Cycles", node.estimatedNodeCycles());
} catch (Throwable t) {
props.put("node-cost-exception", t.getMessage());
}
if (nodeToBlocks != null) {
Object block = getBlockForNode(node, nodeToBlocks);
if (block != null) {
props.put("node-to-block", block);
}
}
if (node instanceof ControlSinkNode) {
props.put("category", "controlSink");
} else if (node instanceof ControlSplitNode) {
props.put("category", "controlSplit");
} else if (node instanceof AbstractMergeNode) {
props.put("category", "merge");
} else if (node instanceof AbstractBeginNode) {
props.put("category", "begin");
} else if (node instanceof AbstractEndNode) {
props.put("category", "end");
} else if (node instanceof FixedNode) {
props.put("category", "fixed");
} else if (node instanceof VirtualState) {
props.put("category", "state");
} else if (node instanceof PhiNode) {
props.put("category", "phi");
} else if (node instanceof ProxyNode) {
props.put("category", "proxy");
} else {
if (node instanceof ConstantNode) {
ConstantNode cn = (ConstantNode) node;
updateStringPropertiesForConstant((Map) props, cn);
}
props.put("category", "floating");
}
if (getSnippetReflectionProvider() != null) {
for (Map.Entry<String, Object> prop : props.entrySet()) {
if (prop.getValue() instanceof JavaConstantFormattable) {
props.put(prop.getKey(), ((JavaConstantFormattable) prop.getValue()).format(this));
}
}
}
}
use of org.graalvm.compiler.nodes.AbstractMergeNode in project graal by oracle.
the class CFGPrinter method printNodes.
private void printNodes(Block block) {
printedNodes = new NodeBitMap(cfg.graph);
begin("IR");
out.println("HIR");
out.disableIndentation();
if (block.getBeginNode() instanceof AbstractMergeNode) {
// Currently phi functions are not in the schedule, so print them separately here.
for (ValueNode phi : ((AbstractMergeNode) block.getBeginNode()).phis()) {
printNode(phi, false);
}
}
Node cur = block.getBeginNode();
while (true) {
printNode(cur, false);
if (cur == block.getEndNode()) {
UnmodifiableMapCursor<Node, Block> cursor = latestScheduling.getEntries();
while (cursor.advance()) {
if (cursor.getValue() == block && !inFixedSchedule(cursor.getKey()) && !printedNodes.isMarked(cursor.getKey())) {
printNode(cursor.getKey(), true);
}
}
break;
}
assert cur.successors().count() == 1;
cur = cur.successors().first();
}
out.enableIndentation();
end("IR");
printedNodes = null;
}
Aggregations