Search in sources :

Example 6 with ValuePhiNode

use of org.graalvm.compiler.nodes.ValuePhiNode in project graal by oracle.

the class EarlyReadEliminationTest method testBadLoop.

@Test
public void testBadLoop() {
    ValueNode result = getReturn("testBadLoopSnippet", false).result();
    assertDeepEquals(0, result.graph().getNodes().filter(LoadFieldNode.class).count());
    assertTrue(result instanceof ProxyNode);
    assertTrue(((ProxyNode) result).value() instanceof ValuePhiNode);
}
Also used : ProxyNode(org.graalvm.compiler.nodes.ProxyNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Test(org.junit.Test) GraalCompilerTest(org.graalvm.compiler.core.test.GraalCompilerTest)

Example 7 with ValuePhiNode

use of org.graalvm.compiler.nodes.ValuePhiNode in project graal by oracle.

the class FrameStateBuilder method createValuePhi.

private ValuePhiNode createValuePhi(ValueNode currentValue, ValueNode otherValue, AbstractMergeNode block) {
    ValuePhiNode phi = graph.addWithoutUnique(new ValuePhiNode(currentValue.stamp(NodeView.DEFAULT).unrestricted(), block));
    for (int i = 0; i < block.phiPredecessorCount(); i++) {
        phi.addInput(currentValue);
    }
    phi.addInput(otherValue);
    assert phi.valueCount() == block.phiPredecessorCount() + 1;
    return phi;
}
Also used : ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode)

Example 8 with ValuePhiNode

use of org.graalvm.compiler.nodes.ValuePhiNode in project graal by oracle.

the class LoopFragmentInside method patchPeeling.

private void patchPeeling(LoopFragmentInside peel) {
    LoopBeginNode loopBegin = loop().loopBegin();
    StructuredGraph graph = loopBegin.graph();
    List<PhiNode> newPhis = new LinkedList<>();
    NodeBitMap usagesToPatch = nodes.copy();
    for (LoopExitNode exit : exits()) {
        markStateNodes(exit, usagesToPatch);
        for (ProxyNode proxy : exit.proxies()) {
            usagesToPatch.markAndGrow(proxy);
        }
    }
    markStateNodes(loopBegin, usagesToPatch);
    List<PhiNode> oldPhis = loopBegin.phis().snapshot();
    for (PhiNode phi : oldPhis) {
        if (phi.hasNoUsages()) {
            continue;
        }
        ValueNode first;
        if (loopBegin.loopEnds().count() == 1) {
            // back edge value
            ValueNode b = phi.valueAt(loopBegin.loopEnds().first());
            // corresponding value in the peel
            first = peel.prim(b);
        } else {
            first = peel.mergedInitializers.get(phi);
        }
        // create a new phi (we don't patch the old one since some usages of the old one may
        // still be valid)
        PhiNode newPhi = patchPhi(graph, phi, loopBegin);
        newPhi.addInput(first);
        for (LoopEndNode end : loopBegin.orderedLoopEnds()) {
            newPhi.addInput(phi.valueAt(end));
        }
        peel.putDuplicatedNode(phi, newPhi);
        newPhis.add(newPhi);
        for (Node usage : phi.usages().snapshot()) {
            // patch only usages that should use the new phi ie usages that were peeled
            if (usagesToPatch.isMarkedAndGrow(usage)) {
                usage.replaceFirstInput(phi, newPhi);
            }
        }
    }
    // new corresponding phis
    for (PhiNode phi : newPhis) {
        for (int i = 0; i < phi.valueCount(); i++) {
            ValueNode v = phi.valueAt(i);
            if (loopBegin.isPhiAtMerge(v)) {
                PhiNode newV = peel.getDuplicatedNode((ValuePhiNode) v);
                if (newV != null) {
                    phi.setValueAt(i, newV);
                }
            }
        }
    }
    boolean progress = true;
    while (progress) {
        progress = false;
        int i = 0;
        outer: while (i < oldPhis.size()) {
            PhiNode oldPhi = oldPhis.get(i);
            for (Node usage : oldPhi.usages()) {
                if (usage instanceof PhiNode && oldPhis.contains(usage)) {
                // Do not mark.
                } else {
                    // Mark alive by removing from delete set.
                    oldPhis.remove(i);
                    progress = true;
                    continue outer;
                }
            }
            i++;
        }
    }
    for (PhiNode deadPhi : oldPhis) {
        deadPhi.clearInputs();
    }
    for (PhiNode deadPhi : oldPhis) {
        if (deadPhi.isAlive()) {
            GraphUtil.killWithUnusedFloatingInputs(deadPhi);
        }
    }
}
Also used : ProxyNode(org.graalvm.compiler.nodes.ProxyNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) AddNode(org.graalvm.compiler.nodes.calc.AddNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) SafepointNode(org.graalvm.compiler.nodes.SafepointNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) LinkedList(java.util.LinkedList) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) ValueNode(org.graalvm.compiler.nodes.ValueNode)

