Search in sources :

Example 1 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class AMD64HotSpotAddressLowering method signExtend.

/**
 * Create a sign extend for {@code input}, or zero extend if {@code input} can be proven
 * positive.
 */
private static ValueNode signExtend(ValueNode input, LoopEx loop) {
    StructuredGraph graph = input.graph();
    if (input instanceof PhiNode) {
        EconomicMap<Node, InductionVariable> ivs = loop.getInductionVariables();
        InductionVariable inductionVariable = ivs.get(input);
        if (inductionVariable != null && inductionVariable instanceof BasicInductionVariable) {
            CountedLoopInfo countedLoopInfo = loop.counted();
            IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT);
            if (initStamp.isPositive()) {
                if (inductionVariable.isConstantExtremum()) {
                    long init = inductionVariable.constantInit();
                    long stride = inductionVariable.constantStride();
                    long extremum = inductionVariable.constantExtremum();
                    if (init >= 0 && extremum >= 0) {
                        long shortestTrip = (extremum - init) / stride + 1;
                        if (countedLoopInfo.constantMaxTripCount().equals(shortestTrip)) {
                            return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
                        }
                    }
                }
                if (countedLoopInfo.getCounter() == inductionVariable && inductionVariable.direction() == InductionVariable.Direction.Up && countedLoopInfo.getOverFlowGuard() != null) {
                    return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
                }
            }
        }
    }
    return input.graph().maybeAddOrUnique(SignExtendNode.create(input, ADDRESS_BITS, NodeView.DEFAULT));
}
Also used : StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) PhiNode(org.graalvm.compiler.nodes.PhiNode) AMD64AddressNode(org.graalvm.compiler.core.amd64.AMD64AddressNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) OffsetAddressNode(org.graalvm.compiler.nodes.memory.address.OffsetAddressNode) AddNode(org.graalvm.compiler.nodes.calc.AddNode) GraalHotSpotVMConfigNode(org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) CompressionNode(org.graalvm.compiler.nodes.CompressionNode) AddressNode(org.graalvm.compiler.nodes.memory.address.AddressNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) PhiNode(org.graalvm.compiler.nodes.PhiNode) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) CountedLoopInfo(org.graalvm.compiler.loop.CountedLoopInfo) BasicInductionVariable(org.graalvm.compiler.loop.BasicInductionVariable) InductionVariable(org.graalvm.compiler.loop.InductionVariable) DerivedInductionVariable(org.graalvm.compiler.loop.DerivedInductionVariable) BasicInductionVariable(org.graalvm.compiler.loop.BasicInductionVariable) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode)

Example 2 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class RawLoadNode method virtualize.

@Override
public void virtualize(VirtualizerTool tool) {
    ValueNode alias = tool.getAlias(object());
    if (alias instanceof VirtualObjectNode) {
        VirtualObjectNode virtual = (VirtualObjectNode) alias;
        ValueNode offsetValue = tool.getAlias(offset());
        if (offsetValue.isConstant()) {
            long off = offsetValue.asJavaConstant().asLong();
            int entryIndex = virtual.entryIndexForOffset(tool.getArrayOffsetProvider(), off, accessKind());
            if (entryIndex != -1) {
                ValueNode entry = tool.getEntry(virtual, entryIndex);
                JavaKind entryKind = virtual.entryKind(entryIndex);
                if (entry.getStackKind() == getStackKind() || entryKind == accessKind()) {
                    if (!(entry.stamp(NodeView.DEFAULT).isCompatible(stamp(NodeView.DEFAULT)))) {
                        if (entry.stamp(NodeView.DEFAULT) instanceof PrimitiveStamp && stamp instanceof PrimitiveStamp) {
                            PrimitiveStamp p1 = (PrimitiveStamp) stamp;
                            PrimitiveStamp p2 = (PrimitiveStamp) entry.stamp(NodeView.DEFAULT);
                            int width1 = p1.getBits();
                            int width2 = p2.getBits();
                            if (width1 == width2) {
                                Node replacement = ReinterpretNode.create(p2, entry, NodeView.DEFAULT);
                                tool.replaceWith((ValueNode) replacement);
                                return;
                            } else {
                                // different bit width
                                return;
                            }
                        } else {
                            // cannot reinterpret for arbitrary objects
                            return;
                        }
                    }
                    tool.replaceWith(entry);
                }
            }
        }
    }
}
Also used : VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) ReinterpretNode(org.graalvm.compiler.nodes.calc.ReinterpretNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) ValueNode(org.graalvm.compiler.nodes.ValueNode) PrimitiveStamp(org.graalvm.compiler.core.common.type.PrimitiveStamp) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 3 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class OnStackReplacementPhase method run.

