Rollup merge of #67328 - rkruppe:simplify-u128-f32-cast, r=matthewjasper
Remove now-redundant range check on u128 -> f32 casts This code was added to avoid UB in LLVM 6 and earlier, but we no longer support those LLVM versions. Since https://reviews.llvm.org/D47807 (released in LLVM 7), uitofp does exactly what we need. Closes #51872
This commit is contained in:
@@ -341,6 +341,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
llval
|
llval
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(CastTy::Int(_), CastTy::Float) => {
|
||||||
|
if signed {
|
||||||
|
bx.sitofp(llval, ll_t_out)
|
||||||
|
} else {
|
||||||
|
bx.uitofp(llval, ll_t_out)
|
||||||
|
}
|
||||||
|
}
|
||||||
(CastTy::Ptr(_), CastTy::Ptr(_)) |
|
(CastTy::Ptr(_), CastTy::Ptr(_)) |
|
||||||
(CastTy::FnPtr, CastTy::Ptr(_)) |
|
(CastTy::FnPtr, CastTy::Ptr(_)) |
|
||||||
(CastTy::RPtr(_), CastTy::Ptr(_)) =>
|
(CastTy::RPtr(_), CastTy::Ptr(_)) =>
|
||||||
@@ -352,8 +359,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
let usize_llval = bx.intcast(llval, bx.cx().type_isize(), signed);
|
let usize_llval = bx.intcast(llval, bx.cx().type_isize(), signed);
|
||||||
bx.inttoptr(usize_llval, ll_t_out)
|
bx.inttoptr(usize_llval, ll_t_out)
|
||||||
}
|
}
|
||||||
(CastTy::Int(_), CastTy::Float) =>
|
|
||||||
cast_int_to_float(&mut bx, signed, llval, ll_t_in, ll_t_out),
|
|
||||||
(CastTy::Float, CastTy::Int(IntTy::I)) =>
|
(CastTy::Float, CastTy::Int(IntTy::I)) =>
|
||||||
cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out),
|
cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out),
|
||||||
(CastTy::Float, CastTy::Int(_)) =>
|
(CastTy::Float, CastTy::Int(_)) =>
|
||||||
@@ -720,40 +725,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast_int_to_float<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|
||||||
bx: &mut Bx,
|
|
||||||
signed: bool,
|
|
||||||
x: Bx::Value,
|
|
||||||
int_ty: Bx::Type,
|
|
||||||
float_ty: Bx::Type
|
|
||||||
) -> Bx::Value {
|
|
||||||
// Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding.
|
|
||||||
// It's only u128 -> f32 that can cause overflows (i.e., should yield infinity).
|
|
||||||
// LLVM's uitofp produces undef in those cases, so we manually check for that case.
|
|
||||||
let is_u128_to_f32 = !signed &&
|
|
||||||
bx.cx().int_width(int_ty) == 128 &&
|
|
||||||
bx.cx().float_width(float_ty) == 32;
|
|
||||||
if is_u128_to_f32 {
|
|
||||||
// All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
|
|
||||||
// and for everything else LLVM's uitofp works just fine.
|
|
||||||
use rustc_apfloat::ieee::Single;
|
|
||||||
const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
|
|
||||||
<< (Single::MAX_EXP - Single::PRECISION as i16);
|
|
||||||
let max = bx.cx().const_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
|
|
||||||
let overflow = bx.icmp(IntPredicate::IntUGE, x, max);
|
|
||||||
let infinity_bits = bx.cx().const_u32(ieee::Single::INFINITY.to_bits() as u32);
|
|
||||||
let infinity = bx.bitcast(infinity_bits, float_ty);
|
|
||||||
let fp = bx.uitofp(x, float_ty);
|
|
||||||
bx.select(overflow, infinity, fp)
|
|
||||||
} else {
|
|
||||||
if signed {
|
|
||||||
bx.sitofp(x, float_ty)
|
|
||||||
} else {
|
|
||||||
bx.uitofp(x, float_ty)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
signed: bool,
|
signed: bool,
|
||||||
|
|||||||
Reference in New Issue
Block a user