Extract (f32::MAX + 0.5 ULP) constant
This commit is contained in:
parent
964ba2a6e7
commit
e999e7b8b2
@ -203,3 +203,11 @@ impl ::std::ops::Neg for ConstFloat {
|
|||||||
ConstFloat { bits, ty: self.ty }
|
ConstFloat { bits, ty: self.ty }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is `f32::MAX + (0.5 ULP)` as an integer. Numbers greater or equal to this
|
||||||
|
/// are rounded to infinity when converted to `f32`.
|
||||||
|
///
|
||||||
|
/// NB: Computed as maximum significand with an extra 1 bit added (for the half ULP)
|
||||||
|
/// shifted by the maximum exponent (accounting for normalization).
|
||||||
|
pub const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
|
||||||
|
<< (Single::MAX_EXP - Single::PRECISION as i16);
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use llvm::{self, ValueRef};
|
use llvm::{self, ValueRef};
|
||||||
use rustc::middle::const_val::{ConstEvalErr, ConstVal, ErrKind};
|
use rustc::middle::const_val::{ConstEvalErr, ConstVal, ErrKind};
|
||||||
use rustc_const_math::ConstInt::*;
|
use rustc_const_math::ConstInt::*;
|
||||||
use rustc_const_math::{ConstInt, ConstMathErr};
|
use rustc_const_math::{ConstInt, ConstMathErr, MAX_F32_PLUS_HALF_ULP};
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer::TransNormalize;
|
use rustc::infer::TransNormalize;
|
||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
@ -986,10 +986,10 @@ unsafe fn const_cast_int_to_float(ccx: &CrateContext,
|
|||||||
panic!("could not get z128 value of constant integer {:?}",
|
panic!("could not get z128 value of constant integer {:?}",
|
||||||
Value(llval));
|
Value(llval));
|
||||||
});
|
});
|
||||||
// If this is an u128 cast and the value is > f32::MAX + 0.5 ULP, round up to infinity.
|
|
||||||
if signed {
|
if signed {
|
||||||
llvm::LLVMConstSIToFP(llval, float_ty.to_ref())
|
llvm::LLVMConstSIToFP(llval, float_ty.to_ref())
|
||||||
} else if value >= 0xffffff80000000000000000000000000_u128 && float_ty.float_width() == 32 {
|
} else if float_ty.float_width() == 32 && value >= MAX_F32_PLUS_HALF_ULP {
|
||||||
|
// We're casting to f32 and the value is > f32::MAX + 0.5 ULP -> round up to infinity.
|
||||||
let infinity_bits = C_u32(ccx, ieee::Single::INFINITY.to_bits() as u32);
|
let infinity_bits = C_u32(ccx, ieee::Single::INFINITY.to_bits() as u32);
|
||||||
consts::bitcast(infinity_bits, float_ty)
|
consts::bitcast(infinity_bits, float_ty)
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,6 +16,7 @@ use rustc::mir::tcx::LvalueTy;
|
|||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::middle::lang_items::ExchangeMallocFnLangItem;
|
use rustc::middle::lang_items::ExchangeMallocFnLangItem;
|
||||||
use rustc_apfloat::{ieee, Float, Status, Round};
|
use rustc_apfloat::{ieee, Float, Status, Round};
|
||||||
|
use rustc_const_math::MAX_F32_PLUS_HALF_ULP;
|
||||||
use std::{u128, i128};
|
use std::{u128, i128};
|
||||||
|
|
||||||
use base;
|
use base;
|
||||||
@ -827,9 +828,9 @@ fn cast_int_to_float(bcx: &Builder,
|
|||||||
// LLVM's uitofp produces undef in those cases, so we manually check for that case.
|
// LLVM's uitofp produces undef in those cases, so we manually check for that case.
|
||||||
let is_u128_to_f32 = !signed && int_ty.int_width() == 128 && float_ty.float_width() == 32;
|
let is_u128_to_f32 = !signed && int_ty.int_width() == 128 && float_ty.float_width() == 32;
|
||||||
if is_u128_to_f32 && bcx.sess().opts.debugging_opts.saturating_float_casts {
|
if is_u128_to_f32 && bcx.sess().opts.debugging_opts.saturating_float_casts {
|
||||||
// f32::MAX + 0.5 ULP as u128. All inputs greater or equal to this should be
|
// All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
|
||||||
// rounded to infinity, for everything else LLVM's uitofp works just fine.
|
// and for everything else LLVM's uitofp works just fine.
|
||||||
let max = C_big_integral(int_ty, 0xffffff80000000000000000000000000_u128);
|
let max = C_big_integral(int_ty, MAX_F32_PLUS_HALF_ULP);
|
||||||
let overflow = bcx.icmp(llvm::IntUGE, x, max);
|
let overflow = bcx.icmp(llvm::IntUGE, x, max);
|
||||||
let infinity_bits = C_u32(bcx.ccx, ieee::Single::INFINITY.to_bits() as u32);
|
let infinity_bits = C_u32(bcx.ccx, ieee::Single::INFINITY.to_bits() as u32);
|
||||||
let infinity = consts::bitcast(infinity_bits, float_ty);
|
let infinity = consts::bitcast(infinity_bits, float_ty);
|
||||||
|
Loading…
Reference in New Issue
Block a user