@@ -2902,7 +2902,7 @@ fn contains_nonascii(v: usize) -> bool {
29022902///
29032903/// - Read the first word with an unaligned load.
29042904/// - Align the pointer, read subsequent words until end with aligned loads.
2905- /// - If there's a tail, the last `usize` from `s` with an unaligned load.
2905+ /// - Read the last `usize` from `s` with an unaligned load.
29062906///
29072907/// If any of these loads produces something for which `contains_nonascii`
29082908/// (above) returns true, then we know the answer is false.
@@ -2949,7 +2949,10 @@ fn is_ascii(s: &[u8]) -> bool {
29492949 // `align_offset` though.
29502950 debug_assert_eq ! ( ( word_ptr as usize ) % mem:: align_of:: <usize >( ) , 0 ) ;
29512951
2952- while byte_pos <= len - USIZE_SIZE {
2952+ // Read subsequent words until the last aligned word, excluding the last
2953+ // aligned word by itself to be done in tail check later, to ensure that
2954+ // tail is always one `usize` at most to extra branch `byte_pos == len`.
2955+ while byte_pos < len - USIZE_SIZE {
29532956 debug_assert ! (
29542957 // Sanity check that the read is in bounds
29552958 ( word_ptr as usize + USIZE_SIZE ) <= ( start. wrapping_add( len) as usize ) &&
@@ -2970,15 +2973,9 @@ fn is_ascii(s: &[u8]) -> bool {
29702973 word_ptr = unsafe { word_ptr. add ( 1 ) } ;
29712974 }
29722975
2973- // If we have anything left over, it should be at-most 1 usize worth of bytes,
2974- // which we check with a read_unaligned.
2975- if byte_pos == len {
2976- return true ;
2977- }
2978-
29792976 // Sanity check to ensure there really is only one `usize` left. This should
29802977 // be guaranteed by our loop condition.
2981- debug_assert ! ( byte_pos < len && len - byte_pos < USIZE_SIZE ) ;
2978+ debug_assert ! ( byte_pos <= len && len - byte_pos <= USIZE_SIZE ) ;
29822979
29832980 // SAFETY: This relies on `len >= USIZE_SIZE`, which we check at the start.
29842981 let last_word = unsafe { ( start. add ( len - USIZE_SIZE ) as * const usize ) . read_unaligned ( ) } ;
0 commit comments