-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
P3
-
None
-
Affects Version/s: 8u481
-
Component/s: hotspot
-
linux
ADDITIONAL SYSTEM INFORMATION :
Software:
System Software Overview:
System Version: Ubuntu 22.04.4 LTS
Kernel Version: 4.15.0-45-generic
Boot Volume: overlay
Boot Mode: Legacy BIOS
Computer Name: 899309ef3feb
User Name: root
Time since boot: 21 weeks, 2 days, 6 hours, 47 minutes
Hardware:
Hardware Overview:
Model: Unknown
Model Identifier: Unknown
Chip: Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
Total Number of Cores: 40 (10 physical x 2 logical)
Memory: 125Gi
System Firmware Version: Unknown
A DESCRIPTION OF THE PROBLEM :
I have encountered a bug where the C2 JIT compiler performs an incorrect algebraic simplification for floating-point subtraction, leading to a violation of IEEE 754 semantics regarding signed zeros.
Mathematically, the expression 0 - (0 - x) equals x. However, in IEEE 754 floating-point arithmetic, this identity does not hold when x is -0.0.
Given f = -0.0f:
Inner expression: 0.0f - (-0.0f) results in +0.0f.
Outer expression: 0.0f - (+0.0f) results in +0.0f.
Therefore, the expected result is positive zero (0.0f, raw bits 0).
However, when the code is executed frequently enough to trigger C2 compilation, the JVM returns negative zero (-0.0f, raw bits 0x80000000 / -2147483648).
This suggests that the C2 optimizer is applying an identity transformation (likely folding 0 - (0 - val) to val) without checking for the special case of signed zero, which is required by the Java Language Specification.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile the attached source code Test.java.
2. Run it with java -Xcomp Test.
---------- BEGIN SOURCE ----------
class Test {
static float testFloat(float f) {
return ((Float) (0 - (0 - f)));
}
public static void main(String[] args) {
for (int k = 0; k < 101; k++) {
for (int i = 0; i < 10000; i++) {
int floatRes = Float.floatToIntBits(testFloat(((float) (-0.0))));
if (floatRes != 0) {
throw new RuntimeException("Invalid result: " + ((long) (floatRes)));
}
}
}
}
}
---------- END SOURCE ----------
FREQUENCY :
ALWAYS
Software:
System Software Overview:
System Version: Ubuntu 22.04.4 LTS
Kernel Version: 4.15.0-45-generic
Boot Volume: overlay
Boot Mode: Legacy BIOS
Computer Name: 899309ef3feb
User Name: root
Time since boot: 21 weeks, 2 days, 6 hours, 47 minutes
Hardware:
Hardware Overview:
Model: Unknown
Model Identifier: Unknown
Chip: Intel(R) Xeon(R) CPU E5-2640 v4 @ 2.40GHz
Total Number of Cores: 40 (10 physical x 2 logical)
Memory: 125Gi
System Firmware Version: Unknown
A DESCRIPTION OF THE PROBLEM :
I have encountered a bug where the C2 JIT compiler performs an incorrect algebraic simplification for floating-point subtraction, leading to a violation of IEEE 754 semantics regarding signed zeros.
Mathematically, the expression 0 - (0 - x) equals x. However, in IEEE 754 floating-point arithmetic, this identity does not hold when x is -0.0.
Given f = -0.0f:
Inner expression: 0.0f - (-0.0f) results in +0.0f.
Outer expression: 0.0f - (+0.0f) results in +0.0f.
Therefore, the expected result is positive zero (0.0f, raw bits 0).
However, when the code is executed frequently enough to trigger C2 compilation, the JVM returns negative zero (-0.0f, raw bits 0x80000000 / -2147483648).
This suggests that the C2 optimizer is applying an identity transformation (likely folding 0 - (0 - val) to val) without checking for the special case of signed zero, which is required by the Java Language Specification.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile the attached source code Test.java.
2. Run it with java -Xcomp Test.
---------- BEGIN SOURCE ----------
class Test {
static float testFloat(float f) {
return ((Float) (0 - (0 - f)));
}
public static void main(String[] args) {
for (int k = 0; k < 101; k++) {
for (int i = 0; i < 10000; i++) {
int floatRes = Float.floatToIntBits(testFloat(((float) (-0.0))));
if (floatRes != 0) {
throw new RuntimeException("Invalid result: " + ((long) (floatRes)));
}
}
}
}
}
---------- END SOURCE ----------
FREQUENCY :
ALWAYS