Search in sources :

Example 1 with SubNode

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

the class IntegerSubExactSplitNode method simplify.

@Override
public void simplify(SimplifierTool tool) {
    NodeView view = NodeView.from(tool);
    if (!IntegerStamp.subtractionCanOverflow((IntegerStamp) x.stamp(view), (IntegerStamp) y.stamp(view))) {
        tool.deleteBranch(overflowSuccessor);
        tool.addToWorkList(next);
        SubNode replacement = graph().unique(new SubNode(x, y));
        graph().replaceSplitWithFloating(this, replacement, next);
        tool.addToWorkList(replacement);
    }
}
Also used : SubNode(org.graalvm.compiler.nodes.calc.SubNode) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) NodeView(org.graalvm.compiler.nodes.NodeView)

Example 2 with SubNode

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

the class DefaultJavaLoweringProvider method reconstructArrayIndex.

@Override
public ValueNode reconstructArrayIndex(JavaKind elementKind, AddressNode address) {
    StructuredGraph graph = address.graph();
    ValueNode offset = ((OffsetAddressNode) address).getOffset();
    int base = arrayBaseOffset(elementKind);
    ValueNode scaledIndex = graph.unique(new SubNode(offset, ConstantNode.forIntegerStamp(offset.stamp(NodeView.DEFAULT), base, graph)));
    int shift = CodeUtil.log2(arrayScalingFactor(elementKind));
    ValueNode ret = graph.unique(new RightShiftNode(scaledIndex, ConstantNode.forInt(shift, graph)));
    return IntegerConvertNode.convert(ret, StampFactory.forKind(JavaKind.Int), graph, NodeView.DEFAULT);
}
Also used : StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) OffsetAddressNode(org.graalvm.compiler.nodes.memory.address.OffsetAddressNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) RightShiftNode(org.graalvm.compiler.nodes.calc.RightShiftNode)

Example 3 with SubNode

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

the class UnsafeAutomaticSubstitutionProcessor method processArrayIndexShift.

/**
 * Try to compute the arrayIndexShift. Return true if successful, false otherwise.
 */
private boolean processArrayIndexShift(ResolvedJavaType type, Class<?> arrayClass, ValueNode indexScaleValue, boolean silentFailure) {
    NodeIterable<MethodCallTargetNode> loadMethodCallTargetUsages = indexScaleValue.usages().filter(MethodCallTargetNode.class);
    for (MethodCallTargetNode methodCallTarget : loadMethodCallTargetUsages) {
        /* Iterate over all the calls that use the index scale value. */
        if (isInvokeTo(methodCallTarget.invoke(), integerNumberOfLeadingZerosMethod)) {
            /*
                 * Found a call to Integer.numberOfLeadingZeros(int) that uses the array index scale
                 * field. Check if it is used to calculate the array index shift, i.e., log2 of the
                 * array index scale.
                 */
            ResolvedJavaField indexShiftField = null;
            List<String> unsuccessfulReasons = new ArrayList<>();
            Invoke numberOfLeadingZerosInvoke = methodCallTarget.invoke();
            NodeIterable<SubNode> numberOfLeadingZerosInvokeSubUsages = numberOfLeadingZerosInvoke.asNode().usages().filter(SubNode.class);
            if (numberOfLeadingZerosInvokeSubUsages.count() == 1) {
                /*
                     * Found the SubNode. Determine if it computes the array index shift. If so find
                     * the field where the value is stored.
                     */
                SubNode subNode = numberOfLeadingZerosInvokeSubUsages.first();
                if (subNodeComputesLog2(subNode, numberOfLeadingZerosInvoke)) {
                    indexShiftField = extractValueStoreField(subNode, unsuccessfulReasons);
                } else {
                    unsuccessfulReasons.add("The index array scale value provided by " + indexScaleValue + " is not used to calculate the array index shift.");
                }
            } else {
                unsuccessfulReasons.add("The call to " + methodCallTarget.targetMethod().format("%H.%n(%p)") + " has multiple uses.");
            }
            if (indexShiftField != null) {
                ResolvedJavaField finalIndexShiftField = indexShiftField;
                Supplier<ComputedValueField> supplier = () -> new ComputedValueField(finalIndexShiftField, null, Kind.ArrayIndexShift, arrayClass, null, true);
                if (tryAutomaticRecomputation(indexShiftField, Kind.ArrayIndexShift, supplier)) {
                    reportSuccessfulAutomaticRecomputation(Kind.ArrayIndexShift, indexShiftField, arrayClass.getCanonicalName());
                    return true;
                }
            } else {
                if (!silentFailure) {
                    reportUnsuccessfulAutomaticRecomputation(type, numberOfLeadingZerosInvoke, Kind.ArrayIndexShift, unsuccessfulReasons);
                }
            }
        }
    }
    return false;
}
Also used : MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) ArrayList(java.util.ArrayList) ResolvedJavaField(jdk.vm.ci.meta.ResolvedJavaField) Invoke(org.graalvm.compiler.nodes.Invoke)

