Skip to content

Commit 00cf640

Browse files
committed
[GR-43958] Fix stamp logic in CopySignNode.
PullRequest: graal/13686
2 parents 4a9636e + 564a6c6 commit 00cf640

File tree

3 files changed

+56
-23
lines changed

3 files changed

+56
-23
lines changed

compiler/src/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MathCopySignStampTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,22 @@ public void testFloatCopySign() throws InvalidInstalledCodeException {
9090
}
9191
}
9292

93+
public static int badCopyStampGR43958(short magnitude) {
94+
/*
95+
* Previously the stamp of the copySign would be incorrect.
96+
*/
97+
return (short) Math.copySign(magnitude, -942.5804f);
98+
}
99+
100+
@Test
101+
public void testGR43958() throws InvalidInstalledCodeException {
102+
short[] shortValues = {42, -42, 95};
103+
for (short magnitude : shortValues) {
104+
InstalledCode code = getCode(getResolvedJavaMethod("badCopyStampGR43958"), null, true);
105+
Assert.assertEquals(badCopyStampGR43958(magnitude), (int) code.executeVarargs(magnitude), 0);
106+
}
107+
}
108+
93109
private static final double[] doubleValues = {
94110
0.0d,
95111
-0.0d,

compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CopySignNode.java

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -51,36 +51,52 @@ public CopySignNode(ValueNode magnitude, ValueNode sign) {
5151
super(TYPE, computeStamp(magnitude.stamp(NodeView.DEFAULT), sign.stamp(NodeView.DEFAULT)), magnitude, sign);
5252
}
5353

54-
public static Stamp computeStamp(Stamp stampX, Stamp stampY) {
55-
FloatStamp floatStampX = (FloatStamp) stampX;
56-
FloatStamp floatStampY = (FloatStamp) stampY;
57-
if (floatStampX.isNaN()) {
58-
return stampX;
54+
public static Stamp computeStamp(Stamp magnitude, Stamp sign) {
55+
FloatStamp magnitudeStamp = (FloatStamp) magnitude;
56+
FloatStamp signStamp = (FloatStamp) sign;
57+
if (magnitudeStamp.isNaN()) {
58+
return magnitude;
5959
}
60-
if (floatStampY.isNonNaN()) {
61-
if (floatStampY.lowerBound() > 0) {
62-
if (floatStampX.lowerBound() > 0) {
63-
return floatStampX;
60+
if (signStamp.isNonNaN()) {
61+
if (signStamp.lowerBound() > 0) {
62+
// the end result will be non-negative
63+
if (magnitudeStamp.lowerBound() > 0) {
64+
// We know the entire range is above 0: leave it unchanged.
65+
return magnitudeStamp;
6466
}
65-
if (floatStampX.upperBound() < 0) {
66-
return new FloatStamp(floatStampX.getBits(), -floatStampX.upperBound(), -floatStampX.lowerBound(), floatStampX.isNonNaN());
67+
if (magnitudeStamp.upperBound() < 0) {
68+
// We know that the entire range is below 0
69+
// flip [lower, upper] to [-upper, -lower]
70+
return new FloatStamp(magnitudeStamp.getBits(), -magnitudeStamp.upperBound(), -magnitudeStamp.lowerBound(), magnitudeStamp.isNonNaN());
6771
}
68-
return new FloatStamp(floatStampX.getBits(), Math.min(-floatStampX.lowerBound(), floatStampX.upperBound()),
69-
Math.max(-floatStampX.lowerBound(), floatStampX.upperBound()), floatStampX.isNonNaN());
72+
// We know lowerBound <= 0 and upperBound >= 0:
73+
// the new range is [0, Math.max(-lower, upper)]
74+
return new FloatStamp(magnitudeStamp.getBits(), 0,
75+
Math.max(-magnitudeStamp.lowerBound(), magnitudeStamp.upperBound()), magnitudeStamp.isNonNaN());
7076
}
71-
if (floatStampY.upperBound() < 0) {
72-
if (floatStampX.upperBound() < 0) {
73-
return floatStampX;
77+
if (signStamp.upperBound() < 0) {
78+
// the result will be non-positive
79+
if (magnitudeStamp.upperBound() < 0) {
80+
// We know the entire range is below 0: leave it unchanged.
81+
return magnitudeStamp;
7482
}
75-
if (floatStampX.lowerBound() > 0) {
76-
return new FloatStamp(floatStampX.getBits(), -floatStampX.upperBound(), -floatStampX.lowerBound(), floatStampX.isNonNaN());
83+
if (magnitudeStamp.lowerBound() > 0) {
84+
// We know that the entire range is above 0
85+
// flip [lower, upper] to [-upper,-lower]
86+
return new FloatStamp(magnitudeStamp.getBits(), -magnitudeStamp.upperBound(), -magnitudeStamp.lowerBound(), magnitudeStamp.isNonNaN());
7787
}
78-
return new FloatStamp(floatStampX.getBits(), Math.min(floatStampX.lowerBound(), -floatStampX.upperBound()),
79-
Math.max(floatStampX.lowerBound(), -floatStampX.upperBound()), floatStampX.isNonNaN());
88+
// We know lowerBound <= 0 and upperBound >= 0
89+
// the new range is [Math.min(lower, -upper), 0]
90+
return new FloatStamp(magnitudeStamp.getBits(), Math.min(magnitudeStamp.lowerBound(), -magnitudeStamp.upperBound()),
91+
0, magnitudeStamp.isNonNaN());
8092
}
8193
}
82-
return new FloatStamp(floatStampX.getBits(), Math.min(floatStampX.lowerBound(), -floatStampX.upperBound()), Math.max(-floatStampX.lowerBound(), floatStampX.upperBound()),
83-
floatStampX.isNonNaN());
94+
/*
95+
* We have no information on whether the range will be flipped or not. Hence, we have to
96+
* expand the result to be the union of [lower, upper] and [-upper, -lower].
97+
*/
98+
return new FloatStamp(magnitudeStamp.getBits(), Math.min(magnitudeStamp.lowerBound(), -magnitudeStamp.upperBound()), Math.max(-magnitudeStamp.lowerBound(), magnitudeStamp.upperBound()),
99+
magnitudeStamp.isNonNaN());
84100
}
85101

86102
@Override

compiler/src/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignumNode.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ private static Stamp computeStamp(Stamp stamp) {
6767
return new FloatStamp(floatStamp.getBits(), -1.0D, -1.0D, true);
6868
}
6969
}
70-
FloatStamp result = new FloatStamp(floatStamp.getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, !floatStamp.canBeNaN());
70+
// Initially make an empty stamp.
71+
FloatStamp result = new FloatStamp(floatStamp.getBits(), Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, floatStamp.isNonNaN());
7172
if (floatStamp.contains(0.0d)) {
7273
// this also covers stamp.contains(-0.0d)
7374
result = (FloatStamp) result.meet(new FloatStamp(floatStamp.getBits(), 0.0d, 0.0d, true));

0 commit comments

Comments
 (0)