about summary refs log tree commit diff
diff options
context:
space:
mode:
authorokaneco <47607823+okaneco@users.noreply.github.com>2024-09-23 00:10:18 -0400
committerokaneco <47607823+okaneco@users.noreply.github.com>2024-11-05 22:34:24 -0500
commitd7d67ad14b7c69325a3377bea83b9919398f9588 (patch)
treedbdbad69446da475882ab2faa88bf7acefd17241
parent4a91ff6bb5f36a94d8ebebd9cad1f5f831abbe7a (diff)
downloadrust-d7d67ad14b7c69325a3377bea83b9919398f9588.tar.gz
rust-d7d67ad14b7c69325a3377bea83b9919398f9588.zip
Add new implementation benchmark
Add LONG benchmarks for more comparison between the methods
-rw-r--r--library/core/benches/ascii/is_ascii.rs45
1 files changed, 42 insertions, 3 deletions
diff --git a/library/core/benches/ascii/is_ascii.rs b/library/core/benches/ascii/is_ascii.rs
index 4b2920c5eb4..417d3e0fcbf 100644
--- a/library/core/benches/ascii/is_ascii.rs
+++ b/library/core/benches/ascii/is_ascii.rs
@@ -10,9 +10,12 @@ macro_rules! benches {
         // Ensure we benchmark cases where the functions are called with strings
         // that are not perfectly aligned or have a length which is not a
         // multiple of size_of::<usize>() (or both)
-        benches!(mod unaligned_head MEDIUM[1..] $($name $arg $body)+);
-        benches!(mod unaligned_tail MEDIUM[..(MEDIUM.len() - 1)] $($name $arg $body)+);
-        benches!(mod unaligned_both MEDIUM[1..(MEDIUM.len() - 1)] $($name $arg $body)+);
+        benches!(mod unaligned_head_medium MEDIUM[1..] $($name $arg $body)+);
+        benches!(mod unaligned_tail_medium MEDIUM[..(MEDIUM.len() - 1)] $($name $arg $body)+);
+        benches!(mod unaligned_both_medium MEDIUM[1..(MEDIUM.len() - 1)] $($name $arg $body)+);
+        benches!(mod unaligned_head_long LONG[1..] $($name $arg $body)+);
+        benches!(mod unaligned_tail_long LONG[..(LONG.len() - 1)] $($name $arg $body)+);
+        benches!(mod unaligned_both_long LONG[1..(LONG.len() - 1)] $($name $arg $body)+);
     };
 
     (mod $mod_name: ident $input: ident [$range: expr] $($name: ident $arg: ident $body: block)+) => {
@@ -49,6 +52,42 @@ benches! {
     fn case03_align_to_unrolled(bytes: &[u8]) {
         is_ascii_align_to_unrolled(bytes)
     }
+
+    fn case04_while_loop(bytes: &[u8]) {
+        // Constant chosen to enable `pmovmskb` instruction on x86-64
+        const N: usize = 32;
+
+        let mut i = 0;
+
+        while i + N <= bytes.len() {
+            let chunk_end = i + N;
+
+            // Get LLVM to produce a `pmovmskb` instruction on x86-64 which
+            // creates a mask from the most significant bit of each byte.
+            // ASCII bytes are less than 128 (0x80), so their most significant
+            // bit is unset. Thus, detecting non-ASCII bytes can be done in one
+            // instruction.
+            let mut count = 0;
+            while i < chunk_end {
+                count += (bytes[i] <= 127) as u8;
+                i += 1;
+            }
+
+            // All bytes should be <= 127 so count is equal to chunk size.
+            if count != N as u8 {
+                return false;
+            }
+        }
+
+        // Process the remaining `bytes.len() % N` bytes.
+        let mut is_ascii = true;
+        while i < bytes.len() {
+            is_ascii &= bytes[i] <= 127;
+            i += 1;
+        }
+
+        is_ascii
+    }
 }
 
 // These are separate since it's easier to debug errors if they don't go through