@@ -878,18 +878,11 @@ fn cast_float_to_int(bcx: &Builder,
878
878
// we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
879
879
// This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
880
880
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 ) ;
889
883
let rounded_max = F :: from_u128_r ( int_max ( signed, int_ty) , Round :: TowardZero ) ;
890
884
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 ( ) )
893
886
}
894
887
fn int_max ( signed : bool , int_ty : Type ) -> u128 {
895
888
let shift_amount = 128 - int_ty. int_width ( ) ;
@@ -906,11 +899,6 @@ fn cast_float_to_int(bcx: &Builder,
906
899
0
907
900
}
908
901
}
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
- } ;
914
902
let float_bits_to_llval = |bits| {
915
903
let bits_llval = match float_ty. float_width ( ) {
916
904
32 => C_u32 ( bcx. ccx , bits as u32 ) ,
@@ -919,6 +907,11 @@ fn cast_float_to_int(bcx: &Builder,
919
907
} ;
920
908
consts:: bitcast ( bits_llval, float_ty)
921
909
} ;
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
+ } ;
922
915
let f_min = float_bits_to_llval ( f_min) ;
923
916
let f_max = float_bits_to_llval ( f_max) ;
924
917
// To implement saturation, we perform the following steps:
@@ -935,45 +928,46 @@ fn cast_float_to_int(bcx: &Builder,
935
928
// undef does not introduce any non-determinism either.
936
929
// More importantly, the above procedure correctly implements saturating conversion.
937
930
// Proof (sketch):
938
- // If x is NaN, 0 is trivially returned.
931
+ // If x is NaN, 0 is returned by definition .
939
932
// Otherwise, x is finite or infinite and thus can be compared with f_min and f_max.
940
933
// This yields three cases to consider:
941
934
// (1) if x in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
942
935
// saturating conversion for inputs in that range.
943
936
// (2) if x > f_max, then x is larger than int_ty::MAX. This holds even if f_max is rounded
944
937
// (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.
946
940
// (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.
948
942
// QED.
949
943
950
944
// Step 1 was already performed above.
951
945
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
954
948
// %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
956
950
// %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) ;
965
959
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) ) ;
967
961
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) ;
969
963
let s1 = bcx. select ( greater, int_max, s0) ;
970
964
971
965
// Step 3: NaN replacement.
972
966
// For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
973
967
// Therefore we only need to execute this step for signed integer types.
974
968
if signed {
975
969
// 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 ) )
977
971
} else {
978
972
s1
979
973
}
0 commit comments