@Override
@SuppressWarnings("try")
protected void run(StructuredGraph graph) {
    DebugContext debug = graph.getDebug();
    if (graph.getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI) {
        // used.
        assert graph.getNodes(EntryMarkerNode.TYPE).isEmpty();
        return;
    }
    debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI());
    EntryMarkerNode osr;
    int maxIterations = -1;
    int iterations = 0;
    final EntryMarkerNode originalOSRNode = getEntryMarker(graph);
    final LoopBeginNode originalOSRLoop = osrLoop(originalOSRNode);
    final boolean currentOSRWithLocks = osrWithLocks(originalOSRNode);
    if (originalOSRLoop == null) {
        /*
             * OSR with Locks: We do not have an OSR loop for the original OSR bci. Therefore we
             * cannot decide where to deopt and which framestate will be used. In the worst case the
             * framestate of the OSR entry would be used.
             */
        throw new PermanentBailoutException("OSR compilation without OSR entry loop.");
    }
    if (!supportOSRWithLocks(graph.getOptions()) && currentOSRWithLocks) {
        throw new PermanentBailoutException("OSR with locks disabled.");
    }
    do {
        osr = getEntryMarker(graph);
        LoopsData loops = new LoopsData(graph);
        // Find the loop that contains the EntryMarker
        Loop<Block> l = loops.getCFG().getNodeToBlock().get(osr).getLoop();
        if (l == null) {
            break;
        }
        iterations++;
        if (maxIterations == -1) {
            maxIterations = l.getDepth();
        } else if (iterations > maxIterations) {
            throw GraalError.shouldNotReachHere();
        }
        // Peel the outermost loop first
        while (l.getParent() != null) {
            l = l.getParent();
        }
        LoopTransformations.peel(loops.loop(l));
        osr.replaceAtUsages(InputType.Guard, AbstractBeginNode.prevBegin((FixedNode) osr.predecessor()));
        for (Node usage : osr.usages().snapshot()) {
            EntryProxyNode proxy = (EntryProxyNode) usage;
            proxy.replaceAndDelete(proxy.value());
        }
        GraphUtil.removeFixedWithUnusedInputs(osr);
        debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result");
    } while (true);
    StartNode start = graph.start();
    FrameState osrState = osr.stateAfter();
    OSRStartNode osrStart;
    try (DebugCloseable context = osr.withNodeSourcePosition()) {
        osr.setStateAfter(null);
        osrStart = graph.add(new OSRStartNode());
        FixedNode next = osr.next();
        osr.setNext(null);
        osrStart.setNext(next);
        graph.setStart(osrStart);
        osrStart.setStateAfter(osrState);
        debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start");
        final int localsSize = osrState.localsSize();
        final int locksSize = osrState.locksSize();
        for (int i = 0; i < localsSize + locksSize; i++) {
            ValueNode value = null;
            if (i >= localsSize) {
                value = osrState.lockAt(i - localsSize);
            } else {
                value = osrState.localAt(i);
            }
            if (value instanceof EntryProxyNode) {
                EntryProxyNode proxy = (EntryProxyNode) value;
                /*
                     * We need to drop the stamp since the types we see during OSR may be too
                     * precise (if a branch was not parsed for example). In cases when this is
                     * possible, we insert a guard and narrow the OSRLocal stamp at its usages.
                     */
                Stamp narrowedStamp = proxy.value().stamp(NodeView.DEFAULT);
                Stamp unrestrictedStamp = proxy.stamp(NodeView.DEFAULT).unrestricted();
                ValueNode osrLocal;
                if (i >= localsSize) {
                    osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, unrestrictedStamp));
                } else {
                    osrLocal = graph.addOrUnique(new OSRLocalNode(i, unrestrictedStamp));
                }
                // Speculate on the OSRLocal stamps that could be more precise.
                OSRLocalSpeculationReason reason = new OSRLocalSpeculationReason(osrState.bci, narrowedStamp, i);
                if (graph.getSpeculationLog().maySpeculate(reason) && osrLocal instanceof OSRLocalNode && value.getStackKind().equals(JavaKind.Object) && !narrowedStamp.isUnrestricted()) {
                    // Add guard.
                    LogicNode check = graph.addOrUniqueWithInputs(InstanceOfNode.createHelper((ObjectStamp) narrowedStamp, osrLocal, null, null));
                    JavaConstant constant = graph.getSpeculationLog().speculate(reason);
                    FixedGuardNode guard = graph.add(new FixedGuardNode(check, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, constant, false));
                    graph.addAfterFixed(osrStart, guard);
                    // Replace with a more specific type at usages.
                    // We know that we are at the root,
                    // so we need to replace the proxy in the state.
                    proxy.replaceAtMatchingUsages(osrLocal, n -> n == osrState);
                    osrLocal = graph.addOrUnique(new PiNode(osrLocal, narrowedStamp, guard));
                }
                proxy.replaceAndDelete(osrLocal);
            } else {
                assert value == null || value instanceof OSRLocalNode;
            }
        }
        osr.replaceAtUsages(InputType.Guard, osrStart);
    }
    debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies");
    GraphUtil.killCFG(start);
    debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement result");
    new DeadCodeEliminationPhase(Required).apply(graph);
    if (currentOSRWithLocks) {
        OsrWithLocksCount.increment(debug);
        try (DebugCloseable context = osrStart.withNodeSourcePosition()) {
            for (int i = osrState.monitorIdCount() - 1; i >= 0; --i) {
                MonitorIdNode id = osrState.monitorIdAt(i);
                ValueNode lockedObject = osrState.lockAt(i);
                OSRMonitorEnterNode osrMonitorEnter = graph.add(new OSRMonitorEnterNode(lockedObject, id));
                for (Node usage : id.usages()) {
                    if (usage instanceof AccessMonitorNode) {
                        AccessMonitorNode access = (AccessMonitorNode) usage;
                        access.setObject(lockedObject);
                    }
                }
                FixedNode oldNext = osrStart.next();
                oldNext.replaceAtPredecessor(null);
                osrMonitorEnter.setNext(oldNext);
                osrStart.setNext(osrMonitorEnter);
            }
        }
        debug.dump(DebugContext.DETAILED_LEVEL, graph, "After inserting OSR monitor enters");
        /*
             * Ensure balanced monitorenter - monitorexit
             *
             * Ensure that there is no monitor exit without a monitor enter in the graph. If there
             * is one this can only be done by bytecode as we have the monitor enter before the OSR
             * loop but the exit in a path of the loop that must be under a condition, else it will
             * throw an IllegalStateException anyway in the 2.iteration
             */
        for (MonitorExitNode exit : graph.getNodes(MonitorExitNode.TYPE)) {
            MonitorIdNode id = exit.getMonitorId();
            if (id.usages().filter(MonitorEnterNode.class).count() != 1) {
                throw new PermanentBailoutException("Unbalanced monitor enter-exit in OSR compilation with locks. Object is locked before the loop but released inside the loop.");
            }
        }
    }
    debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement result");
    new DeadCodeEliminationPhase(Required).apply(graph);
    /*
         * There must not be any parameter nodes left after OSR compilation.
         */
    assert graph.getNodes(ParameterNode.TYPE).count() == 0 : "OSR Compilation contains references to parameters.";
}
Also used : EntryMarkerNode(org.graalvm.compiler.nodes.EntryMarkerNode) AccessMonitorNode(org.graalvm.compiler.nodes.java.AccessMonitorNode) ObjectStamp(org.graalvm.compiler.core.common.type.ObjectStamp) OSRLockNode(org.graalvm.compiler.nodes.extended.OSRLockNode) MonitorIdNode(org.graalvm.compiler.nodes.java.MonitorIdNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) OSRLocalNode(org.graalvm.compiler.nodes.extended.OSRLocalNode) EntryMarkerNode(org.graalvm.compiler.nodes.EntryMarkerNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) EntryProxyNode(org.graalvm.compiler.nodes.EntryProxyNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) PiNode(org.graalvm.compiler.nodes.PiNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) OSRMonitorEnterNode(org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode) MonitorExitNode(org.graalvm.compiler.nodes.java.MonitorExitNode) StartNode(org.graalvm.compiler.nodes.StartNode) InstanceOfNode(org.graalvm.compiler.nodes.java.InstanceOfNode) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) AccessMonitorNode(org.graalvm.compiler.nodes.java.AccessMonitorNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) OSRStartNode(org.graalvm.compiler.nodes.extended.OSRStartNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Node(org.graalvm.compiler.graph.Node) JavaConstant(jdk.vm.ci.meta.JavaConstant) FixedNode(org.graalvm.compiler.nodes.FixedNode) PiNode(org.graalvm.compiler.nodes.PiNode) FrameState(org.graalvm.compiler.nodes.FrameState) MonitorExitNode(org.graalvm.compiler.nodes.java.MonitorExitNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) DeadCodeEliminationPhase(org.graalvm.compiler.phases.common.DeadCodeEliminationPhase) PermanentBailoutException(org.graalvm.compiler.core.common.PermanentBailoutException) MonitorIdNode(org.graalvm.compiler.nodes.java.MonitorIdNode) StartNode(org.graalvm.compiler.nodes.StartNode) OSRStartNode(org.graalvm.compiler.nodes.extended.OSRStartNode) LoopsData(org.graalvm.compiler.loop.LoopsData) ObjectStamp(org.graalvm.compiler.core.common.type.ObjectStamp) Stamp(org.graalvm.compiler.core.common.type.Stamp) OSRLocalNode(org.graalvm.compiler.nodes.extended.OSRLocalNode) DebugContext(org.graalvm.compiler.debug.DebugContext) EntryProxyNode(org.graalvm.compiler.nodes.EntryProxyNode) OSRLockNode(org.graalvm.compiler.nodes.extended.OSRLockNode) OSRMonitorEnterNode(org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) OSRStartNode(org.graalvm.compiler.nodes.extended.OSRStartNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Block(org.graalvm.compiler.nodes.cfg.Block) LogicNode(org.graalvm.compiler.nodes.LogicNode) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable)

Example 4 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class WriteBarrierVerificationPhase method hasAttachedBarrier.

private boolean hasAttachedBarrier(FixedWithNextNode node) {
    final Node next = node.next();
    final Node previous = node.predecessor();
    boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWrite) node).isInitialization());
    if (node instanceof WriteNode) {
        WriteNode writeNode = (WriteNode) node;
        if (writeNode.getLocationIdentity().isInit()) {
            validatePreBarrier = false;
        }
    }
    if (isObjectWrite(node)) {
        return (isObjectBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isObjectBarrier(node, previous));
    } else if (isObjectArrayRangeWrite(node)) {
        return (isArrayBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isArrayBarrier(node, previous));
    } else {
        return true;
    }
}
Also used : ArrayRangeWrite(org.graalvm.compiler.nodes.extended.ArrayRangeWrite) WriteNode(org.graalvm.compiler.nodes.memory.WriteNode) LoweredAtomicReadAndWriteNode(org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode) ReadNode(org.graalvm.compiler.nodes.memory.ReadNode) OffsetAddressNode(org.graalvm.compiler.nodes.memory.address.OffsetAddressNode) FixedAccessNode(org.graalvm.compiler.nodes.memory.FixedAccessNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) DeoptimizingNode(org.graalvm.compiler.nodes.DeoptimizingNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) LogicCompareAndSwapNode(org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode) WriteNode(org.graalvm.compiler.nodes.memory.WriteNode) LoweredAtomicReadAndWriteNode(org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode)

