@@ -1068,8 +1068,13 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
1068
1068
1069
1069
let mut result = T :: from_u32 ( 0 ) ;
1070
1070
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:
1073
1078
// `u8::MAX` is `ff` (2 characters), `u16::MAX` is `ffff` (4 characters)
1074
1079
// We can be sure that any src len of 2 would fit in a u8 so we don't need
1075
1080
// to check for overflow.
@@ -1088,9 +1093,14 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, Par
1088
1093
let overflow_err = || PIE { kind : if is_positive { PosOverflow } else { NegOverflow } } ;
1089
1094
1090
1095
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.
1091
1102
let mul = result. checked_mul ( radix) ;
1092
1103
let x = ( c as char ) . to_digit ( radix) . ok_or ( PIE { kind : InvalidDigit } ) ?;
1093
- // multiply done early for performance reasons.
1094
1104
result = mul. ok_or_else ( overflow_err) ?;
1095
1105
result = additive_op ( & result, x) . ok_or_else ( overflow_err) ?;
1096
1106
}
0 commit comments