use of org.graalvm.compiler.nodes.SafepointNode 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.SafepointNode in project graal by oracle.
the class ExceedMaxOopMapStackOffset method editGraphBuilderConfiguration.
@Override
protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
InvocationPlugin safepointPlugin = new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) {
b.add(new SafepointNode());
return true;
}
};
conf.getPlugins().getInvocationPlugins().register(safepointPlugin, getClass(), "safepoint");
return super.editGraphBuilderConfiguration(conf);
}
use of org.graalvm.compiler.nodes.SafepointNode in project graal by oracle.
the class LoopFragmentInside method insertWithinAfter.
/**
* Duplicate the body within the loop after the current copy copy of the body.
*
* @param loop
* @param updateLimit true if the iteration limit should be adjusted.
*/
public void insertWithinAfter(LoopEx loop, boolean updateLimit) {
assert isDuplicate() && original().loop() == loop;
patchNodes(dataFixWithinAfter);
/*
* Collect any new back edges values before updating them since they might reference each
* other.
*/
LoopBeginNode mainLoopBegin = loop.loopBegin();
ArrayList<ValueNode> backedgeValues = new ArrayList<>();
for (PhiNode mainPhiNode : mainLoopBegin.phis()) {
ValueNode duplicatedNode = getDuplicatedNode(mainPhiNode.valueAt(1));
if (duplicatedNode == null) {
if (mainLoopBegin.isPhiAtMerge(mainPhiNode.valueAt(1))) {
duplicatedNode = ((PhiNode) (mainPhiNode.valueAt(1))).valueAt(1);
} else {
assert mainPhiNode.valueAt(1).isConstant() : mainPhiNode.valueAt(1);
}
}
backedgeValues.add(duplicatedNode);
}
int index = 0;
for (PhiNode mainPhiNode : mainLoopBegin.phis()) {
ValueNode duplicatedNode = backedgeValues.get(index++);
if (duplicatedNode != null) {
mainPhiNode.setValueAt(1, duplicatedNode);
}
}
placeNewSegmentAndCleanup(loop);
// Remove any safepoints from the original copy leaving only the duplicated one
assert loop.whole().nodes().filter(SafepointNode.class).count() == nodes().filter(SafepointNode.class).count();
for (SafepointNode safepoint : loop.whole().nodes().filter(SafepointNode.class)) {
graph().removeFixed(safepoint);
}
int unrollFactor = mainLoopBegin.getUnrollFactor();
StructuredGraph graph = mainLoopBegin.graph();
if (updateLimit) {
// Now use the previous unrollFactor to update the exit condition to power of two
InductionVariable iv = loop.counted().getCounter();
CompareNode compareNode = (CompareNode) loop.counted().getLimitTest().condition();
ValueNode compareBound;
if (compareNode.getX() == iv.valueNode()) {
compareBound = compareNode.getY();
} else if (compareNode.getY() == iv.valueNode()) {
compareBound = compareNode.getX();
} else {
throw GraalError.shouldNotReachHere();
}
long originalStride = unrollFactor == 1 ? iv.constantStride() : iv.constantStride() / unrollFactor;
if (iv.direction() == InductionVariable.Direction.Up) {
ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(NodeView.DEFAULT), unrollFactor * originalStride));
ValueNode newLimit = graph.addWithoutUnique(new SubNode(compareBound, aboveVal));
compareNode.replaceFirstInput(compareBound, newLimit);
} else if (iv.direction() == InductionVariable.Direction.Down) {
ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(NodeView.DEFAULT), unrollFactor * -originalStride));
ValueNode newLimit = graph.addWithoutUnique(new AddNode(compareBound, aboveVal));
compareNode.replaceFirstInput(compareBound, newLimit);
}
}
mainLoopBegin.setUnrollFactor(unrollFactor * 2);
mainLoopBegin.setLoopFrequency(mainLoopBegin.loopFrequency() / 2);
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "LoopPartialUnroll %s", loop);
mainLoopBegin.getDebug().dump(DebugContext.VERBOSE_LEVEL, mainLoopBegin.graph(), "After insertWithinAfter %s", mainLoopBegin);
}
use of org.graalvm.compiler.nodes.SafepointNode in project graal by oracle.
the class MethodSafepointInsertionPhase method run.
@Override
protected void run(StructuredGraph graph) {
if (graph.method().getAnnotation(Uninterruptible.class) != null) {
/*
* If a method is annotated with {@link Uninterruptible}, then I do not want a test for
* a safepoint at the return.
*/
return;
}
if (graph.method().getAnnotation(CFunction.class) != null) {
/*
* If a method transfers from Java to C, then the return transition (if any) contains
* the safepoint test and one is not needed at the return of the transferring method.
*/
return;
}
if (((SharedMethod) graph.method()).isEntryPoint()) {
/*
* If a method is transferring from C to Java, then no safepoint test is needed at the
* return of the transferring method.
*/
return;
}
for (ReturnNode returnNode : graph.getNodes(ReturnNode.TYPE)) {
SafepointNode safepointNode = graph.add(new SafepointNode());
graph.addBeforeFixed(returnNode, safepointNode);
}
}
use of org.graalvm.compiler.nodes.SafepointNode in project graal by oracle.
the class DefaultHotSpotLoweringProvider method lower.
@Override
public void lower(Node n, LoweringTool tool) {
StructuredGraph graph = (StructuredGraph) n.graph();
if (n instanceof Invoke) {
lowerInvoke((Invoke) n, tool, graph);
} else if (n instanceof LoadMethodNode) {
lowerLoadMethodNode((LoadMethodNode) n);
} else if (n instanceof GetClassNode) {
lowerGetClassNode((GetClassNode) n, tool, graph);
} else if (n instanceof StoreHubNode) {
lowerStoreHubNode((StoreHubNode) n, graph);
} else if (n instanceof OSRStartNode) {
lowerOSRStartNode((OSRStartNode) n);
} else if (n instanceof BytecodeExceptionNode) {
lowerBytecodeExceptionNode((BytecodeExceptionNode) n);
} else if (n instanceof InstanceOfNode) {
InstanceOfNode instanceOfNode = (InstanceOfNode) n;
if (graph.getGuardsStage().areDeoptsFixed()) {
instanceofSnippets.lower(instanceOfNode, tool);
} else {
if (instanceOfNode.allowsNull()) {
ValueNode object = instanceOfNode.getValue();
LogicNode newTypeCheck = graph.addOrUniqueWithInputs(InstanceOfNode.create(instanceOfNode.type(), object, instanceOfNode.profile(), instanceOfNode.getAnchor()));
LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY);
instanceOfNode.replaceAndDelete(newNode);
}
}
} else if (n instanceof InstanceOfDynamicNode) {
InstanceOfDynamicNode instanceOfDynamicNode = (InstanceOfDynamicNode) n;
if (graph.getGuardsStage().areDeoptsFixed()) {
instanceofSnippets.lower(instanceOfDynamicNode, tool);
} else {
ValueNode mirror = instanceOfDynamicNode.getMirrorOrHub();
if (mirror.stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Object) {
ClassGetHubNode classGetHub = graph.unique(new ClassGetHubNode(mirror));
instanceOfDynamicNode.setMirror(classGetHub);
}
if (instanceOfDynamicNode.allowsNull()) {
ValueNode object = instanceOfDynamicNode.getObject();
LogicNode newTypeCheck = graph.addOrUniqueWithInputs(InstanceOfDynamicNode.create(graph.getAssumptions(), tool.getConstantReflection(), instanceOfDynamicNode.getMirrorOrHub(), object, false));
LogicNode newNode = LogicNode.or(graph.unique(IsNullNode.create(object)), newTypeCheck, GraalDirectives.UNLIKELY_PROBABILITY);
instanceOfDynamicNode.replaceAndDelete(newNode);
}
}
} else if (n instanceof ClassIsAssignableFromNode) {
if (graph.getGuardsStage().areDeoptsFixed()) {
instanceofSnippets.lower((ClassIsAssignableFromNode) n, tool);
}
} else if (n instanceof NewInstanceNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower((NewInstanceNode) n, registers, tool);
}
} else if (n instanceof DynamicNewInstanceNode) {
DynamicNewInstanceNode newInstanceNode = (DynamicNewInstanceNode) n;
if (newInstanceNode.getClassClass() == null) {
JavaConstant classClassMirror = constantReflection.forObject(Class.class);
ConstantNode classClass = ConstantNode.forConstant(classClassMirror, tool.getMetaAccess(), graph);
newInstanceNode.setClassClass(classClass);
}
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower(newInstanceNode, registers, tool);
}
} else if (n instanceof NewArrayNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower((NewArrayNode) n, registers, tool);
}
} else if (n instanceof DynamicNewArrayNode) {
DynamicNewArrayNode dynamicNewArrayNode = (DynamicNewArrayNode) n;
if (dynamicNewArrayNode.getVoidClass() == null) {
JavaConstant voidClassMirror = constantReflection.forObject(void.class);
ConstantNode voidClass = ConstantNode.forConstant(voidClassMirror, tool.getMetaAccess(), graph);
dynamicNewArrayNode.setVoidClass(voidClass);
}
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower(dynamicNewArrayNode, registers, tool);
}
} else if (n instanceof VerifyHeapNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower((VerifyHeapNode) n, registers, tool);
}
} else if (n instanceof RawMonitorEnterNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
monitorSnippets.lower((RawMonitorEnterNode) n, registers, tool);
}
} else if (n instanceof MonitorExitNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
monitorSnippets.lower((MonitorExitNode) n, registers, tool);
}
} else if (n instanceof ArrayCopyNode) {
arraycopySnippets.lower((ArrayCopyNode) n, tool);
} else if (n instanceof ArrayCopyWithSlowPathNode) {
arraycopySnippets.lower((ArrayCopyWithSlowPathNode) n, tool);
} else if (n instanceof G1PreWriteBarrier) {
writeBarrierSnippets.lower((G1PreWriteBarrier) n, registers, tool);
} else if (n instanceof G1PostWriteBarrier) {
writeBarrierSnippets.lower((G1PostWriteBarrier) n, registers, tool);
} else if (n instanceof G1ReferentFieldReadBarrier) {
writeBarrierSnippets.lower((G1ReferentFieldReadBarrier) n, registers, tool);
} else if (n instanceof SerialWriteBarrier) {
writeBarrierSnippets.lower((SerialWriteBarrier) n, tool);
} else if (n instanceof SerialArrayRangeWriteBarrier) {
writeBarrierSnippets.lower((SerialArrayRangeWriteBarrier) n, tool);
} else if (n instanceof G1ArrayRangePreWriteBarrier) {
writeBarrierSnippets.lower((G1ArrayRangePreWriteBarrier) n, registers, tool);
} else if (n instanceof G1ArrayRangePostWriteBarrier) {
writeBarrierSnippets.lower((G1ArrayRangePostWriteBarrier) n, registers, tool);
} else if (n instanceof NewMultiArrayNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
newObjectSnippets.lower((NewMultiArrayNode) n, tool);
}
} else if (n instanceof LoadExceptionObjectNode) {
exceptionObjectSnippets.lower((LoadExceptionObjectNode) n, registers, tool);
} else if (n instanceof AssertionNode) {
assertionSnippets.lower((AssertionNode) n, tool);
} else if (n instanceof StringToBytesNode) {
if (graph.getGuardsStage().areDeoptsFixed()) {
stringToBytesSnippets.lower((StringToBytesNode) n, tool);
}
} else if (n instanceof IntegerDivRemNode) {
// Nothing to do for division nodes. The HotSpot signal handler catches divisions by
// zero and the MIN_VALUE / -1 cases.
} else if (n instanceof AbstractDeoptimizeNode || n instanceof UnwindNode || n instanceof RemNode || n instanceof SafepointNode) {
/* No lowering, we generate LIR directly for these nodes. */
} else if (n instanceof ClassGetHubNode) {
lowerClassGetHubNode((ClassGetHubNode) n, tool);
} else if (n instanceof HubGetClassNode) {
lowerHubGetClassNode((HubGetClassNode) n, tool);
} else if (n instanceof KlassLayoutHelperNode) {
lowerKlassLayoutHelperNode((KlassLayoutHelperNode) n, tool);
} else if (n instanceof ComputeObjectAddressNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
lowerComputeObjectAddressNode((ComputeObjectAddressNode) n);
}
} else if (n instanceof IdentityHashCodeNode) {
hashCodeSnippets.lower((IdentityHashCodeNode) n, tool);
} else if (n instanceof ResolveDynamicConstantNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
resolveConstantSnippets.lower((ResolveDynamicConstantNode) n, tool);
}
} else if (n instanceof ResolveConstantNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
resolveConstantSnippets.lower((ResolveConstantNode) n, tool);
}
} else if (n instanceof ResolveMethodAndLoadCountersNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool);
}
} else if (n instanceof InitializeKlassNode) {
if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
resolveConstantSnippets.lower((InitializeKlassNode) n, tool);
}
} else if (n instanceof ProfileNode) {
profileSnippets.lower((ProfileNode) n, tool);
} else {
super.lower(n, tool);
}
}
Aggregations