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);
}
}
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);
}
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;
}
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;
}
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);
}
Aggregations