Skip to content

Commit ce46649

Browse files
author
Robin Kruppe
committed
Clean up
1 parent 0a843df commit ce46649

File tree

1 file changed

+26
-32
lines changed

1 file changed

+26
-32
lines changed

src/librustc_trans/mir/rvalue.rs

+26-32
Original file line numberDiff line numberDiff line change
@@ -878,18 +878,11 @@ fn cast_float_to_int(bcx: &Builder,
878878
// we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
879879
// This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
880880
fn compute_clamp_bounds<F: Float>(signed: bool, int_ty: Type) -> (u128, u128) {
881-
let f_min = if signed {
882-
let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
883-
assert_eq!(rounded_min.status, Status::OK);
884-
rounded_min.value
885-
} else {
886-
F::ZERO
887-
};
888-
881+
let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
882+
assert_eq!(rounded_min.status, Status::OK);
889883
let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
890884
assert!(rounded_max.value.is_finite());
891-
892-
(f_min.to_bits(), rounded_max.value.to_bits())
885+
(rounded_min.value.to_bits(), rounded_max.value.to_bits())
893886
}
894887
fn int_max(signed: bool, int_ty: Type) -> u128 {
895888
let shift_amount = 128 - int_ty.int_width();
@@ -906,11 +899,6 @@ fn cast_float_to_int(bcx: &Builder,
906899
0
907900
}
908901
}
909-
let (f_min, f_max) = match float_ty.float_width() {
910-
32 => compute_clamp_bounds::<ieee::Single>(signed, int_ty),
911-
64 => compute_clamp_bounds::<ieee::Double>(signed, int_ty),
912-
n => bug!("unsupported float width {}", n),
913-
};
914902
let float_bits_to_llval = |bits| {
915903
let bits_llval = match float_ty.float_width() {
916904
32 => C_u32(bcx.ccx, bits as u32),
@@ -919,6 +907,11 @@ fn cast_float_to_int(bcx: &Builder,
919907
};
920908
consts::bitcast(bits_llval, float_ty)
921909
};
910+
let (f_min, f_max) = match float_ty.float_width() {
911+
32 => compute_clamp_bounds::<ieee::Single>(signed, int_ty),
912+
64 => compute_clamp_bounds::<ieee::Double>(signed, int_ty),
913+
n => bug!("unsupported float width {}", n),
914+
};
922915
let f_min = float_bits_to_llval(f_min);
923916
let f_max = float_bits_to_llval(f_max);
924917
// To implement saturation, we perform the following steps:
@@ -935,45 +928,46 @@ fn cast_float_to_int(bcx: &Builder,
935928
// undef does not introduce any non-determinism either.
936929
// More importantly, the above procedure correctly implements saturating conversion.
937930
// Proof (sketch):
938-
// If x is NaN, 0 is trivially returned.
931+
// If x is NaN, 0 is returned by definition.
939932
// Otherwise, x is finite or infinite and thus can be compared with f_min and f_max.
940933
// This yields three cases to consider:
941934
// (1) if x in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
942935
// saturating conversion for inputs in that range.
943936
// (2) if x > f_max, then x is larger than int_ty::MAX. This holds even if f_max is rounded
944937
// (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger
945-
// than int_ty::MAX. Because x is larger than int_ty::MAX, the return value is correct.
938+
// than int_ty::MAX. Because x is larger than int_ty::MAX, the return value of int_ty::MAX
939+
// is correct.
946940
// (3) if x < f_min, then x is smaller than int_ty::MIN. As shown earlier, f_min exactly equals
947-
// int_ty::MIN and therefore the return value of int_ty::MIN is immediately correct.
941+
// int_ty::MIN and therefore the return value of int_ty::MIN is correct.
948942
// QED.
949943

950944
// Step 1 was already performed above.
951945

952-
// Step 2: We use two comparisons and two selects, with s1 being the result:
953-
// %less = fcmp ult %x, %f_min
946+
// Step 2: We use two comparisons and two selects, with %s1 being the result:
947+
// %less_or_nan = fcmp ult %x, %f_min
954948
// %greater = fcmp olt %x, %f_max
955-
// %s0 = select %less, int_ty::MIN, %fptosi_result
949+
// %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result
956950
// %s1 = select %greater, int_ty::MAX, %s0
957-
// Note that %less uses an *unordered* comparison. This comparison is true if the operands are
958-
// not comparable (i.e., if x is NaN). The unordered comparison ensures that s1 becomes
959-
// int_ty::MIN if x is NaN.
960-
// Performance note: It can be lowered to a flipped comparison and a negation (and the negation
961-
// can be merged into the select), so it not necessarily any more expensive than a ordered
962-
// ("normal") comparison. Whether these optimizations will be performed is ultimately up to the
963-
// backend but at least x86 does that.
964-
let less = bcx.fcmp(llvm::RealULT, x, f_min);
951+
// Note that %less_or_nan uses an *unordered* comparison. This comparison is true if the
952+
// operands are not comparable (i.e., if x is NaN). The unordered comparison ensures that s1
953+
// becomes int_ty::MIN if x is NaN.
954+
// Performance note: Unordered comparison can be lowered to a "flipped" comparison and a
955+
// negation, and the negation can be merged into the select. Therefore, it not necessarily any
956+
// more expensive than a ordered ("normal") comparison. Whether these optimizations will be
957+
// performed is ultimately up to the backend, but at least x86 does perform them.
958+
let less_or_nan = bcx.fcmp(llvm::RealULT, x, f_min);
965959
let greater = bcx.fcmp(llvm::RealOGT, x, f_max);
966-
let int_max = C_big_integral(int_ty, int_max(signed, int_ty) as u128);
960+
let int_max = C_big_integral(int_ty, int_max(signed, int_ty));
967961
let int_min = C_big_integral(int_ty, int_min(signed, int_ty) as u128);
968-
let s0 = bcx.select(less, int_min, fptosui_result);
962+
let s0 = bcx.select(less_or_nan, int_min, fptosui_result);
969963
let s1 = bcx.select(greater, int_max, s0);
970964

971965
// Step 3: NaN replacement.
972966
// For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
973967
// Therefore we only need to execute this step for signed integer types.
974968
if signed {
975969
// LLVM has no isNaN predicate, so we use (x == x) instead
976-
bcx.select(bcx.fcmp(llvm::RealOEQ, x, x), s1, C_big_integral(int_ty, 0))
970+
bcx.select(bcx.fcmp(llvm::RealOEQ, x, x), s1, C_uint(int_ty, 0))
977971
} else {
978972
s1
979973
}

0 commit comments

Comments
 (0)