Example 9 with ValuePhiNode

use of org.graalvm.compiler.nodes.ValuePhiNode in project graal by oracle.

the class InferStamps method inferStamps.

/**
 * Infer the stamps for all Object nodes in the graph, to make the stamps as precise as
 * possible. For example, this propagates the word-type through phi functions. To handle phi
 * functions at loop headers, the stamp inference is called until a fix point is reached.
 * <p>
 * This method can be used when it is needed that stamps are inferred before the first run of
 * the canonicalizer. For example, word type rewriting must run before the first run of the
 * canonicalizer because many nodes are not prepared to see the word type during
 * canonicalization.
 */
public static void inferStamps(StructuredGraph graph) {
    /*
         * We want to make the stamps more precise. For cyclic phi functions, this means we have to
         * ignore the initial stamp because the imprecise stamp would always propagate around the
         * cycle. We therefore set the stamp to an illegal stamp, which is automatically ignored
         * when the phi function performs the "meet" operator on its input stamps.
         */
    for (Node n : graph.getNodes()) {
        if (n instanceof ValuePhiNode) {
            ValueNode node = (ValueNode) n;
            if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) {
                assert node.stamp(NodeView.DEFAULT).hasValues() : "We assume all Phi and Proxy stamps are legal before the analysis";
                node.setStamp(node.stamp(NodeView.DEFAULT).empty());
            }
        }
    }
    boolean stampChanged;
    // The algorithm is not guaranteed to reach a stable state.
    int z = 0;
    do {
        stampChanged = false;
        /*
             * We could use GraphOrder.forwardGraph() to process the nodes in a defined order and
             * propagate long def-use chains in fewer iterations. However, measurements showed that
             * we have few iterations anyway, and the overhead of computing the order is much higher
             * than the benefit.
             */
        for (Node n : graph.getNodes()) {
            if (n instanceof ValueNode) {
                ValueNode node = (ValueNode) n;
                if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) {
                    stampChanged |= node.inferStamp();
                }
            }
        }
        ++z;
    } while (stampChanged && z < 10000);
    /*
         * Check that all the illegal stamps we introduced above are correctly replaced with real
         * stamps again.
         */
    assert checkNoEmptyStamp(graph);
}
Also used : ObjectStamp(org.graalvm.compiler.core.common.type.ObjectStamp) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) Node(org.graalvm.compiler.graph.Node) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode)

Example 10 with ValuePhiNode

use of org.graalvm.compiler.nodes.ValuePhiNode in project graal by oracle.

the class JNIJavaCallWrapperMethod method loadAndUnboxArguments.

