Search in sources :

Example 11 with NodeBitMap

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

the class LoopFragment method computeNodes.

protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
    for (AbstractBeginNode b : blocks) {
        if (b.isDeleted()) {
            continue;
        }
        for (Node n : b.getBlockNodes()) {
            if (n instanceof Invoke) {
                nodes.mark(((Invoke) n).callTarget());
            }
            if (n instanceof NodeWithState) {
                NodeWithState withState = (NodeWithState) n;
                withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node)));
            }
            if (n instanceof AbstractMergeNode) {
                // if a merge is in the loop, all of its phis are also in the loop
                for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
                    nodes.mark(phi);
                }
            }
            nodes.mark(n);
        }
    }
    for (AbstractBeginNode earlyExit : earlyExits) {
        if (earlyExit.isDeleted()) {
            continue;
        }
        nodes.mark(earlyExit);
        if (earlyExit instanceof LoopExitNode) {
            LoopExitNode loopExit = (LoopExitNode) earlyExit;
            FrameState stateAfter = loopExit.stateAfter();
            if (stateAfter != null) {
                stateAfter.applyToVirtual(node -> nodes.mark(node));
            }
            for (ProxyNode proxy : loopExit.proxies()) {
                nodes.mark(proxy);
            }
        }
    }
    final NodeBitMap nonLoopNodes = graph.createNodeBitMap();
    Deque<WorkListEntry> worklist = new ArrayDeque<>();
    for (AbstractBeginNode b : blocks) {
        if (b.isDeleted()) {
            continue;
        }
        for (Node n : b.getBlockNodes()) {
            if (n instanceof CommitAllocationNode) {
                for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) {
                    markFloating(worklist, obj, nodes, nonLoopNodes);
                }
            }
            if (n instanceof MonitorEnterNode) {
                markFloating(worklist, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
            }
            if (n instanceof AbstractMergeNode) {
                /*
                     * Since we already marked all phi nodes as being in the loop to break cycles,
                     * we also have to iterate over their usages here.
                     */
                for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
                    for (Node usage : phi.usages()) {
                        markFloating(worklist, usage, nodes, nonLoopNodes);
                    }
                }
            }
            for (Node usage : n.usages()) {
                markFloating(worklist, usage, nodes, nonLoopNodes);
            }
        }
    }
}
Also used : GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) Deque(java.util.Deque) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) TriState(jdk.vm.ci.meta.TriState) EconomicMap(org.graalvm.collections.EconomicMap) MergeNode(org.graalvm.compiler.nodes.MergeNode) VirtualState(org.graalvm.compiler.nodes.VirtualState) FixedNode(org.graalvm.compiler.nodes.FixedNode) NodeWithState(org.graalvm.compiler.nodes.spi.NodeWithState) Iterator(java.util.Iterator) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) NodeView(org.graalvm.compiler.nodes.NodeView) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) Graph(org.graalvm.compiler.graph.Graph) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) DuplicationReplacement(org.graalvm.compiler.graph.Graph.DuplicationReplacement) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) FrameState(org.graalvm.compiler.nodes.FrameState) NodeIterable(org.graalvm.compiler.graph.iterators.NodeIterable) Invoke(org.graalvm.compiler.nodes.Invoke) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Block(org.graalvm.compiler.nodes.cfg.Block) GraalError(org.graalvm.compiler.debug.GraalError) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) ArrayDeque(java.util.ArrayDeque) Collections(java.util.Collections) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FrameState(org.graalvm.compiler.nodes.FrameState) ArrayDeque(java.util.ArrayDeque) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Invoke(org.graalvm.compiler.nodes.Invoke) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) NodeWithState(org.graalvm.compiler.nodes.spi.NodeWithState) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode)

Example 12 with NodeBitMap

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

the class MethodTypeFlowBuilder method apply.

