use of org.graalvm.compiler.nodes.memory.MemoryMapNode in project graal by oracle.
the class SnippetTemplate method rewireMemoryGraph.
private void rewireMemoryGraph(ValueNode replacee, UnmodifiableEconomicMap<Node, Node> duplicates) {
if (replacee.graph().isAfterFloatingReadPhase()) {
// rewire outgoing memory edges
replaceMemoryUsages(replacee, new MemoryOutputMap(replacee, duplicates));
if (returnNode != null) {
ReturnNode ret = (ReturnNode) duplicates.get(returnNode);
if (ret != null) {
MemoryMapNode memoryMap = ret.getMemoryMap();
if (memoryMap != null) {
ret.setMemoryMap(null);
memoryMap.safeDelete();
}
}
}
if (memoryAnchor != null) {
// rewire incoming memory edges
MemoryAnchorNode memoryDuplicate = (MemoryAnchorNode) duplicates.get(memoryAnchor);
replaceMemoryUsages(memoryDuplicate, new MemoryInputMap(replacee));
if (memoryDuplicate.hasNoUsages()) {
if (memoryDuplicate.next() != null) {
memoryDuplicate.graph().removeFixed(memoryDuplicate);
} else {
// this was a dummy memory node used when instantiating pure data-flow
// snippets: it was not attached to the control flow.
memoryDuplicate.safeDelete();
}
}
}
}
}
use of org.graalvm.compiler.nodes.memory.MemoryMapNode in project graal by oracle.
the class SnippetTemplate method assertSnippetKills.
private boolean assertSnippetKills(ValueNode replacee) {
if (!replacee.graph().isAfterFloatingReadPhase()) {
// 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 MemoryCheckpoint.Single) {
// check if some node in snippet graph also kills the same location
LocationIdentity locationIdentity = ((MemoryCheckpoint.Single) replacee).getLocationIdentity();
if (locationIdentity.isAny()) {
assert !(memoryMap.getLastLocationAccess(any()) instanceof MemoryAnchorNode) : replacee + " kills ANY_LOCATION, but snippet does not";
// 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 MemoryCheckpoint.Multi) : 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