use of org.graalvm.compiler.nodes.memory.MultiMemoryKill in project graal by oracle.
the class Block method calcKillLocations.
private LocationSet calcKillLocations() {
LocationSet result = new LocationSet();
for (FixedNode node : this.getNodes()) {
if (node instanceof SingleMemoryKill) {
LocationIdentity identity = ((SingleMemoryKill) node).getKilledLocationIdentity();
result.add(identity);
} else if (node instanceof MultiMemoryKill) {
for (LocationIdentity identity : ((MultiMemoryKill) node).getKilledLocationIdentities()) {
result.add(identity);
}
}
if (result.isAny()) {
break;
}
}
return result;
}
use of org.graalvm.compiler.nodes.memory.MultiMemoryKill in project graal by oracle.
the class ScheduleVerification method processBlock.
@Override
protected EconomicSet<FloatingReadNode> processBlock(Block block, EconomicSet<FloatingReadNode> currentState) {
AbstractBeginNode beginNode = block.getBeginNode();
if (beginNode instanceof AbstractMergeNode) {
AbstractMergeNode abstractMergeNode = (AbstractMergeNode) beginNode;
for (PhiNode phi : abstractMergeNode.phis()) {
if (phi instanceof MemoryPhiNode) {
MemoryPhiNode memoryPhiNode = (MemoryPhiNode) phi;
addFloatingReadUsages(currentState, memoryPhiNode);
}
}
}
if (beginNode instanceof LoopExitNode) {
LoopExitNode loopExitNode = (LoopExitNode) beginNode;
for (ProxyNode proxy : loopExitNode.proxies()) {
if (proxy instanceof MemoryProxyNode) {
MemoryProxyNode memoryProxyNode = (MemoryProxyNode) proxy;
addFloatingReadUsages(currentState, memoryProxyNode);
}
}
}
for (Node n : blockToNodesMap.get(block)) {
if (n instanceof MemoryKill) {
if (n instanceof SingleMemoryKill) {
SingleMemoryKill single = (SingleMemoryKill) n;
processLocation(n, single.getKilledLocationIdentity(), currentState);
} else if (n instanceof MultiMemoryKill) {
MultiMemoryKill multi = (MultiMemoryKill) n;
for (LocationIdentity location : multi.getKilledLocationIdentities()) {
processLocation(n, location, currentState);
}
}
addFloatingReadUsages(currentState, n);
} else if (n instanceof MemoryAccess) {
addFloatingReadUsages(currentState, n);
} else if (n instanceof FloatingReadNode) {
FloatingReadNode floatingReadNode = (FloatingReadNode) n;
if (floatingReadNode.getLastLocationAccess() != null && floatingReadNode.getLocationIdentity().isMutable()) {
if (currentState.contains(floatingReadNode)) {
// Floating read was found in the state.
currentState.remove(floatingReadNode);
} else {
throw new RuntimeException("Floating read node " + n + " was not found in the state, i.e., it was killed by a memory check point before its place in the schedule. Block=" + block + ", block begin: " + block.getBeginNode() + " block loop: " + block.getLoop() + ", " + blockToNodesMap.get(block).get(0));
}
}
}
assert nodeMap.get(n) == block;
if (graph.isBeforeStage(StageFlag.VALUE_PROXY_REMOVAL) && block.getLoop() != null && !(n instanceof VirtualState)) {
for (Node usage : n.usages()) {
Node usageNode = usage;
if (usageNode instanceof PhiNode) {
PhiNode phiNode = (PhiNode) usage;
usageNode = phiNode.merge();
}
if (usageNode instanceof LoopExitNode) {
LoopExitNode loopExitNode = (LoopExitNode) usageNode;
if (loopExitNode.loopBegin() == n || loopExitNode.stateAfter() == n) {
continue;
}
}
Block usageBlock = nodeMap.get(usageNode);
if (usageBlock == null) {
if (usage instanceof FloatingNode || usage instanceof VirtualState || usage instanceof CallTargetNode) {
if (!(usage instanceof GuardNode)) {
/*
* We do not want to run the schedule behind the verification with
* dead code elimination, i.e., floating nodes without usages are
* not removed, thus we must handle the case that a floating node
* without a usage occurs here.
*/
if (nonFixedNodeTreeWithoutUsages(usage)) {
continue;
}
}
}
}
assert usageBlock != null || usage instanceof ProxyNode : "Usage " + usageNode + " of node " + n + " has no block";
Loop<Block> usageLoop = null;
if (usageNode instanceof ProxyNode) {
ProxyNode proxyNode = (ProxyNode) usageNode;
usageLoop = nodeMap.get(proxyNode.proxyPoint().loopBegin()).getLoop();
} else {
if (usageBlock.getBeginNode() instanceof LoopExitNode) {
// For nodes in the loop exit node block, we don't know for sure
// whether they are "in the loop" or not. It depends on whether
// one of their transient usages is a loop proxy node.
// For now, let's just assume those nodes are OK, i.e., "in the loop".
LoopExitNode loopExitNode = (LoopExitNode) usageBlock.getBeginNode();
usageLoop = nodeMap.get(loopExitNode.loopBegin()).getLoop();
} else {
usageLoop = usageBlock.getLoop();
}
}
assert usageLoop != null : n + ", " + nodeMap.get(n) + " / " + usageNode + ", " + nodeMap.get(usageNode);
while (usageLoop != block.getLoop() && usageLoop != null) {
usageLoop = usageLoop.getParent();
}
assert usageLoop != null : n + ", " + usageNode + ", " + usageBlock + ", " + usageBlock.getLoop() + ", " + block + ", " + block.getLoop();
}
}
}
return currentState;
}
use of org.graalvm.compiler.nodes.memory.MultiMemoryKill in project graal by oracle.
the class BinaryGraphPrinter method nodeProperties.
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void nodeProperties(GraphInfo info, Node node, Map<String, ? super Object> props) {
node.getDebugProperties((Map) props);
NodeMap<Block> nodeToBlocks = info.nodeToBlocks;
if (nodeToBlocks != null) {
Block block = getBlockForNode(node, nodeToBlocks);
if (block != null) {
props.put("relativeFrequency", block.getRelativeFrequency());
props.put("nodeToBlock", block);
}
}
props.put("nodeCostSize", node.estimatedNodeSize());
props.put("nodeCostCycles", node.estimatedNodeCycles());
if (nodeToBlocks != null) {
Object block = getBlockForNode(node, nodeToBlocks);
if (block != null) {
props.put("nodeToBlock", block);
}
}
if (info.cfg != null) {
if (node instanceof LoopBeginNode) {
// check if cfg is up to date
if (info.cfg.getLocalLoopFrequencyData().containsKey((LoopBeginNode) node)) {
props.put("localLoopFrequency", info.cfg.localLoopFrequency((LoopBeginNode) node));
}
}
}
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 (node instanceof SingleMemoryKill) {
props.put("killedLocationIdentity", ((SingleMemoryKill) node).getKilledLocationIdentity());
}
if (node instanceof MultiMemoryKill) {
props.put("killedLocationIdentities", ((MultiMemoryKill) node).getKilledLocationIdentities());
}
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.memory.MultiMemoryKill in project graal by oracle.
the class PlaceholderLogicNode method verifyWithExceptionNode.
/**
* Verifies that a {@link WithExceptionNode} has only memory usages via the
* {@link WithExceptionNode#next()} edge. On the {@link WithExceptionNode#exceptionEdge()} there
* must be a {@link MemoryKill} (or an {@link UnreachableBeginNode}), otherwise we would not
* know from which edge a memory usage is coming from.
*/
private static void verifyWithExceptionNode(ValueNode node) {
if (node instanceof WithExceptionNode && node instanceof MemoryKill) {
WithExceptionNode withExceptionNode = (WithExceptionNode) node;
AbstractBeginNode exceptionEdge = withExceptionNode.exceptionEdge();
if (exceptionEdge instanceof UnreachableBeginNode) {
// exception edge is unreachable - we are good
return;
}
GraalError.guarantee(exceptionEdge instanceof MemoryKill, "The exception edge of %s is not a memory kill %s", node, exceptionEdge);
if (exceptionEdge instanceof SingleMemoryKill) {
SingleMemoryKill exceptionEdgeKill = (SingleMemoryKill) exceptionEdge;
if (exceptionEdgeKill.getKilledLocationIdentity().isAny()) {
// exception edge kills any - we are good
return;
}
// if the exception edge does not kill any, it must kill the same location
GraalError.guarantee(withExceptionNode instanceof SingleMemoryKill, "Not a single memory kill: %s", withExceptionNode);
SingleMemoryKill withExceptionKill = (SingleMemoryKill) withExceptionNode;
GraalError.guarantee(withExceptionKill.getKilledLocationIdentity().equals(exceptionEdgeKill.getKilledLocationIdentity()), "Kill locations do not match: %s (%s) vs %s (%s)", withExceptionKill, withExceptionKill.getKilledLocationIdentity(), exceptionEdgeKill, exceptionEdgeKill.getKilledLocationIdentity());
} else if (exceptionEdge instanceof MultiMemoryKill) {
// for multi memory kills the locations must match
MultiMemoryKill exceptionEdgeKill = (MultiMemoryKill) exceptionEdge;
GraalError.guarantee(withExceptionNode instanceof MultiMemoryKill, "Not a single memory kill: %s", withExceptionNode);
MultiMemoryKill withExceptionKill = (MultiMemoryKill) withExceptionNode;
GraalError.guarantee(Arrays.equals(withExceptionKill.getKilledLocationIdentities(), exceptionEdgeKill.getKilledLocationIdentities()), "Kill locations do not match: %s (%s) vs %s (%s)", withExceptionKill, withExceptionKill.getKilledLocationIdentities(), exceptionEdgeKill, exceptionEdgeKill.getKilledLocationIdentities());
} else {
GraalError.shouldNotReachHere("Unexpected exception edge: " + exceptionEdge);
}
}
}
use of org.graalvm.compiler.nodes.memory.MultiMemoryKill in project graal by oracle.
the class ReadEliminationClosure method processNode.
@Override
protected boolean processNode(Node node, ReadEliminationBlockState state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
boolean deleted = false;
if (node instanceof AccessFieldNode) {
AccessFieldNode access = (AccessFieldNode) node;
if (access.ordersMemoryAccesses()) {
killReadCacheByIdentity(state, any());
} else {
ValueNode object = GraphUtil.unproxify(access.object());
LoadCacheEntry identifier = new LoadCacheEntry(object, new FieldLocationIdentity(access.field()));
ValueNode cachedValue = state.getCacheEntry(identifier);
if (node instanceof LoadFieldNode) {
if (cachedValue != null && areValuesReplaceable(access, cachedValue, considerGuards)) {
effects.replaceAtUsages(access, cachedValue, access);
addScalarAlias(access, cachedValue);
deleted = true;
} else {
state.addCacheEntry(identifier, access);
}
} else {
assert node instanceof StoreFieldNode;
StoreFieldNode store = (StoreFieldNode) node;
ValueNode value = getScalarAlias(store.value());
if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
effects.deleteNode(store);
deleted = true;
}
// will be a field location identity not killing array accesses
killReadCacheByIdentity(state, identifier.identity);
state.addCacheEntry(identifier, value);
}
}
} else if (node instanceof ReadNode) {
ReadNode read = (ReadNode) node;
if (read.ordersMemoryAccesses()) {
killReadCacheByIdentity(state, any());
} else {
if (read.getLocationIdentity().isSingle()) {
ValueNode object = GraphUtil.unproxify(read.getAddress());
LoadCacheEntry identifier = new LoadCacheEntry(object, read.getLocationIdentity());
ValueNode cachedValue = state.getCacheEntry(identifier);
if (cachedValue != null && areValuesReplaceable(read, cachedValue, considerGuards)) {
effects.replaceAtUsages(read, cachedValue, read);
addScalarAlias(read, cachedValue);
deleted = true;
} else {
state.addCacheEntry(identifier, read);
}
}
}
} else if (node instanceof WriteNode) {
WriteNode write = (WriteNode) node;
if (write.getKilledLocationIdentity().isSingle()) {
ValueNode object = GraphUtil.unproxify(write.getAddress());
LoadCacheEntry identifier = new LoadCacheEntry(object, write.getKilledLocationIdentity());
ValueNode cachedValue = state.getCacheEntry(identifier);
ValueNode value = getScalarAlias(write.value());
if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
effects.deleteNode(write);
deleted = true;
}
killReadCacheByIdentity(state, write.getKilledLocationIdentity());
state.addCacheEntry(identifier, value);
} else {
killReadCacheByIdentity(state, write.getKilledLocationIdentity());
}
} else if (node instanceof UnsafeAccessNode) {
final UnsafeAccessNode unsafeAccess = (UnsafeAccessNode) node;
if (unsafeAccess.ordersMemoryAccesses()) {
killReadCacheByIdentity(state, any());
} else {
/*
* We do not know if we are writing an array or a normal object
*/
if (node instanceof RawLoadNode) {
RawLoadNode load = (RawLoadNode) node;
if (load.getLocationIdentity().isSingle()) {
ValueNode object = GraphUtil.unproxify(load.object());
UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, load.offset(), load.getLocationIdentity(), load.accessKind());
ValueNode cachedValue = state.getCacheEntry(identifier);
if (cachedValue != null && areValuesReplaceable(load, cachedValue, considerGuards)) {
if (load.accessKind() == JavaKind.Boolean) {
// perform boolean coercion
LogicNode cmp = IntegerEqualsNode.create(cachedValue, ConstantNode.forInt(0), NodeView.DEFAULT);
ValueNode boolValue = ConditionalNode.create(cmp, ConstantNode.forBoolean(false), ConstantNode.forBoolean(true), NodeView.DEFAULT);
effects.ensureFloatingAdded(boolValue);
cachedValue = boolValue;
}
effects.replaceAtUsages(load, cachedValue, load);
addScalarAlias(load, cachedValue);
deleted = true;
} else {
state.addCacheEntry(identifier, load);
}
}
} else {
assert node instanceof RawStoreNode;
RawStoreNode write = (RawStoreNode) node;
if (write.getKilledLocationIdentity().isSingle()) {
ValueNode object = GraphUtil.unproxify(write.object());
UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getKilledLocationIdentity(), write.accessKind());
ValueNode cachedValue = state.getCacheEntry(identifier);
ValueNode value = getScalarAlias(write.value());
if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) {
effects.deleteNode(write);
deleted = true;
}
killReadCacheByIdentity(state, write.getKilledLocationIdentity());
state.addCacheEntry(identifier, value);
} else {
killReadCacheByIdentity(state, write.getKilledLocationIdentity());
}
}
}
} else if (node instanceof StoreIndexedNode) {
LocationIdentity identity = NamedLocationIdentity.getArrayLocation(((StoreIndexedNode) node).elementKind());
killReadCacheByIdentity(state, identity);
} else if (node instanceof SingleMemoryKill) {
LocationIdentity identity = ((SingleMemoryKill) node).getKilledLocationIdentity();
killReadCacheByIdentity(state, identity);
} else if (node instanceof MultiMemoryKill) {
for (LocationIdentity identity : ((MultiMemoryKill) node).getKilledLocationIdentities()) {
killReadCacheByIdentity(state, identity);
}
}
return deleted;
}
Aggregations