protected void apply() {
    // assert method.getAnnotation(Fold.class) == null : method;
    if (method.getAnnotation(NodeIntrinsic.class) != null) {
        graph.getDebug().log("apply MethodTypeFlow on node intrinsic %s", method);
        AnalysisType returnType = (AnalysisType) method.getSignature().getReturnType(method.getDeclaringClass());
        if (returnType.getJavaKind() == JavaKind.Object) {
            /*
                 * This is a method used in a snippet, so most likely the return value does not
                 * matter at all. However, some methods return an object, and the snippet continues
                 * to work with the object. So pretend that this method returns an object of the
                 * exact return type.
                 */
            TypeFlow<?> returnTypeFlow = methodFlow.getResultFlow().getDeclaredType().getTypeFlow(this.bb, true);
            returnTypeFlow = new ProxyTypeFlow(null, returnTypeFlow);
            FormalReturnTypeFlow resultFlow = new FormalReturnTypeFlow(null, returnType, method);
            returnTypeFlow.addOriginalUse(this.bb, resultFlow);
            methodFlow.addMiscEntry(returnTypeFlow);
            methodFlow.setResult(resultFlow);
        }
        return;
    }
    if (!parse()) {
        return;
    }
    this.bb.getUnsupportedFeatures().checkMethod(method, graph);
    processedNodes = new NodeBitMap(graph);
    TypeFlowsOfNodes typeFlows = new TypeFlowsOfNodes();
    for (Node n : graph.getNodes()) {
        if (n instanceof ParameterNode) {
            ParameterNode node = (ParameterNode) n;
            if (node.getStackKind() == JavaKind.Object) {
                TypeFlowBuilder<?> paramBuilder = TypeFlowBuilder.create(bb, node, FormalParamTypeFlow.class, () -> {
                    boolean isStatic = Modifier.isStatic(method.getModifiers());
                    int index = node.index();
                    FormalParamTypeFlow parameter;
                    if (!isStatic && index == 0) {
                        AnalysisType paramType = method.getDeclaringClass();
                        parameter = new FormalReceiverTypeFlow(node, paramType, method);
                    } else {
                        int offset = isStatic ? 0 : 1;
                        AnalysisType paramType = (AnalysisType) method.getSignature().getParameterType(index - offset, method.getDeclaringClass());
                        parameter = new FormalParamTypeFlow(node, paramType, method, index);
                    }
                    methodFlow.setParameter(index, parameter);
                    return parameter;
                });
                typeFlowGraphBuilder.checkFormalParameterBuilder(paramBuilder);
                typeFlows.add(node, paramBuilder);
            }
        } else if (n instanceof BoxNode) {
            BoxNode node = (BoxNode) n;
            Object key = uniqueKey(node);
            BytecodeLocation boxSite = bb.analysisPolicy().createAllocationSite(bb, key, methodFlow.getMethod());
            AnalysisType type = (AnalysisType) StampTool.typeOrNull(node);
            TypeFlowBuilder<?> boxBuilder = TypeFlowBuilder.create(bb, node, BoxTypeFlow.class, () -> {
                BoxTypeFlow boxFlow = new BoxTypeFlow(node, type, boxSite);
                methodFlow.addAllocation(boxFlow);
                return boxFlow;
            });
            typeFlows.add(node, boxBuilder);
        }
        for (Node input : n.inputs()) {
            /*
                 * TODO change the handling of constants so that the SourceTypeFlow is created on
                 * demand, with the optimization that only one SourceTypeFlow is created ever for
                 * every distinct object (using, e.g., caching in a global IdentityHashMap).
                 */
            if (input instanceof ConstantNode && !typeFlows.contains((ConstantNode) input)) {
                ConstantNode node = (ConstantNode) input;
                if (node.asJavaConstant().isNull()) {
                    TypeFlowBuilder<SourceTypeFlow> sourceBuilder = TypeFlowBuilder.create(bb, node, SourceTypeFlow.class, () -> {
                        SourceTypeFlow constantSource = new SourceTypeFlow(node, TypeState.forNull());
                        methodFlow.addSource(constantSource);
                        return constantSource;
                    });
                    typeFlows.add(node, sourceBuilder);
                } else if (node.asJavaConstant().getJavaKind() == JavaKind.Object) {
                    /*
                         * TODO a SubstrateObjectConstant wrapping a PrimitiveConstant has kind
                         * equals to Object. Do we care about the effective value of these primitive
                         * constants in the analysis?
                         */
                    assert StampTool.isExactType(node);
                    AnalysisType type = (AnalysisType) StampTool.typeOrNull(node);
                    assert type.isInstantiated();
                    TypeFlowBuilder<SourceTypeFlow> sourceBuilder = TypeFlowBuilder.create(bb, node, SourceTypeFlow.class, () -> {
                        SourceTypeFlow constantSource = new SourceTypeFlow(node, TypeState.forConstant(this.bb, node.asJavaConstant(), type));
                        methodFlow.addSource(constantSource);
                        return constantSource;
                    });
                    typeFlows.add(node, sourceBuilder);
                }
            }
        }
    }
    // Propagate the type flows through the method's graph
    new NodeIterator(graph.start(), typeFlows).apply();
    /* Prune the method graph. Eliminate nodes with no uses. */
    typeFlowGraphBuilder.build();
    /*
         * Make sure that all existing InstanceOfNodes are registered even when only used as an
         * input of a conditional.
         */
    for (Node n : graph.getNodes()) {
        if (n instanceof InstanceOfNode) {
            InstanceOfNode instanceOf = (InstanceOfNode) n;
            markFieldsUsedInComparison(instanceOf.getValue());
        } else if (n instanceof ObjectEqualsNode) {
            ObjectEqualsNode compareNode = (ObjectEqualsNode) n;
            markFieldsUsedInComparison(compareNode.getX());
            markFieldsUsedInComparison(compareNode.getY());
        }
    }
}
Also used : AnalysisType(com.oracle.graal.pointsto.meta.AnalysisType) TypeFlowBuilder(com.oracle.graal.pointsto.flow.builder.TypeFlowBuilder) RawLoadNode(org.graalvm.compiler.nodes.extended.RawLoadNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) WordCastNode(org.graalvm.compiler.word.WordCastNode) DynamicNewArrayNode(org.graalvm.compiler.nodes.java.DynamicNewArrayNode) ObjectEqualsNode(org.graalvm.compiler.nodes.calc.ObjectEqualsNode) BasicObjectCloneNode(org.graalvm.compiler.replacements.nodes.BasicObjectCloneNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) AtomicReadAndWriteNode(org.graalvm.compiler.nodes.java.AtomicReadAndWriteNode) ConvertUnknownValueNode(com.oracle.graal.pointsto.nodes.ConvertUnknownValueNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) AnalysisUnsafePartitionLoadNode(com.oracle.graal.pointsto.nodes.AnalysisUnsafePartitionLoadNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) ForeignCallNode(org.graalvm.compiler.nodes.extended.ForeignCallNode) NewInstanceNode(org.graalvm.compiler.nodes.java.NewInstanceNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) AnalysisArraysCopyOfNode(com.oracle.graal.pointsto.nodes.AnalysisArraysCopyOfNode) DynamicNewInstanceNode(org.graalvm.compiler.nodes.java.DynamicNewInstanceNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) NewMultiArrayNode(org.graalvm.compiler.nodes.java.NewMultiArrayNode) LoadIndexedNode(org.graalvm.compiler.nodes.java.LoadIndexedNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) BoxNode(org.graalvm.compiler.nodes.extended.BoxNode) BinaryMathIntrinsicNode(org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode) IfNode(org.graalvm.compiler.nodes.IfNode) RawStoreNode(org.graalvm.compiler.nodes.extended.RawStoreNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) NewArrayNode(org.graalvm.compiler.nodes.java.NewArrayNode) UnsafeCompareAndSwapNode(org.graalvm.compiler.nodes.java.UnsafeCompareAndSwapNode) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) InstanceOfNode(org.graalvm.compiler.nodes.java.InstanceOfNode) BasicArrayCopyNode(org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode) InvokeNode(org.graalvm.compiler.nodes.InvokeNode) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) UnaryMathIntrinsicNode(org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode) StoreIndexedNode(org.graalvm.compiler.nodes.java.StoreIndexedNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) GetClassNode(org.graalvm.compiler.nodes.extended.GetClassNode) BytecodeExceptionNode(org.graalvm.compiler.nodes.extended.BytecodeExceptionNode) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) AnalysisUnsafePartitionStoreNode(com.oracle.graal.pointsto.nodes.AnalysisUnsafePartitionStoreNode) BoxNode(org.graalvm.compiler.nodes.extended.BoxNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) BytecodeLocation(com.oracle.graal.pointsto.flow.context.BytecodeLocation) NodeIntrinsic(org.graalvm.compiler.graph.Node.NodeIntrinsic) PostOrderNodeIterator(org.graalvm.compiler.phases.graph.PostOrderNodeIterator) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) ObjectEqualsNode(org.graalvm.compiler.nodes.calc.ObjectEqualsNode) InstanceOfNode(org.graalvm.compiler.nodes.java.InstanceOfNode)

