Skip to content

Commit e999e7b

Browse files
author
Robin Kruppe
committed
Extract (f32::MAX + 0.5 ULP) constant
1 parent 964ba2a commit e999e7b

File tree

3 files changed

+15
-6
lines changed

3 files changed

+15
-6
lines changed

src/librustc_const_math/float.rs

+8
Original file line numberDiff line numberDiff line change
@@ -203,3 +203,11 @@ impl ::std::ops::Neg for ConstFloat {
203203
ConstFloat { bits, ty: self.ty }
204204
}
205205
}
206+
207+
/// This is `f32::MAX + (0.5 ULP)` as an integer. Numbers greater or equal to this
208+
/// are rounded to infinity when converted to `f32`.
209+
///
210+
/// NB: Computed as maximum significand with an extra 1 bit added (for the half ULP)
211+
/// shifted by the maximum exponent (accounting for normalization).
212+
pub const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
213+
<< (Single::MAX_EXP - Single::PRECISION as i16);

src/librustc_trans/mir/constant.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use llvm::{self, ValueRef};
1212
use rustc::middle::const_val::{ConstEvalErr, ConstVal, ErrKind};
1313
use rustc_const_math::ConstInt::*;
14-
use rustc_const_math::{ConstInt, ConstMathErr};
14+
use rustc_const_math::{ConstInt, ConstMathErr, MAX_F32_PLUS_HALF_ULP};
1515
use rustc::hir::def_id::DefId;
1616
use rustc::infer::TransNormalize;
1717
use rustc::traits;
@@ -986,10 +986,10 @@ unsafe fn const_cast_int_to_float(ccx: &CrateContext,
986986
panic!("could not get z128 value of constant integer {:?}",
987987
Value(llval));
988988
});
989-
// If this is an u128 cast and the value is > f32::MAX + 0.5 ULP, round up to infinity.
990989
if signed {
991990
llvm::LLVMConstSIToFP(llval, float_ty.to_ref())
992-
} else if value >= 0xffffff80000000000000000000000000_u128 && float_ty.float_width() == 32 {
991+
} else if float_ty.float_width() == 32 && value >= MAX_F32_PLUS_HALF_ULP {
992+
// We're casting to f32 and the value is > f32::MAX + 0.5 ULP -> round up to infinity.
993993
let infinity_bits = C_u32(ccx, ieee::Single::INFINITY.to_bits() as u32);
994994
consts::bitcast(infinity_bits, float_ty)
995995
} else {

src/librustc_trans/mir/rvalue.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use rustc::mir::tcx::LvalueTy;
1616
use rustc::mir;
1717
use rustc::middle::lang_items::ExchangeMallocFnLangItem;
1818
use rustc_apfloat::{ieee, Float, Status, Round};
19+
use rustc_const_math::MAX_F32_PLUS_HALF_ULP;
1920
use std::{u128, i128};
2021

2122
use base;
@@ -827,9 +828,9 @@ fn cast_int_to_float(bcx: &Builder,
827828
// LLVM's uitofp produces undef in those cases, so we manually check for that case.
828829
let is_u128_to_f32 = !signed && int_ty.int_width() == 128 && float_ty.float_width() == 32;
829830
if is_u128_to_f32 && bcx.sess().opts.debugging_opts.saturating_float_casts {
830-
// f32::MAX + 0.5 ULP as u128. All inputs greater or equal to this should be
831-
// rounded to infinity, for everything else LLVM's uitofp works just fine.
832-
let max = C_big_integral(int_ty, 0xffffff80000000000000000000000000_u128);
831+
// All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
832+
// and for everything else LLVM's uitofp works just fine.
833+
let max = C_big_integral(int_ty, MAX_F32_PLUS_HALF_ULP);
833834
let overflow = bcx.icmp(llvm::IntUGE, x, max);
834835
let infinity_bits = C_u32(bcx.ccx, ieee::Single::INFINITY.to_bits() as u32);
835836
let infinity = consts::bitcast(infinity_bits, float_ty);

0 commit comments

Comments
 (0)