diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp index b3ac0a4a1b0..d4e76950503 100644 --- a/src/hotspot/share/opto/divnode.cpp +++ b/src/hotspot/share/opto/divnode.cpp @@ -825,6 +825,29 @@ const Type* DivHFNode::Value(PhaseGVN* phase) const { if (t1->base() == Type::HalfFloatCon && t2->base() == Type::HalfFloatCon) { + // IEEE 754 floating point comparison treats 0.0 and -0.0 as equals. + + // Division of a zero by a zero results in NaN. + if (t1->getf() == 0.0f && t2->getf() == 0.0f) { + return TypeH::make(NAN); + } + + // As per C++ standard section 7.6.5 (expr.mul), behavior is undefined only if + // the second operand is 0.0. In all other situations, we can expect a standard-compliant + // C++ compiler to generate code following IEEE 754 semantics. + if (t2->getf() == 0.0) { + // If either operand is NaN, the result is NaN + if (g_isnan(t1->getf())) { + return TypeH::make(NAN); + } else { + // Division of a nonzero finite value by a zero results in a signed infinity. Also, + // division of an infinity by a finite value results in a signed infinity. + bool res_sign_neg = (jint_cast(t1->getf()) < 0) ^ (jint_cast(t2->getf()) < 0); + const TypeF* res = res_sign_neg ? TypeF::NEG_INF : TypeF::POS_INF; + return TypeH::make(res->getf()); + } + } + return TypeH::make(t1->getf() / t2->getf()); }