Example 5 with Node

use of org.graalvm.compiler.graph.Node in project graal by oracle.

the class ProfileNode method simplify.

@Override
public void simplify(SimplifierTool tool) {
    for (Node p = predecessor(); p != null; p = p.predecessor()) {
        // Terminate search when we hit a control split or merge.
        if (p instanceof ControlSplitNode || p instanceof AbstractMergeNode) {
            break;
        }
        if (p instanceof ProfileNode) {
            ProfileNode that = (ProfileNode) p;
            if (this.canBeMergedWith(that)) {
                that.setStep(this.getStep() + that.getStep());
                removeFixedWithUnusedInputs(this);
                tool.addToWorkList(that);
                break;
            }
        }
    }
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) DeoptimizingFixedWithNextNode(org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode) Node(org.graalvm.compiler.graph.Node) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode)

Aggregations

Node (org.graalvm.compiler.graph.Node)189 ValueNode (org.graalvm.compiler.nodes.ValueNode)105 FixedNode (org.graalvm.compiler.nodes.FixedNode)91 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)75 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)74 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)73 PhiNode (org.graalvm.compiler.nodes.PhiNode)64 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)61 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)53 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)47 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)43 FloatingNode (org.graalvm.compiler.nodes.calc.FloatingNode)41 ParameterNode (org.graalvm.compiler.nodes.ParameterNode)38 EndNode (org.graalvm.compiler.nodes.EndNode)37 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)37 MethodCallTargetNode (org.graalvm.compiler.nodes.java.MethodCallTargetNode)37 MergeNode (org.graalvm.compiler.nodes.MergeNode)35 ReturnNode (org.graalvm.compiler.nodes.ReturnNode)35 VirtualObjectNode (org.graalvm.compiler.nodes.virtual.VirtualObjectNode)32 LogicNode (org.graalvm.compiler.nodes.LogicNode)31