use of org.graalvm.compiler.nodes.EndNode in project graal by oracle.
the class BytecodeParser method afterInvocationPluginExecution.
/**
* Performs any action required after execution of an invocation plugin. This includes
* {@linkplain InvocationPluginAssertions#check checking} invocation plugin invariants as well
* as weaving the {@code else} branch of the code woven by {@link #guardIntrinsic} if
* {@code guard != null}.
*/
protected void afterInvocationPluginExecution(boolean pluginHandledInvoke, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard, InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) {
assert assertions.check(pluginHandledInvoke);
if (intrinsicGuard != null) {
if (pluginHandledInvoke) {
if (intrinsicGuard.nonIntrinsicBranch != null) {
// Intrinsic emitted: emit a virtual call to the target method and
// merge it with the intrinsic branch
EndNode intrinsicEnd = append(new EndNode());
FrameStateBuilder intrinsicState = null;
FrameStateBuilder nonIntrinisicState = null;
if (resultType != JavaKind.Void) {
intrinsicState = frameState.copy();
frameState.pop(resultType);
nonIntrinisicState = frameState;
}
lastInstr = intrinsicGuard.nonIntrinsicBranch;
createNonInlinedInvoke(getActionForInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile);
EndNode nonIntrinsicEnd = append(new EndNode());
AbstractMergeNode mergeNode = graph.add(new MergeNode());
mergeNode.addForwardEnd(intrinsicEnd);
if (intrinsicState != null) {
intrinsicState.merge(mergeNode, nonIntrinisicState);
frameState = intrinsicState;
}
mergeNode.addForwardEnd(nonIntrinsicEnd);
mergeNode.setStateAfter(frameState.create(stream.nextBCI(), mergeNode));
lastInstr = mergeNode;
}
} else {
// Intrinsic was not applied: remove intrinsic guard
// and restore the original receiver node in the arguments array
intrinsicGuard.lastInstr.setNext(null);
GraphUtil.removeNewNodes(graph, intrinsicGuard.mark);
lastInstr = intrinsicGuard.lastInstr;
args[0] = intrinsicGuard.receiver;
}
}
}
use of org.graalvm.compiler.nodes.EndNode 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.EndNode in project graal by oracle.
the class LoopFragmentInside method getDuplicationReplacement.
@Override
@SuppressWarnings("try")
protected DuplicationReplacement getDuplicationReplacement() {
final LoopBeginNode loopBegin = loop().loopBegin();
final StructuredGraph graph = graph();
return new DuplicationReplacement() {
private EconomicMap<Node, Node> seenNode = EconomicMap.create(Equivalence.IDENTITY);
@Override
public Node replacement(Node original) {
try (DebugCloseable position = original.withNodeSourcePosition()) {
if (original == loopBegin) {
Node value = seenNode.get(original);
if (value != null) {
return value;
}
AbstractBeginNode newValue = graph.add(new BeginNode());
seenNode.put(original, newValue);
return newValue;
}
if (original instanceof LoopExitNode && ((LoopExitNode) original).loopBegin() == loopBegin) {
Node value = seenNode.get(original);
if (value != null) {
return value;
}
AbstractBeginNode newValue = graph.add(new BeginNode());
seenNode.put(original, newValue);
return newValue;
}
if (original instanceof LoopEndNode && ((LoopEndNode) original).loopBegin() == loopBegin) {
Node value = seenNode.get(original);
if (value != null) {
return value;
}
EndNode newValue = graph.add(new EndNode());
seenNode.put(original, newValue);
return newValue;
}
return original;
}
}
};
}
use of org.graalvm.compiler.nodes.EndNode in project graal by oracle.
the class LoopFragmentWhole method getDuplicationReplacement.
@Override
protected DuplicationReplacement getDuplicationReplacement() {
final FixedNode entry = loop().entryPoint();
final Graph graph = this.graph();
return new DuplicationReplacement() {
private EndNode endNode;
@Override
public Node replacement(Node o) {
if (o == entry) {
if (endNode == null) {
endNode = graph.add(new EndNode());
}
return endNode;
}
return o;
}
};
}
use of org.graalvm.compiler.nodes.EndNode in project graal by oracle.
the class GraphOrder method visitForward.
private static void visitForward(ArrayList<Node> nodes, NodeBitMap visited, Node node, boolean floatingOnly) {
try {
assert node == null || node.isAlive() : node + " not alive";
if (node != null && !visited.isMarked(node)) {
if (floatingOnly && node instanceof FixedNode) {
throw new GraalError("unexpected reference to fixed node: %s (this indicates an unexpected cycle)", node);
}
visited.mark(node);
FrameState stateAfter = null;
if (node instanceof StateSplit) {
stateAfter = ((StateSplit) node).stateAfter();
}
for (Node input : node.inputs()) {
if (input != stateAfter) {
visitForward(nodes, visited, input, true);
}
}
if (node instanceof EndNode) {
EndNode end = (EndNode) node;
for (PhiNode phi : end.merge().phis()) {
visitForward(nodes, visited, phi.valueAt(end), true);
}
}
nodes.add(node);
if (node instanceof AbstractMergeNode) {
for (PhiNode phi : ((AbstractMergeNode) node).phis()) {
visited.mark(phi);
nodes.add(phi);
}
}
if (stateAfter != null) {
visitForward(nodes, visited, stateAfter, true);
}
}
} catch (GraalError e) {
throw GraalGraphError.transformAndAddContext(e, node);
}
}
Aggregations