private List<Pair<ValueNode, ResolvedJavaType>> loadAndUnboxArguments(JNIGraphKit kit, HostedProviders providers, ResolvedJavaMethod invokeMethod, Signature invokeSignature) {
    MetaAccessProvider metaAccess = providers.getMetaAccess();
    List<Pair<ValueNode, ResolvedJavaType>> args = new ArrayList<>();
    int javaIndex = 0;
    javaIndex += metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind().getSlotCount();
    if (!invokeMethod.isStatic()) {
        JavaKind kind = metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind();
        ValueNode handle = kit.loadLocal(javaIndex, kind);
        ValueNode unboxed = kit.unboxHandle(handle);
        ValueNode receiver;
        ResolvedJavaType receiverClass = invokeMethod.getDeclaringClass();
        if (invokeMethod.isConstructor()) {
            /*
                 * Our target method is a constructor and we might be called via `NewObject`, in
                 * which case we need to allocate the object before calling the constructor. We can
                 * detect when this is the case because unlike with `Call<Type>Method`, we are
                 * passed the object hub of our target class in place of the receiver object.
                 */
            Constant hub = providers.getConstantReflection().asObjectHub(receiverClass);
            ConstantNode hubNode = kit.createConstant(hub, JavaKind.Object);
            kit.startIf(kit.unique(new ObjectEqualsNode(unboxed, hubNode)), BranchProbabilityNode.FAST_PATH_PROBABILITY);
            kit.thenPart();
            ValueNode created = kit.append(new NewInstanceNode(receiverClass, true));
            AbstractMergeNode merge = kit.endIf();
            receiver = kit.unique(new ValuePhiNode(StampFactory.object(), merge, new ValueNode[] { created, unboxed }));
        } else {
            receiver = unboxed;
        }
        args.add(Pair.create(receiver, receiverClass));
    }
    javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
    if (nonVirtual) {
        javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
    }
    javaIndex += metaAccess.lookupJavaType(JNIMethodId.class).getJavaKind().getSlotCount();
    int count = invokeSignature.getParameterCount(false);
    if (callVariant == CallVariant.VARARGS) {
        for (int i = 0; i < count; i++) {
            ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
            JavaKind kind = type.getJavaKind();
            JavaKind loadKind = kind;
            if (loadKind == JavaKind.Float) {
                // C varargs promote float to double
                loadKind = JavaKind.Double;
            }
            ValueNode value = kit.loadLocal(javaIndex, loadKind);
            if (kind == JavaKind.Float) {
                value = kit.unique(new FloatConvertNode(FloatConvert.D2F, value));
            } else if (kind.isObject()) {
                value = kit.unboxHandle(value);
            }
            args.add(Pair.create(value, type));
            javaIndex += loadKind.getSlotCount();
        }
    } else if (callVariant == CallVariant.ARRAY) {
        ResolvedJavaType elementType = metaAccess.lookupJavaType(JNIValue.class);
        int elementSize = SizeOf.get(JNIValue.class);
        ValueNode array = kit.loadLocal(javaIndex, elementType.getJavaKind());
        for (int i = 0; i < count; i++) {
            ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
            JavaKind readKind = type.getJavaKind();
            StructFieldInfo fieldInfo = getJNIValueOffsetOf(elementType, readKind);
            int offset = i * elementSize + fieldInfo.getOffsetInfo().getProperty();
            ConstantNode offsetConstant = kit.createConstant(JavaConstant.forInt(offset), providers.getWordTypes().getWordKind());
            OffsetAddressNode address = kit.unique(new OffsetAddressNode(array, offsetConstant));
            LocationIdentity locationIdentity = fieldInfo.getLocationIdentity();
            if (locationIdentity == null) {
                locationIdentity = LocationIdentity.any();
            }
            Stamp readStamp = getNarrowStamp(providers, readKind);
            ValueNode value = kit.append(new CInterfaceReadNode(address, locationIdentity, readStamp, BarrierType.NONE, "args[" + i + "]"));
            JavaKind stackKind = readKind.getStackKind();
            if (readKind != stackKind) {
                assert stackKind.getBitCount() > readKind.getBitCount() : "read kind must be narrower than stack kind";
                if (readKind.isUnsigned()) {
                    // needed or another op may illegally sign-extend
                    value = kit.unique(new ZeroExtendNode(value, stackKind.getBitCount()));
                } else {
                    value = kit.unique(new SignExtendNode(value, stackKind.getBitCount()));
                }
            } else if (readKind.isObject()) {
                value = kit.unboxHandle(value);
            }
            args.add(Pair.create(value, type));
        }
    } else if (callVariant == CallVariant.VA_LIST) {
        ValueNode valist = kit.loadLocal(javaIndex, metaAccess.lookupJavaType(WordBase.class).getJavaKind());
        for (int i = 0; i < count; i++) {
            ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
            JavaKind loadKind = type.getJavaKind();
            if (loadKind.isObject()) {
                loadKind = providers.getWordTypes().getWordKind();
            }
            ValueNode value = kit.append(new VaListNextArgNode(loadKind, valist));
            if (type.getJavaKind().isObject()) {
                value = kit.unboxHandle(value);
            }
            args.add(Pair.create(value, type));
        }
    } else {
        throw VMError.unsupportedFeature("Call variant: " + callVariant);
    }
    return args;
}
Also used : NewInstanceNode(org.graalvm.compiler.nodes.java.NewInstanceNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) Constant(jdk.vm.ci.meta.Constant) JavaConstant(jdk.vm.ci.meta.JavaConstant) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) CInterfaceReadNode(com.oracle.svm.core.graal.nodes.CInterfaceReadNode) ArrayList(java.util.ArrayList) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) JNIValue(com.oracle.svm.jni.nativeapi.JNIValue) LocationIdentity(org.graalvm.word.LocationIdentity) JNIObjectHandle(com.oracle.svm.jni.nativeapi.JNIObjectHandle) Pair(org.graalvm.collections.Pair) JavaKind(jdk.vm.ci.meta.JavaKind) VaListNextArgNode(com.oracle.svm.core.graal.nodes.VaListNextArgNode) Stamp(org.graalvm.compiler.core.common.type.Stamp) ObjectEqualsNode(org.graalvm.compiler.nodes.calc.ObjectEqualsNode) StructFieldInfo(com.oracle.svm.hosted.c.info.StructFieldInfo) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) JNIMethodId(com.oracle.svm.jni.nativeapi.JNIMethodId) FloatConvertNode(org.graalvm.compiler.nodes.calc.FloatConvertNode) OffsetAddressNode(org.graalvm.compiler.nodes.memory.address.OffsetAddressNode) JNIEnvironment(com.oracle.svm.jni.nativeapi.JNIEnvironment) ValueNode(org.graalvm.compiler.nodes.ValueNode) MetaAccessProvider(jdk.vm.ci.meta.MetaAccessProvider)

Aggregations

ValuePhiNode (org.graalvm.compiler.nodes.ValuePhiNode)24 ValueNode (org.graalvm.compiler.nodes.ValueNode)18 PhiNode (org.graalvm.compiler.nodes.PhiNode)12 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)11 Node (org.graalvm.compiler.graph.Node)9 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)8 FixedNode (org.graalvm.compiler.nodes.FixedNode)8 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)7 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)6 LogicNode (org.graalvm.compiler.nodes.LogicNode)6 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)5 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)5 EndNode (org.graalvm.compiler.nodes.EndNode)5 JavaKind (jdk.vm.ci.meta.JavaKind)4 IfNode (org.graalvm.compiler.nodes.IfNode)4 ArrayList (java.util.ArrayList)3 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)3 FixedGuardNode (org.graalvm.compiler.nodes.FixedGuardNode)3 LogicConstantNode (org.graalvm.compiler.nodes.LogicConstantNode)3 MergeNode (org.graalvm.compiler.nodes.MergeNode)3