@@ -1068,8 +1068,13 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
10681068
10691069 let mut result = T :: from_u32 ( 0 ) ;
10701070
1071- if radix <= 16 && digits. len ( ) <= mem:: size_of :: < T > ( ) * 2 - is_signed_ty as usize {
1072- // SAFETY: Consider the highest radix of 16:
1071+ if intrinsics:: likely (
1072+ radix <= 16 && digits. len ( ) <= mem:: size_of :: < T > ( ) * 2 - is_signed_ty as usize ,
1073+ ) {
1074+ // SAFETY: We can take this fast path when `radix.pow(digits.len()) - 1 <= T::MAX`
1075+ // but the condition above is a faster (conservative) approximation of this.
1076+ //
1077+ // Consider the highest radix of 16:
10731078 // `u8::MAX` is `ff` (2 characters), `u16::MAX` is `ffff` (4 characters)
10741079 // We can be sure that any src len of 2 would fit in a u8 so we don't need
10751080 // to check for overflow.
@@ -1088,9 +1093,14 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
10881093 let overflow_err = || PIE { kind : if is_positive { PosOverflow } else { NegOverflow } } ;
10891094
10901095 for & c in digits {
1096+ // When `radix` is passed in as a literal, rather than doing a slow `imul`
1097+ // then the compiler can use a shift if `radix` is a power of 2.
1098+ // (*10 can also be turned into *8 + *2).
1099+ // When the compiler can't use these optimisations,
1100+ // there is a latency of several cycles so doing the
1101+ // multiply before we need to use the result helps.
10911102 let mul = result. checked_mul ( radix) ;
10921103 let x = ( c as char ) . to_digit ( radix) . ok_or ( PIE { kind : InvalidDigit } ) ?;
1093- // multiply done early for performance reasons.
10941104 result = mul. ok_or_else ( overflow_err) ?;
10951105 result = additive_op ( & result, x) . ok_or_else ( overflow_err) ?;
10961106 }
0 commit comments