Example 13 with NodeBitMap

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

the class GraphUtil method originalValueSimple.

private static ValueNode originalValueSimple(ValueNode value) {
    /* The very simple case: look through proxies. */
    ValueNode cur = originalValueForProxy(value);
    while (cur instanceof PhiNode) {
        /*
             * We found a phi function. Check if we can analyze it without allocating temporary data
             * structures.
             */
        PhiNode phi = (PhiNode) cur;
        ValueNode phiSingleValue = null;
        int count = phi.valueCount();
        for (int i = 0; i < count; ++i) {
            ValueNode phiCurValue = originalValueForProxy(phi.valueAt(i));
            if (phiCurValue == phi) {
            /* Simple cycle, we can ignore the input value. */
            } else if (phiSingleValue == null) {
                /* The first input. */
                phiSingleValue = phiCurValue;
            } else if (phiSingleValue != phiCurValue) {
                if (phiSingleValue instanceof PhiNode || phiCurValue instanceof PhiNode) {
                    /*
                         * We have two different input values for the phi function, and at least one
                         * of the inputs is another phi function. We need to do a complicated
                         * exhaustive check.
                         */
                    return originalValueForComplicatedPhi(phi, new NodeBitMap(value.graph()));
                } else {
                    /*
                         * We have two different input values for the phi function, but none of them
                         * is another phi function. This phi function cannot be reduce any further,
                         * so the phi function is the original value.
                         */
                    return phi;
                }
            }
        }
        /*
             * Successfully reduced the phi function to a single input value. The single input value
             * can itself be a phi function again, so we might take another loop iteration.
             */
        assert phiSingleValue != null;
        cur = phiSingleValue;
    }
    /* We reached a "normal" node, which is the original value. */
    assert !(cur instanceof LimitedValueProxy) && !(cur instanceof PhiNode);
    return cur;
}
Also used : PhiNode(org.graalvm.compiler.nodes.PhiNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) ValueNode(org.graalvm.compiler.nodes.ValueNode) LimitedValueProxy(org.graalvm.compiler.nodes.spi.LimitedValueProxy)