Example 4 with SubNode

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

the class UnsafeAutomaticSubstitutionProcessor method extractValueStoreField.

/**
 * If the value produced by valueNode is stored into a static final field then that field is
 * returned. If the field is either not static or not final the method returns null and the
 * reason is recorded in the unsuccessfulReasons parameter.
 */
private static ResolvedJavaField extractValueStoreField(ValueNode valueNode, List<String> unsuccessfulReasons) {
    ResolvedJavaField offsetField = null;
    NodeIterable<Node> valueNodeUsages = valueNode.usages();
    NodeIterable<StoreFieldNode> valueNodeStoreFieldUsages = valueNodeUsages.filter(StoreFieldNode.class);
    NodeIterable<SignExtendNode> valueNodeSignExtendUsages = valueNodeUsages.filter(SignExtendNode.class);
    if (valueNodeStoreFieldUsages.count() == 1) {
        offsetField = valueNodeStoreFieldUsages.first().field();
    } else if (valueNodeSignExtendUsages.count() == 1) {
        SignExtendNode signExtendNode = valueNodeSignExtendUsages.first();
        NodeIterable<StoreFieldNode> signExtendFieldStoreUsages = signExtendNode.usages().filter(StoreFieldNode.class);
        if (signExtendFieldStoreUsages.count() == 1) {
            offsetField = signExtendFieldStoreUsages.first().field();
        }
    }
    if (offsetField != null) {
        if (offsetField.isStatic() && offsetField.isFinal()) {
            return offsetField;
        } else {
            if (!offsetField.isStatic()) {
                unsuccessfulReasons.add("The offset field " + offsetField.format("%H.%n") + " is not static.");
            }
            if (!offsetField.isFinal()) {
                unsuccessfulReasons.add("The offset field " + offsetField.format("%H.%n") + " is not final.");
            }
        }
    } else {
        String producer;
        String operation;
        if (valueNode instanceof Invoke) {
            Invoke invokeNode = (Invoke) valueNode;
            producer = "call to " + invokeNode.callTarget().targetMethod().format("%H.%n(%p)");
            operation = "call";
        } else if (valueNode instanceof SubNode) {
            producer = "subtraction operation " + valueNode;
            operation = "subtraction";
        } else {
            throw VMError.shouldNotReachHere();
        }
        String message = "Could not determine the field where the value produced by the " + producer + " is stored. The " + operation + " is not directly followed by a field store or by a sign extend node followed directly by a field store. ";
        unsuccessfulReasons.add(message);
    }
    return null;
}
Also used : StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) NodeIterable(org.graalvm.compiler.graph.iterators.NodeIterable) SubNode(org.graalvm.compiler.nodes.calc.SubNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) Node(org.graalvm.compiler.graph.Node) ResolvedJavaField(jdk.vm.ci.meta.ResolvedJavaField) Invoke(org.graalvm.compiler.nodes.Invoke)

Example 5 with SubNode

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

the class LoopFragmentInside method insertWithinAfter.

/**
 * Duplicate the body within the loop after the current copy copy of the body.
 *
 * @param loop
 * @param updateLimit true if the iteration limit should be adjusted.
 */
