use of org.graalvm.compiler.nodes.memory.MultiMemoryKill in project graal by oracle.
the class PEReadEliminationClosure method processNode.
@Override
protected boolean processNode(Node node, PEReadEliminationBlockState state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
if (super.processNode(node, state, effects, lastFixedNode)) {
return true;
}
if (currentMode != EffectsClosureMode.REGULAR_VIRTUALIZATION) {
/*
* PEA closure decided it has to give up for this loop nest, do the same and stop
* processing nodes.
*/
return false;
}
if (node instanceof LoadFieldNode) {
return processLoadField((LoadFieldNode) node, state, effects);
} else if (node instanceof StoreFieldNode) {
return processStoreField((StoreFieldNode) node, state, effects);
} else if (node instanceof LoadIndexedNode) {
return processLoadIndexed((LoadIndexedNode) node, state, effects);
} else if (node instanceof StoreIndexedNode) {
return processStoreIndexed((StoreIndexedNode) node, state, effects);
} else if (node instanceof ArrayLengthNode) {
return processArrayLength((ArrayLengthNode) node, state, effects);
} else if (node instanceof UnboxNode) {
return processUnbox((UnboxNode) node, state, effects);
} else if (node instanceof RawLoadNode) {
return processUnsafeLoad((RawLoadNode) node, state, effects);
} else if (node instanceof RawStoreNode) {
return processUnsafeStore((RawStoreNode) node, state, effects);
} else if (node instanceof SingleMemoryKill) {
COUNTER_MEMORYCHECKPOINT.increment(node.getDebug());
LocationIdentity identity = ((SingleMemoryKill) node).getKilledLocationIdentity();
processIdentity(state, identity);
} else if (node instanceof MultiMemoryKill) {
COUNTER_MEMORYCHECKPOINT.increment(node.getDebug());
for (LocationIdentity identity : ((MultiMemoryKill) node).getKilledLocationIdentities()) {
processIdentity(state, identity);
}
}
return false;
}
use of org.graalvm.compiler.nodes.memory.MultiMemoryKill in project graal by oracle.
the class LoweringPhase method checkPostNodeLowering.
/**
* Checks that lowering of a given node did not introduce any new {@link Lowerable} nodes that
* could be lowered in the current {@link LoweringPhase}. Such nodes must be recursively lowered
* as part of lowering {@code node}.
*
* @param node a node that was just lowered
* @param preLoweringMark the graph mark before {@code node} was lowered
* @param unscheduledUsages set of {@code node}'s usages that were unscheduled before it was
* lowered
* @throws AssertionError if the check fails
*/
private static boolean checkPostNodeLowering(Node node, LoweringToolImpl loweringTool, Mark preLoweringMark, Collection<Node> unscheduledUsages) {
StructuredGraph graph = (StructuredGraph) node.graph();
Mark postLoweringMark = graph.getMark();
NodeIterable<Node> newNodesAfterLowering = graph.getNewNodes(preLoweringMark);
if (node instanceof FloatingNode) {
if (!unscheduledUsages.isEmpty()) {
for (Node n : newNodesAfterLowering) {
assert !(n instanceof FixedNode) : node.graph() + ": cannot lower floatable node " + node + " as it introduces fixed node(s) but has the following unscheduled usages: " + unscheduledUsages;
}
}
}
for (Node n : newNodesAfterLowering) {
if (n instanceof Lowerable) {
((Lowerable) n).lower(loweringTool);
Mark mark = graph.getMark();
assert postLoweringMark.equals(mark) : graph + ": lowering of " + node + " produced lowerable " + n + " that should have been recursively lowered as it introduces these new nodes: " + graph.getNewNodes(postLoweringMark).snapshot();
}
if (graph.isAfterStage(StageFlag.FLOATING_READS) && n instanceof MemoryKill && !(node instanceof MemoryKill) && !(node instanceof ControlSinkNode)) {
/*
* The lowering introduced a MemoryCheckpoint but the current node isn't a
* checkpoint. This is only OK if the locations involved don't affect the memory
* graph or if the new kill location doesn't connect into the existing graph.
*/
boolean isAny = false;
if (n instanceof SingleMemoryKill) {
isAny = ((SingleMemoryKill) n).getKilledLocationIdentity().isAny();
} else if (n instanceof MultiMemoryKill) {
for (LocationIdentity ident : ((MultiMemoryKill) n).getKilledLocationIdentities()) {
if (ident.isAny()) {
isAny = true;
}
}
} else {
throw GraalError.shouldNotReachHere("Unknown type of memory kill " + n);
}
if (isAny && n instanceof FixedWithNextNode) {
/*
* Check if the next kill location leads directly to a ControlSinkNode in the
* new part of the graph. This is a fairly conservative test that could be made
* more general if required.
*/
FixedWithNextNode cur = (FixedWithNextNode) n;
while (cur != null && graph.isNew(preLoweringMark, cur)) {
if (cur.next() instanceof ControlSinkNode) {
isAny = false;
break;
}
if (cur.next() instanceof FixedWithNextNode) {
cur = (FixedWithNextNode) cur.next();
} else {
break;
}
}
}
assert !isAny : node + " " + n;
}
}
return true;
}
use of org.graalvm.compiler.nodes.memory.MultiMemoryKill in project graal by oracle.
the class VarHandleTest method countAnyKill.
private static int countAnyKill(StructuredGraph graph) {
int anyKillCount = 0;
int startNodes = 0;
for (Node n : graph.getNodes()) {
if (n instanceof StartNode) {
startNodes++;
} else if (n instanceof SingleMemoryKill) {
SingleMemoryKill single = (SingleMemoryKill) n;
if (single.getKilledLocationIdentity().isAny()) {
anyKillCount++;
}
} else if (n instanceof MultiMemoryKill) {
MultiMemoryKill multi = (MultiMemoryKill) n;
for (LocationIdentity loc : multi.getKilledLocationIdentities()) {
if (loc.isAny()) {
anyKillCount++;
break;
}
}
}
}
// Ignore single StartNode.
Assert.assertEquals(1, startNodes);
return anyKillCount;
}
use of org.graalvm.compiler.nodes.memory.MultiMemoryKill in project graal by oracle.
the class PlaceholderLogicNode method assertSnippetKills.
private boolean assertSnippetKills(ValueNode replacee) {
if (replacee.graph().isBeforeStage(StageFlag.FLOATING_READS)) {
// no floating reads yet, ignore locations created while lowering
return true;
}
if (returnNode == null) {
// The snippet terminates control flow
return true;
}
MemoryMapNode memoryMap = returnNode.getMemoryMap();
if (memoryMap == null || memoryMap.isEmpty()) {
// there are no kills in the snippet graph
return true;
}
EconomicSet<LocationIdentity> kills = EconomicSet.create(Equivalence.DEFAULT);
kills.addAll(memoryMap.getLocations());
if (replacee instanceof SingleMemoryKill) {
// check if some node in snippet graph also kills the same location
LocationIdentity locationIdentity = ((SingleMemoryKill) replacee).getKilledLocationIdentity();
if (locationIdentity.isAny()) {
// if the replacee kills ANY_LOCATION, the snippet can kill arbitrary locations
return true;
}
assert kills.contains(locationIdentity) : replacee + " kills " + locationIdentity + ", but snippet doesn't contain a kill to this location";
kills.remove(locationIdentity);
}
assert !(replacee instanceof MultiMemoryKill) : replacee + " multi not supported (yet)";
// remove ANY_LOCATION if it's just a kill by the start node
if (memoryMap.getLastLocationAccess(any()) instanceof MemoryAnchorNode) {
kills.remove(any());
}
// node can only lower to a ANY_LOCATION kill if the replacee also kills ANY_LOCATION
assert !kills.contains(any()) : "snippet graph contains a kill to ANY_LOCATION, but replacee (" + replacee + ") doesn't kill ANY_LOCATION. kills: " + kills;
/*
* Kills to private locations are safe, since there can be no floating read to these
* locations except reads that are introduced by the snippet itself or related snippets in
* the same lowering round. These reads are anchored to a MemoryAnchor at the beginning of
* their snippet, so they can not float above a kill in another instance of the same
* snippet.
*/
for (LocationIdentity p : this.info.privateLocations) {
kills.remove(p);
}
assert kills.isEmpty() : "snippet graph kills non-private locations " + kills + " that replacee (" + replacee + ") doesn't kill";
return true;
}
Aggregations