Example 14 with NodeBitMap

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

the class CFGPrinter method printSchedule.

public void printSchedule(String message, ScheduleResult theSchedule) {
    schedule = theSchedule;
    cfg = schedule.getCFG();
    printedNodes = new NodeBitMap(cfg.graph);
    begin("cfg");
    out.print("name \"").print(message).println('"');
    for (Block b : schedule.getCFG().getBlocks()) {
        if (schedule.nodesFor(b) != null) {
            printScheduledBlock(b, schedule.nodesFor(b));
        }
    }
    end("cfg");
    schedule = null;
    cfg = null;
    printedNodes = null;
}
Also used : NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) Block(org.graalvm.compiler.nodes.cfg.Block)

Aggregations

NodeBitMap (org.graalvm.compiler.graph.NodeBitMap)14 Node (org.graalvm.compiler.graph.Node)11 FixedNode (org.graalvm.compiler.nodes.FixedNode)9 PhiNode (org.graalvm.compiler.nodes.PhiNode)9 ValueNode (org.graalvm.compiler.nodes.ValueNode)9 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)8 EndNode (org.graalvm.compiler.nodes.EndNode)7 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)6 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)6 ProxyNode (org.graalvm.compiler.nodes.ProxyNode)6 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)5 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)5 Block (org.graalvm.compiler.nodes.cfg.Block)5 VirtualObjectNode (org.graalvm.compiler.nodes.virtual.VirtualObjectNode)5 ArrayList (java.util.ArrayList)4 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)4 MergeNode (org.graalvm.compiler.nodes.MergeNode)4 ValuePhiNode (org.graalvm.compiler.nodes.ValuePhiNode)4 ArrayDeque (java.util.ArrayDeque)3 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)3