public void insertWithinAfter(LoopEx loop, boolean updateLimit) {
    assert isDuplicate() && original().loop() == loop;
    patchNodes(dataFixWithinAfter);
    /*
         * Collect any new back edges values before updating them since they might reference each
         * other.
         */
    LoopBeginNode mainLoopBegin = loop.loopBegin();
    ArrayList<ValueNode> backedgeValues = new ArrayList<>();
    for (PhiNode mainPhiNode : mainLoopBegin.phis()) {
        ValueNode duplicatedNode = getDuplicatedNode(mainPhiNode.valueAt(1));
        if (duplicatedNode == null) {
            if (mainLoopBegin.isPhiAtMerge(mainPhiNode.valueAt(1))) {
                duplicatedNode = ((PhiNode) (mainPhiNode.valueAt(1))).valueAt(1);
            } else {
                assert mainPhiNode.valueAt(1).isConstant() : mainPhiNode.valueAt(1);
            }
        }
        backedgeValues.add(duplicatedNode);
    }
    int index = 0;
    for (PhiNode mainPhiNode : mainLoopBegin.phis()) {
        ValueNode duplicatedNode = backedgeValues.get(index++);
        if (duplicatedNode != null) {
            mainPhiNode.setValueAt(1, duplicatedNode);
        }
    }
    placeNewSegmentAndCleanup(loop);
    // Remove any safepoints from the original copy leaving only the duplicated one
    assert loop.whole().nodes().filter(SafepointNode.class).count() == nodes().filter(SafepointNode.class).count();
    for (SafepointNode safepoint : loop.whole().nodes().filter(SafepointNode.class)) {
        graph().removeFixed(safepoint);
    }
    int unrollFactor = mainLoopBegin.getUnrollFactor();
    StructuredGraph graph = mainLoopBegin.graph();
    if (updateLimit) {
        // Now use the previous unrollFactor to update the exit condition to power of two
        InductionVariable iv = loop.counted().getCounter();
        CompareNode compareNode = (CompareNode) loop.counted().getLimitTest().condition();
        ValueNode compareBound;
        if (compareNode.getX() == iv.valueNode()) {
            compareBound = compareNode.getY();
        } else if (compareNode.getY() == iv.valueNode()) {
            compareBound = compareNode.getX();
        } else {
            throw GraalError.shouldNotReachHere();
        }
        long originalStride = unrollFactor == 1 ? iv.constantStride() : iv.constantStride() / unrollFactor;
        if (iv.direction() == InductionVariable.Direction.Up) {
            ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(NodeView.DEFAULT), unrollFactor * originalStride));
            ValueNode newLimit = graph.addWithoutUnique(new SubNode(compareBound, aboveVal));
            compareNode.replaceFirstInput(compareBound, newLimit);
        } else if (iv.direction() == InductionVariable.Direction.Down) {
            ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(NodeView.DEFAULT), unrollFactor * -originalStride));
            ValueNode newLimit = graph.addWithoutUnique(new AddNode(compareBound, aboveVal));
            compareNode.replaceFirstInput(compareBound, newLimit);
        }
    }
    mainLoopBegin.setUnrollFactor(unrollFactor * 2);
    mainLoopBegin.setLoopFrequency(mainLoopBegin.loopFrequency() / 2);
    graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "LoopPartialUnroll %s", loop);
    mainLoopBegin.getDebug().dump(DebugContext.VERBOSE_LEVEL, mainLoopBegin.graph(), "After insertWithinAfter %s", mainLoopBegin);
}
Also used : 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) SafepointNode(org.graalvm.compiler.nodes.SafepointNode) ArrayList(java.util.ArrayList) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) AddNode(org.graalvm.compiler.nodes.calc.AddNode)

Aggregations

SubNode (org.graalvm.compiler.nodes.calc.SubNode)6 ValueNode (org.graalvm.compiler.nodes.ValueNode)3 ArrayList (java.util.ArrayList)2 ResolvedJavaField (jdk.vm.ci.meta.ResolvedJavaField)2 IntegerStamp (org.graalvm.compiler.core.common.type.IntegerStamp)2 Invoke (org.graalvm.compiler.nodes.Invoke)2 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)2 AddNode (org.graalvm.compiler.nodes.calc.AddNode)2 MethodCallTargetNode (org.graalvm.compiler.nodes.java.MethodCallTargetNode)2 Stamp (org.graalvm.compiler.core.common.type.Stamp)1 Node (org.graalvm.compiler.graph.Node)1 NodeIterable (org.graalvm.compiler.graph.iterators.NodeIterable)1 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)1 GuardPhiNode (org.graalvm.compiler.nodes.GuardPhiNode)1 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)1 NodeView (org.graalvm.compiler.nodes.NodeView)1 PhiNode (org.graalvm.compiler.nodes.PhiNode)1 SafepointNode (org.graalvm.compiler.nodes.SafepointNode)1 ValuePhiNode (org.graalvm.compiler.nodes.ValuePhiNode)1 CompareNode (org.graalvm.compiler.nodes.calc.CompareNode)1