diff --git a/llvm/lib/Support/APFloat.cpp b/llvm/lib/Support/APFloat.cpp --- a/llvm/lib/Support/APFloat.cpp +++ b/llvm/lib/Support/APFloat.cpp @@ -2191,7 +2191,7 @@ if (shift < 0 && isFiniteNonZero()) { int exponentChange = significandMSB() + 1 - fromSemantics.precision; if (exponent + exponentChange < toSemantics.minExponent) - exponentChange = toSemantics.minExponent - exponent; + exponentChange = exponent - toSemantics.minExponent; if (exponentChange < shift) exponentChange = shift; if (exponentChange < 0) { diff --git a/llvm/test/Transforms/InstCombine/fpcast.ll b/llvm/test/Transforms/InstCombine/fpcast.ll --- a/llvm/test/Transforms/InstCombine/fpcast.ll +++ b/llvm/test/Transforms/InstCombine/fpcast.ll @@ -156,3 +156,55 @@ ret half %t2 } +define float @fptrunc_double_to_float_rounding_to_zero0() { +; CHECK-LABEL: @fptrunc_double_to_float_rounding_to_zero0( +; CHECK-NEXT: ret float 0.000000e+00 +; + %trunc = fptrunc double 0x10000001 to float + ret float %trunc +} + +define float @fptrunc_double_to_float_rounding_to_zero1() { +; CHECK-LABEL: @fptrunc_double_to_float_rounding_to_zero1( +; CHECK-NEXT: ret float 0.000000e+00 +; + %trunc = fptrunc double 0x11111111 to float + ret float %trunc +} + +define float @fptrunc_double_to_float_rounding_to_zero2() { +; CHECK-LABEL: @fptrunc_double_to_float_rounding_to_zero2( +; CHECK-NEXT: ret float 0.000000e+00 +; + %trunc = fptrunc double 0x10000000 to float + ret float %trunc +} + +define float @fptrunc_double_to_float_rounding_lower() { +; CHECK-LABEL: @fptrunc_double_to_float_rounding_lower( +; CHECK-NEXT: ret float 0.000000e+00 +; + %den_f = bitcast i32 1 to float + %den_d = fpext float %den_f to double + %div = fdiv double %den_d, 2.0 + %bits = bitcast double %div to i64 + %add = add i64 %bits, 0 + %cast = bitcast i64 %add to double + %trunc = fptrunc double %cast to float + ret float %trunc +} + +define float @fptrunc_double_to_float_rounding_upper() { +; CHECK-LABEL: @fptrunc_double_to_float_rounding_upper( +; CHECK-NEXT: ret float 0x36A0000000000000 +; + %den_f = bitcast i32 1 to float + %den_d = fpext float %den_f to double + %div = fdiv double %den_d, 2.0 + %bits = bitcast double %div to i64 + %add = add i64 %bits, 1 + %cast = bitcast i64 %add to double + %trunc = fptrunc double %cast to float + ret float %trunc +} +