in BoolNode::Ideal, we commute comparisons with constants involved. However, the current code does not allow commuting CmpF and CmpD nodes: https://github.com/openjdk/jdk/blob/38bb8adf4f632b08af15f2d8530b35f05f86a020/src/hotspot/share/opto/subnode.cpp#L1536-L1537
The comment is wrong, however. It does not matter on which side a NaN ends up, the result of the comparison is always false. I assume this was confused with *negating* the test, e.g. const < fp => !(const >= fp) is not valid due to NaNs.
Interestingly, the fcmpg bytecode is already implemented similarly: https://github.com/openjdk/jdk/blob/b73663a2b4fe7049fc0990c1a1e51221640b4e29/src/hotspot/share/opto/parse2.cpp#L2300-L2306
It creates a CmpF3 node with swapped inputs and negates the result (negating here works due to how fcmpg handles NaN (see https://docs.oracle.com/javase/specs/jvms/se24/html/jvms-6.html#jvms-6.5.fcmp_op).
Due to the handling of the fcmpg bytecode, it can be tricky to produce an example where commuting the inputs actually changes something. But when using == or !=, you can come up with simple examples where the current restriction prevents GVN and therefore other optimizations:
int call(float a) {
int x;
int y;
if (a == 0) {
x = 5;
} else {
x = 20;
}
if (0 == a) {
y = 5;
} else {
y = -50;
}
return x + y;
}
The comment is wrong, however. It does not matter on which side a NaN ends up, the result of the comparison is always false. I assume this was confused with *negating* the test, e.g. const < fp => !(const >= fp) is not valid due to NaNs.
Interestingly, the fcmpg bytecode is already implemented similarly: https://github.com/openjdk/jdk/blob/b73663a2b4fe7049fc0990c1a1e51221640b4e29/src/hotspot/share/opto/parse2.cpp#L2300-L2306
It creates a CmpF3 node with swapped inputs and negates the result (negating here works due to how fcmpg handles NaN (see https://docs.oracle.com/javase/specs/jvms/se24/html/jvms-6.html#jvms-6.5.fcmp_op).
Due to the handling of the fcmpg bytecode, it can be tricky to produce an example where commuting the inputs actually changes something. But when using == or !=, you can come up with simple examples where the current restriction prevents GVN and therefore other optimizations:
int call(float a) {
int x;
int y;
if (a == 0) {
x = 5;
} else {
x = 20;
}
if (0 == a) {
y = 5;
} else {
y = -50;
}
return x + y;
}