diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ed8893ea6..1c35058713 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -379,7 +379,8 @@ jobs: $FEATURES \ --verbose \ -- \ - --skip ui + --skip ui \ + --skip codegen # Only run tests when targetting Linux x86 (32- or 64-bit) - we're # executing on Linux x86_64, so we can't run tests for any non-x86 target. @@ -609,6 +610,28 @@ jobs: matrix.target != 'wasm32-unknown-unknown' && env.ZC_SKIP_CARGO_SEMVER_CHECKS != '1' + codegen: + runs-on: ubuntu-latest + name: Run codegen tests + needs: generate_cache + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + - name: Populate cache + uses: ./.github/actions/cache + - name: Run tests + run: | + set -eo pipefail + sudo apt install -qq llvm + ./cargo.sh +nightly install --quiet cargo-show-asm + RUSTFLAGS="$RUSTFLAGS -Awarnings" ./cargo.sh +nightly test \ + --package zerocopy \ + --target x86_64-unknown-linux-gnu \ + --all-features \ + --verbose \ + --test codegen + coverage: runs-on: ubuntu-latest name: Generate code coverage @@ -631,7 +654,9 @@ jobs: --lcov \ --output-path lcov.info \ --verbose \ - -- --skip ui + -- \ + --skip ui \ + --skip codegen - name: Upload coverage to Codecov uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 with: @@ -988,7 +1013,7 @@ jobs: # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks if: failure() runs-on: ubuntu-latest - needs: [build_test, coverage, kani, check_be_aarch64, check_avr_atmega, check_fmt, check_actions, check_readme, check_versions, check_msrv_is_minimal, check_stale_stderr, generate_cache, check-all-toolchains-tested, check-job-dependencies, check-todo, run-git-hooks, zizmor] + needs: [build_test, codegen, coverage, kani, check_be_aarch64, check_avr_atmega, check_fmt, check_actions, check_readme, check_versions, check_msrv_is_minimal, check_stale_stderr, generate_cache, check-all-toolchains-tested, check-job-dependencies, check-todo, run-git-hooks, zizmor] steps: - name: Mark the job as failed run: exit 1 diff --git a/benches/formats/coco.rs b/benches/formats/coco.rs new file mode 100644 index 0000000000..8da4d78ede --- /dev/null +++ b/benches/formats/coco.rs @@ -0,0 +1,44 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +//! This modules defines two formats similar to the one used to illustrate the +//! examples of [`zerocopy::TryFromBytes`]. The basic structure of these formats +//! is a [`Packet`], which has a parameterizable leading field, followed by +//! two-fixed byte fields, followed by a dynamically sized field. This format is +//! consumed by our benchmarks either as a [`CocoPacket`] (which begins with the +//! leading bytes `0xC0C0`), or a [`LocoPacket`] (which begins two bytes of any +//! value). Both formats share the following qualities which stress-test our +//! benchmarks: +//! +//! - They have a minimum alignment of two. +//! - They have a minimum size of four bytes. +//! - They have an even size. + +use zerocopy_derive::*; + +// The only valid value of this type are the bytes `0xC0C0`. +#[derive(TryFromBytes, KnownLayout, Immutable)] +#[repr(u16)] +pub enum C0C0 { + _XC0C0 = 0xC0C0, +} + +#[derive(FromBytes, KnownLayout, Immutable)] +#[repr(C, align(2))] +pub struct Packet { + magic_number: Magic, + mug_size: u8, + temperature: u8, + marshmallows: [[u8; 2]], +} + +/// A packet begining with the magic number `0xC0C0`. +pub type CocoPacket = Packet; + +/// A packet beginning with any two initialized bytes. +pub type LocoPacket = Packet<[u8; 2]>; diff --git a/benches/ref_from_bytes.rs b/benches/ref_from_bytes.rs new file mode 100644 index 0000000000..c5a7fb3da3 --- /dev/null +++ b/benches/ref_from_bytes.rs @@ -0,0 +1,17 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::FromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8]) -> Option<&format::LocoPacket> { + FromBytes::ref_from_bytes(source).ok() +} diff --git a/benches/ref_from_bytes.x86-64.mca b/benches/ref_from_bytes.x86-64.mca new file mode 100644 index 0000000000..68aea583e4 --- /dev/null +++ b/benches/ref_from_bytes.x86-64.mca @@ -0,0 +1,75 @@ +Iterations: 100 +Instructions: 1800 +Total Cycles: 704 +Total uOps: 2000 + +Dispatch Width: 4 +uOps Per Cycle: 2.84 +IPC: 2.56 +Block RThroughput: 5.0 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 mov rdx, rsi + 1 1 0.33 cmp rsi, 4 + 1 1 0.50 setb al + 1 1 0.33 or al, dil + 1 1 0.33 test al, 1 + 1 1 1.00 je .LBB5_2 + 1 0 0.25 xor eax, eax + 1 1 1.00 U ret + 1 1 0.50 lea rcx, [rdx - 4] + 1 1 0.33 mov rsi, rcx + 1 1 0.33 and rsi, -2 + 1 1 0.33 add rsi, 4 + 1 1 0.50 shr rcx + 1 0 0.25 xor eax, eax + 1 1 0.33 cmp rdx, rsi + 2 2 0.67 cmove rdx, rcx + 2 2 0.67 cmove rax, rdi + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 5.97 5.98 - 6.05 - - + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - 0.97 0.01 - 0.02 - - mov rdx, rsi + - - 0.01 0.02 - 0.97 - - cmp rsi, 4 + - - 0.03 - - 0.97 - - setb al + - - 0.01 0.02 - 0.97 - - or al, dil + - - - 0.98 - 0.02 - - test al, 1 + - - - - - 1.00 - - je .LBB5_2 + - - - - - - - - xor eax, eax + - - - - - 1.00 - - ret + - - 0.98 0.02 - - - - lea rcx, [rdx - 4] + - - 0.01 0.99 - - - - mov rsi, rcx + - - - 0.98 - 0.02 - - and rsi, -2 + - - 0.98 0.01 - 0.01 - - add rsi, 4 + - - 0.99 - - 0.01 - - shr rcx + - - - - - - - - xor eax, eax + - - 0.02 0.97 - 0.01 - - cmp rdx, rsi + - - 0.99 0.99 - 0.02 - - cmove rdx, rcx + - - 0.98 0.99 - 0.03 - - cmove rax, rdi + - - - - - 1.00 - - ret diff --git a/benches/ref_from_bytes_with_elems.rs b/benches/ref_from_bytes_with_elems.rs new file mode 100644 index 0000000000..704e3fdc35 --- /dev/null +++ b/benches/ref_from_bytes_with_elems.rs @@ -0,0 +1,17 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::FromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8], count: usize) -> Option<&format::LocoPacket> { + FromBytes::ref_from_bytes_with_elems(source, count).ok() +} diff --git a/benches/ref_from_bytes_with_elems.x86-64.mca b/benches/ref_from_bytes_with_elems.x86-64.mca new file mode 100644 index 0000000000..4a67974f1a --- /dev/null +++ b/benches/ref_from_bytes_with_elems.x86-64.mca @@ -0,0 +1,65 @@ +Iterations: 100 +Instructions: 1300 +Total Cycles: 439 +Total uOps: 1400 + +Dispatch Width: 4 +uOps Per Cycle: 3.19 +IPC: 2.96 +Block RThroughput: 3.5 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 movabs rax, 9223372036854775805 + 1 1 0.33 cmp rdx, rax + 2 2 1.00 seta cl + 1 1 0.33 mov rax, rdi + 1 1 0.33 or dil, cl + 1 1 0.33 test dil, 1 + 1 1 1.00 jne .LBB5_2 + 1 1 0.50 lea rcx, [2*rdx + 4] + 1 1 0.33 cmp rsi, rcx + 1 1 1.00 je .LBB5_3 + 1 0 0.25 xor eax, eax + 1 1 0.33 mov rdx, rsi + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 4.32 4.33 - 4.35 - - + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - - 0.99 - 0.01 - - movabs rax, 9223372036854775805 + - - 0.33 0.67 - - - - cmp rdx, rax + - - 1.98 - - 0.02 - - seta cl + - - 0.01 0.99 - - - - mov rax, rdi + - - 1.00 - - - - - or dil, cl + - - 0.99 0.01 - - - - test dil, 1 + - - - - - 1.00 - - jne .LBB5_2 + - - - 1.00 - - - - lea rcx, [2*rdx + 4] + - - 0.01 - - 0.99 - - cmp rsi, rcx + - - - - - 1.00 - - je .LBB5_3 + - - - - - - - - xor eax, eax + - - - 0.67 - 0.33 - - mov rdx, rsi + - - - - - 1.00 - - ret diff --git a/benches/ref_from_prefix.rs b/benches/ref_from_prefix.rs new file mode 100644 index 0000000000..1bd9a66821 --- /dev/null +++ b/benches/ref_from_prefix.rs @@ -0,0 +1,20 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::FromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8]) -> Option<&format::LocoPacket> { + match FromBytes::ref_from_prefix(source) { + Ok((packet, _rest)) => Some(packet), + _ => None, + } +} diff --git a/benches/ref_from_prefix.x86-64.mca b/benches/ref_from_prefix.x86-64.mca new file mode 100644 index 0000000000..3900a59461 --- /dev/null +++ b/benches/ref_from_prefix.x86-64.mca @@ -0,0 +1,67 @@ +Iterations: 100 +Instructions: 1400 +Total Cycles: 405 +Total uOps: 1400 + +Dispatch Width: 4 +uOps Per Cycle: 3.46 +IPC: 3.46 +Block RThroughput: 4.0 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 0 0.25 xor edx, edx + 1 1 0.33 mov eax, 0 + 1 1 0.33 test dil, 1 + 1 1 1.00 jne .LBB5_4 + 1 1 0.33 cmp rsi, 4 + 1 1 1.00 jae .LBB5_3 + 1 1 0.33 mov edx, 1 + 1 0 0.25 xor eax, eax + 1 1 1.00 U ret + 1 1 0.33 add rsi, -4 + 1 1 0.50 shr rsi + 1 1 0.33 mov rdx, rsi + 1 1 0.33 mov rax, rdi + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 3.99 3.99 - 4.02 - - + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - - - - - - - xor edx, edx + - - 0.01 0.98 - 0.01 - - mov eax, 0 + - - 0.98 0.02 - - - - test dil, 1 + - - - - - 1.00 - - jne .LBB5_4 + - - 0.02 0.98 - - - - cmp rsi, 4 + - - - - - 1.00 - - jae .LBB5_3 + - - 0.98 0.01 - 0.01 - - mov edx, 1 + - - - - - - - - xor eax, eax + - - - - - 1.00 - - ret + - - 0.01 0.99 - - - - add rsi, -4 + - - 1.00 - - - - - shr rsi + - - - 1.00 - - - - mov rdx, rsi + - - 0.99 0.01 - - - - mov rax, rdi + - - - - - 1.00 - - ret diff --git a/benches/ref_from_prefix_with_elems.rs b/benches/ref_from_prefix_with_elems.rs new file mode 100644 index 0000000000..3d4b5fc6d3 --- /dev/null +++ b/benches/ref_from_prefix_with_elems.rs @@ -0,0 +1,20 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::FromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8], count: usize) -> Option<&format::LocoPacket> { + match FromBytes::ref_from_prefix_with_elems(source, count) { + Ok((packet, _rest)) => Some(packet), + _ => None, + } +} diff --git a/benches/ref_from_prefix_with_elems.x86-64.mca b/benches/ref_from_prefix_with_elems.x86-64.mca new file mode 100644 index 0000000000..94c718e22c --- /dev/null +++ b/benches/ref_from_prefix_with_elems.x86-64.mca @@ -0,0 +1,77 @@ +Iterations: 100 +Instructions: 1900 +Total Cycles: 672 +Total uOps: 2300 + +Dispatch Width: 4 +uOps Per Cycle: 3.42 +IPC: 2.83 +Block RThroughput: 5.8 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 movabs rax, 9223372036854775805 + 1 1 0.33 cmp rdx, rax + 1 1 1.00 ja .LBB5_1 + 1 1 0.33 mov rcx, rdx + 1 0 0.25 xor edx, edx + 1 1 0.33 mov eax, 0 + 1 1 0.33 test dil, 1 + 1 1 1.00 jne .LBB5_4 + 1 1 0.50 lea rax, [2*rcx + 4] + 1 0 0.25 xor r8d, r8d + 1 1 0.33 cmp rax, rsi + 1 1 0.33 mov edx, 1 + 3 3 1.00 cmovbe rdx, rcx + 3 3 1.00 cmova rdi, r8 + 1 1 0.33 mov rax, rdi + 1 1 1.00 U ret + 1 1 0.33 mov edx, 1 + 1 0 0.25 xor eax, eax + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 6.66 6.66 - 6.68 - - + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - - 0.99 - 0.01 - - movabs rax, 9223372036854775805 + - - 0.37 0.63 - - - - cmp rdx, rax + - - - - - 1.00 - - ja .LBB5_1 + - - 0.63 0.37 - - - - mov rcx, rdx + - - - - - - - - xor edx, edx + - - 0.01 0.98 - 0.01 - - mov eax, 0 + - - 0.98 0.02 - - - - test dil, 1 + - - - - - 1.00 - - jne .LBB5_4 + - - 0.01 0.99 - - - - lea rax, [2*rcx + 4] + - - - - - - - - xor r8d, r8d + - - 1.00 - - - - - cmp rax, rsi + - - - 0.67 - 0.33 - - mov edx, 1 + - - 0.73 0.98 - 1.29 - - cmovbe rdx, rcx + - - 1.60 0.36 - 1.04 - - cmova rdi, r8 + - - 0.99 0.01 - - - - mov rax, rdi + - - - - - 1.00 - - ret + - - 0.34 0.66 - - - - mov edx, 1 + - - - - - - - - xor eax, eax + - - - - - 1.00 - - ret diff --git a/benches/ref_from_suffix.rs b/benches/ref_from_suffix.rs new file mode 100644 index 0000000000..032875ae43 --- /dev/null +++ b/benches/ref_from_suffix.rs @@ -0,0 +1,20 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::FromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8]) -> Option<&format::LocoPacket> { + match FromBytes::ref_from_suffix(source) { + Ok((_rest, packet)) => Some(packet), + _ => None, + } +} diff --git a/benches/ref_from_suffix.x86-64.mca b/benches/ref_from_suffix.x86-64.mca new file mode 100644 index 0000000000..1398bcfe27 --- /dev/null +++ b/benches/ref_from_suffix.x86-64.mca @@ -0,0 +1,63 @@ +Iterations: 100 +Instructions: 1200 +Total Cycles: 439 +Total uOps: 1400 + +Dispatch Width: 4 +uOps Per Cycle: 3.19 +IPC: 2.73 +Block RThroughput: 3.5 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 mov rdx, rsi + 1 1 0.50 lea ecx, [rsi + rdi] + 1 1 0.33 mov eax, edx + 1 1 0.33 and eax, 1 + 1 1 0.33 add rax, rdi + 1 0 0.25 xor esi, esi + 1 1 0.33 sub rdx, 4 + 2 2 0.67 cmovb rax, rsi + 1 1 0.50 shr rdx + 1 1 0.33 test cl, 1 + 2 2 0.67 cmovne rax, rsi + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 4.33 4.33 - 4.34 - - + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - 0.02 0.32 - 0.66 - - mov rdx, rsi + - - 0.32 0.68 - - - - lea ecx, [rsi + rdi] + - - 0.66 - - 0.34 - - mov eax, edx + - - 0.02 0.33 - 0.65 - - and eax, 1 + - - - 0.99 - 0.01 - - add rax, rdi + - - - - - - - - xor esi, esi + - - 0.65 - - 0.35 - - sub rdx, 4 + - - 1.00 1.00 - - - - cmovb rax, rsi + - - 0.66 - - 0.34 - - shr rdx + - - - 0.01 - 0.99 - - test cl, 1 + - - 1.00 1.00 - - - - cmovne rax, rsi + - - - - - 1.00 - - ret diff --git a/benches/ref_from_suffix_with_elems.rs b/benches/ref_from_suffix_with_elems.rs new file mode 100644 index 0000000000..63fa358219 --- /dev/null +++ b/benches/ref_from_suffix_with_elems.rs @@ -0,0 +1,20 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::FromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8], count: usize) -> Option<&format::LocoPacket> { + match FromBytes::ref_from_suffix_with_elems(source, count) { + Ok((_rest, packet)) => Some(packet), + _ => None, + } +} diff --git a/benches/ref_from_suffix_with_elems.x86-64.mca b/benches/ref_from_suffix_with_elems.x86-64.mca new file mode 100644 index 0000000000..eac400f3f4 --- /dev/null +++ b/benches/ref_from_suffix_with_elems.x86-64.mca @@ -0,0 +1,77 @@ +Iterations: 100 +Instructions: 1900 +Total Cycles: 571 +Total uOps: 1900 + +Dispatch Width: 4 +uOps Per Cycle: 3.33 +IPC: 3.33 +Block RThroughput: 5.0 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 movabs rax, 9223372036854775805 + 1 1 0.33 cmp rdx, rax + 1 1 1.00 ja .LBB5_1 + 1 1 0.50 lea r8d, [rsi + rdi] + 1 0 0.25 xor ecx, ecx + 1 1 0.33 mov eax, 0 + 1 1 0.33 test r8b, 1 + 1 1 1.00 jne .LBB5_5 + 1 1 0.50 lea rax, [2*rdx + 4] + 1 1 0.33 sub rsi, rax + 1 1 1.00 jae .LBB5_4 + 1 0 0.25 xor eax, eax + 1 1 0.33 mov edx, 1 + 1 1 1.00 U ret + 1 1 0.33 add rdi, rsi + 1 1 0.33 mov rcx, rdx + 1 1 0.33 mov rax, rdi + 1 1 0.33 mov rdx, rcx + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 5.66 5.66 - 5.68 - - + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - 0.66 0.33 - 0.01 - - movabs rax, 9223372036854775805 + - - 0.01 0.99 - - - - cmp rdx, rax + - - - - - 1.00 - - ja .LBB5_1 + - - 0.99 0.01 - - - - lea r8d, [rsi + rdi] + - - - - - - - - xor ecx, ecx + - - 0.33 0.33 - 0.34 - - mov eax, 0 + - - 0.33 0.34 - 0.33 - - test r8b, 1 + - - - - - 1.00 - - jne .LBB5_5 + - - 0.34 0.66 - - - - lea rax, [2*rdx + 4] + - - - 1.00 - - - - sub rsi, rax + - - - - - 1.00 - - jae .LBB5_4 + - - - - - - - - xor eax, eax + - - 1.00 - - - - - mov edx, 1 + - - - - - 1.00 - - ret + - - - 1.00 - - - - add rdi, rsi + - - 1.00 - - - - - mov rcx, rdx + - - 0.32 0.68 - - - - mov rax, rdi + - - 0.68 0.32 - - - - mov rdx, rcx + - - - - - 1.00 - - ret diff --git a/benches/transmute_ref.rs b/benches/transmute_ref.rs new file mode 100644 index 0000000000..d13e97ef2d --- /dev/null +++ b/benches/transmute_ref.rs @@ -0,0 +1,25 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::transmute_ref; +use zerocopy_derive::*; + +#[path = "formats/coco.rs"] +mod format; + +#[derive(IntoBytes, KnownLayout, Immutable)] +#[repr(C, align(2))] +struct MinimalViableSource { + header: [u8; 4], + trailer: [[u8; 2]], +} + +#[unsafe(no_mangle)] +fn codegen_test(source: &MinimalViableSource) -> &format::LocoPacket { + transmute_ref!(source) +} diff --git a/benches/transmute_ref.x86-64.mca b/benches/transmute_ref.x86-64.mca new file mode 100644 index 0000000000..132e8ecb7a --- /dev/null +++ b/benches/transmute_ref.x86-64.mca @@ -0,0 +1,45 @@ +Iterations: 100 +Instructions: 300 +Total Cycles: 104 +Total uOps: 300 + +Dispatch Width: 4 +uOps Per Cycle: 2.88 +IPC: 2.88 +Block RThroughput: 1.0 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 mov rdx, rsi + 1 1 0.33 mov rax, rdi + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 0.99 1.00 - 1.01 - - + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - 0.99 - - 0.01 - - mov rdx, rsi + - - - 1.00 - - - - mov rax, rdi + - - - - - 1.00 - - ret diff --git a/benches/try_ref_from_bytes.rs b/benches/try_ref_from_bytes.rs new file mode 100644 index 0000000000..609c4bb3d3 --- /dev/null +++ b/benches/try_ref_from_bytes.rs @@ -0,0 +1,17 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::TryFromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8]) -> Option<&format::CocoPacket> { + TryFromBytes::try_ref_from_bytes(source).ok() +} diff --git a/benches/try_ref_from_bytes.x86-64.mca b/benches/try_ref_from_bytes.x86-64.mca new file mode 100644 index 0000000000..ecd7a18f6d --- /dev/null +++ b/benches/try_ref_from_bytes.x86-64.mca @@ -0,0 +1,79 @@ +Iterations: 100 +Instructions: 2000 +Total Cycles: 639 +Total uOps: 2100 + +Dispatch Width: 4 +uOps Per Cycle: 3.29 +IPC: 3.13 +Block RThroughput: 5.3 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 mov rdx, rsi + 1 1 0.33 mov rax, rdi + 1 1 0.33 cmp rsi, 4 + 1 1 0.50 setb cl + 1 1 0.33 or cl, al + 1 1 0.33 test cl, 1 + 1 1 1.00 jne .LBB5_4 + 1 1 0.50 lea rcx, [rdx - 4] + 1 1 0.33 mov rsi, rcx + 1 1 0.33 and rsi, -2 + 1 1 0.33 add rsi, 4 + 1 1 0.33 cmp rdx, rsi + 1 1 1.00 jne .LBB5_4 + 2 6 0.50 * cmp word ptr [rax], -16192 + 1 1 1.00 jne .LBB5_4 + 1 1 0.50 shr rcx + 1 1 0.33 mov rdx, rcx + 1 1 1.00 U ret + 1 0 0.25 xor eax, eax + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 6.32 6.32 - 6.36 0.50 0.50 + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - 0.33 0.66 - 0.01 - - mov rdx, rsi + - - 0.66 0.34 - - - - mov rax, rdi + - - 0.34 0.66 - - - - cmp rsi, 4 + - - 0.99 - - 0.01 - - setb cl + - - 0.01 0.99 - - - - or cl, al + - - - 1.00 - - - - test cl, 1 + - - - - - 1.00 - - jne .LBB5_4 + - - 0.66 0.34 - - - - lea rcx, [rdx - 4] + - - 0.33 0.66 - 0.01 - - mov rsi, rcx + - - 1.00 - - - - - and rsi, -2 + - - 0.66 0.34 - - - - add rsi, 4 + - - - 1.00 - - - - cmp rdx, rsi + - - - - - 1.00 - - jne .LBB5_4 + - - - - - 1.00 0.50 0.50 cmp word ptr [rax], -16192 + - - - - - 1.00 - - jne .LBB5_4 + - - 0.67 - - 0.33 - - shr rcx + - - 0.67 0.33 - - - - mov rdx, rcx + - - - - - 1.00 - - ret + - - - - - - - - xor eax, eax + - - - - - 1.00 - - ret diff --git a/benches/try_ref_from_bytes_with_elems.rs b/benches/try_ref_from_bytes_with_elems.rs new file mode 100644 index 0000000000..4594ca3421 --- /dev/null +++ b/benches/try_ref_from_bytes_with_elems.rs @@ -0,0 +1,17 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::TryFromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8], count: usize) -> Option<&format::CocoPacket> { + TryFromBytes::try_ref_from_bytes_with_elems(source, count).ok() +} diff --git a/benches/try_ref_from_bytes_with_elems.x86-64.mca b/benches/try_ref_from_bytes_with_elems.x86-64.mca new file mode 100644 index 0000000000..76a7caaecf --- /dev/null +++ b/benches/try_ref_from_bytes_with_elems.x86-64.mca @@ -0,0 +1,69 @@ +Iterations: 100 +Instructions: 1500 +Total Cycles: 507 +Total uOps: 1700 + +Dispatch Width: 4 +uOps Per Cycle: 3.35 +IPC: 2.96 +Block RThroughput: 4.3 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 movabs rax, 9223372036854775805 + 1 1 0.33 cmp rdx, rax + 2 2 1.00 seta cl + 1 1 0.33 mov rax, rdi + 1 1 0.33 or dil, cl + 1 1 0.33 test dil, 1 + 1 1 1.00 jne .LBB5_3 + 1 1 0.50 lea rcx, [2*rdx + 4] + 1 1 0.33 cmp rsi, rcx + 1 1 1.00 jne .LBB5_3 + 2 6 0.50 * cmp word ptr [rax], -16192 + 1 1 1.00 je .LBB5_4 + 1 0 0.25 xor eax, eax + 1 1 0.33 mov rdx, rsi + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 4.98 4.99 - 5.03 0.50 0.50 + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - - 0.99 - 0.01 - - movabs rax, 9223372036854775805 + - - 0.50 0.50 - - - - cmp rdx, rax + - - 1.96 - - 0.04 - - seta cl + - - 0.01 0.99 - - - - mov rax, rdi + - - 1.00 - - - - - or dil, cl + - - 0.99 0.01 - - - - test dil, 1 + - - - - - 1.00 - - jne .LBB5_3 + - - 0.01 0.99 - - - - lea rcx, [2*rdx + 4] + - - 0.02 0.49 - 0.49 - - cmp rsi, rcx + - - - - - 1.00 - - jne .LBB5_3 + - - - 0.51 - 0.49 0.50 0.50 cmp word ptr [rax], -16192 + - - - - - 1.00 - - je .LBB5_4 + - - - - - - - - xor eax, eax + - - 0.49 0.51 - - - - mov rdx, rsi + - - - - - 1.00 - - ret diff --git a/benches/try_ref_from_prefix.rs b/benches/try_ref_from_prefix.rs new file mode 100644 index 0000000000..25dddcbbc6 --- /dev/null +++ b/benches/try_ref_from_prefix.rs @@ -0,0 +1,20 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::TryFromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8]) -> Option<&format::CocoPacket> { + match TryFromBytes::try_ref_from_prefix(source) { + Ok((packet, _rest)) => Some(packet), + _ => None, + } +} diff --git a/benches/try_ref_from_prefix.x86-64.mca b/benches/try_ref_from_prefix.x86-64.mca new file mode 100644 index 0000000000..11706defe1 --- /dev/null +++ b/benches/try_ref_from_prefix.x86-64.mca @@ -0,0 +1,77 @@ +Iterations: 100 +Instructions: 1900 +Total Cycles: 573 +Total uOps: 2100 + +Dispatch Width: 4 +uOps Per Cycle: 3.66 +IPC: 3.32 +Block RThroughput: 5.3 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 0 0.25 xor edx, edx + 1 1 0.33 mov eax, 0 + 1 1 0.33 test dil, 1 + 1 1 1.00 jne .LBB5_4 + 1 1 0.33 cmp rsi, 4 + 1 1 1.00 jae .LBB5_3 + 1 1 0.33 mov edx, 1 + 1 0 0.25 xor eax, eax + 1 1 1.00 U ret + 1 1 0.33 add rsi, -4 + 1 1 0.50 shr rsi + 1 5 0.50 * movzx ecx, word ptr [rdi] + 1 1 0.33 cmp ecx, 49344 + 1 1 0.33 mov edx, 2 + 2 2 0.67 cmove rdx, rsi + 1 0 0.25 xor eax, eax + 1 1 0.33 cmp cx, -16192 + 2 2 0.67 cmove rax, rdi + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 5.66 5.67 - 5.67 0.50 0.50 + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - - - - - - - xor edx, edx + - - 0.30 0.37 - 0.33 - - mov eax, 0 + - - 0.35 0.32 - 0.33 - - test dil, 1 + - - - - - 1.00 - - jne .LBB5_4 + - - 0.32 0.33 - 0.35 - - cmp rsi, 4 + - - - - - 1.00 - - jae .LBB5_3 + - - 0.33 0.35 - 0.32 - - mov edx, 1 + - - - - - - - - xor eax, eax + - - - - - 1.00 - - ret + - - 0.34 0.64 - 0.02 - - add rsi, -4 + - - 1.00 - - - - - shr rsi + - - - - - - 0.50 0.50 movzx ecx, word ptr [rdi] + - - 0.60 0.40 - - - - cmp ecx, 49344 + - - 0.05 0.95 - - - - mov edx, 2 + - - 1.00 1.00 - - - - cmove rdx, rsi + - - - - - - - - xor eax, eax + - - 0.37 0.31 - 0.32 - - cmp cx, -16192 + - - 1.00 1.00 - - - - cmove rax, rdi + - - - - - 1.00 - - ret diff --git a/benches/try_ref_from_prefix_with_elems.rs b/benches/try_ref_from_prefix_with_elems.rs new file mode 100644 index 0000000000..d81d3b3c63 --- /dev/null +++ b/benches/try_ref_from_prefix_with_elems.rs @@ -0,0 +1,20 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::TryFromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8], count: usize) -> Option<&format::CocoPacket> { + match TryFromBytes::try_ref_from_prefix_with_elems(source, count) { + Ok((packet, _rest)) => Some(packet), + _ => None, + } +} diff --git a/benches/try_ref_from_prefix_with_elems.x86-64.mca b/benches/try_ref_from_prefix_with_elems.x86-64.mca new file mode 100644 index 0000000000..7dc6caa16b --- /dev/null +++ b/benches/try_ref_from_prefix_with_elems.x86-64.mca @@ -0,0 +1,83 @@ +Iterations: 100 +Instructions: 2200 +Total Cycles: 674 +Total uOps: 2400 + +Dispatch Width: 4 +uOps Per Cycle: 3.56 +IPC: 3.26 +Block RThroughput: 6.0 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 movabs rax, 9223372036854775805 + 1 1 0.33 cmp rdx, rax + 1 1 1.00 ja .LBB5_1 + 1 1 0.33 mov rcx, rdx + 1 0 0.25 xor edx, edx + 1 1 0.33 mov eax, 0 + 1 1 0.33 test dil, 1 + 1 1 1.00 jne .LBB5_5 + 1 1 0.50 lea rax, [2*rcx + 4] + 1 1 0.33 cmp rax, rsi + 1 1 1.00 jbe .LBB5_4 + 1 0 0.25 xor eax, eax + 1 1 0.33 mov edx, 1 + 1 1 1.00 U ret + 1 5 0.50 * movzx esi, word ptr [rdi] + 1 1 0.33 cmp si, -16192 + 1 1 0.33 mov edx, 2 + 2 2 0.67 cmove rdx, rcx + 1 0 0.25 xor eax, eax + 1 1 0.33 cmp esi, 49344 + 2 2 0.67 cmove rax, rdi + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 6.65 6.66 - 6.69 0.50 0.50 + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - 0.66 0.33 - 0.01 - - movabs rax, 9223372036854775805 + - - 0.02 0.66 - 0.32 - - cmp rdx, rax + - - - - - 1.00 - - ja .LBB5_1 + - - 0.66 0.33 - 0.01 - - mov rcx, rdx + - - - - - - - - xor edx, edx + - - 0.33 0.01 - 0.66 - - mov eax, 0 + - - 0.34 0.65 - 0.01 - - test dil, 1 + - - - - - 1.00 - - jne .LBB5_5 + - - 0.65 0.35 - - - - lea rax, [2*rcx + 4] + - - - 1.00 - - - - cmp rax, rsi + - - - - - 1.00 - - jbe .LBB5_4 + - - - - - - - - xor eax, eax + - - 0.34 0.01 - 0.65 - - mov edx, 1 + - - - - - 1.00 - - ret + - - - - - - 0.50 0.50 movzx esi, word ptr [rdi] + - - 0.65 0.34 - 0.01 - - cmp si, -16192 + - - 0.66 0.34 - - - - mov edx, 2 + - - 1.00 0.99 - 0.01 - - cmove rdx, rcx + - - - - - - - - xor eax, eax + - - 0.34 0.66 - - - - cmp esi, 49344 + - - 1.00 0.99 - 0.01 - - cmove rax, rdi + - - - - - 1.00 - - ret diff --git a/benches/try_ref_from_suffix.rs b/benches/try_ref_from_suffix.rs new file mode 100644 index 0000000000..73d678174f --- /dev/null +++ b/benches/try_ref_from_suffix.rs @@ -0,0 +1,20 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::TryFromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8]) -> Option<&format::CocoPacket> { + match TryFromBytes::try_ref_from_suffix(source) { + Ok((_rest, packet)) => Some(packet), + _ => None, + } +} diff --git a/benches/try_ref_from_suffix.x86-64.mca b/benches/try_ref_from_suffix.x86-64.mca new file mode 100644 index 0000000000..6cf7f8e493 --- /dev/null +++ b/benches/try_ref_from_suffix.x86-64.mca @@ -0,0 +1,71 @@ +Iterations: 100 +Instructions: 1600 +Total Cycles: 510 +Total uOps: 1800 + +Dispatch Width: 4 +uOps Per Cycle: 3.53 +IPC: 3.14 +Block RThroughput: 4.5 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.50 lea eax, [rsi + rdi] + 1 1 0.33 cmp rsi, 4 + 1 1 0.50 setb cl + 1 1 0.33 or cl, al + 1 1 0.33 test cl, 1 + 1 1 1.00 je .LBB5_2 + 1 0 0.25 xor eax, eax + 1 1 1.00 U ret + 1 1 0.50 lea rdx, [rsi - 4] + 1 1 0.50 shr rdx + 1 1 0.33 and esi, 1 + 1 1 0.50 lea rcx, [rdi + rsi] + 1 0 0.25 xor eax, eax + 2 6 0.50 * cmp word ptr [rdi + rsi], -16192 + 2 2 0.67 cmove rax, rcx + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 4.99 5.00 - 5.01 0.50 0.50 + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - 0.98 0.02 - - - - lea eax, [rsi + rdi] + - - - 0.98 - 0.02 - - cmp rsi, 4 + - - 1.00 - - - - - setb cl + - - 0.01 0.99 - - - - or cl, al + - - 0.01 0.07 - 0.92 - - test cl, 1 + - - - - - 1.00 - - je .LBB5_2 + - - - - - - - - xor eax, eax + - - - - - 1.00 - - ret + - - 0.93 0.07 - - - - lea rdx, [rsi - 4] + - - 0.93 - - 0.07 - - shr rdx + - - 0.06 0.93 - 0.01 - - and esi, 1 + - - 0.07 0.93 - - - - lea rcx, [rdi + rsi] + - - - - - - - - xor eax, eax + - - - 0.01 - 0.99 0.50 0.50 cmp word ptr [rdi + rsi], -16192 + - - 1.00 1.00 - - - - cmove rax, rcx + - - - - - 1.00 - - ret diff --git a/benches/try_ref_from_suffix_with_elems.rs b/benches/try_ref_from_suffix_with_elems.rs new file mode 100644 index 0000000000..eaa0dd3016 --- /dev/null +++ b/benches/try_ref_from_suffix_with_elems.rs @@ -0,0 +1,20 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::TryFromBytes; + +#[path = "formats/coco.rs"] +mod format; + +#[unsafe(no_mangle)] +fn codegen_test(source: &[u8], count: usize) -> Option<&format::CocoPacket> { + match TryFromBytes::try_ref_from_suffix_with_elems(source, count) { + Ok((_rest, packet)) => Some(packet), + _ => None, + } +} diff --git a/benches/try_ref_from_suffix_with_elems.x86-64.mca b/benches/try_ref_from_suffix_with_elems.x86-64.mca new file mode 100644 index 0000000000..8b6333bf34 --- /dev/null +++ b/benches/try_ref_from_suffix_with_elems.x86-64.mca @@ -0,0 +1,87 @@ +Iterations: 100 +Instructions: 2400 +Total Cycles: 1107 +Total uOps: 2600 + +Dispatch Width: 4 +uOps Per Cycle: 2.35 +IPC: 2.17 +Block RThroughput: 6.5 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 movabs rax, 9223372036854775805 + 1 1 0.33 cmp rdx, rax + 1 1 1.00 ja .LBB5_1 + 1 1 0.50 lea r8d, [rsi + rdi] + 1 0 0.25 xor ecx, ecx + 1 1 0.33 mov eax, 0 + 1 1 0.33 test r8b, 1 + 1 1 1.00 jne .LBB5_5 + 1 1 0.50 lea rax, [2*rdx + 4] + 1 1 0.33 sub rsi, rax + 1 1 1.00 jae .LBB5_4 + 1 0 0.25 xor eax, eax + 1 1 0.33 mov edx, 1 + 1 1 1.00 U ret + 1 1 0.50 lea r8, [rdi + rsi] + 1 5 0.50 * movzx esi, word ptr [rdi + rsi] + 1 1 0.33 cmp si, -16192 + 1 1 0.33 mov ecx, 2 + 2 2 0.67 cmove rcx, rdx + 1 0 0.25 xor eax, eax + 1 1 0.33 cmp esi, 49344 + 2 2 0.67 cmove rax, r8 + 1 1 0.33 mov rdx, rcx + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 6.99 7.00 - 8.01 0.50 0.50 + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - 0.02 0.95 - 0.03 - - movabs rax, 9223372036854775805 + - - 0.93 0.04 - 0.03 - - cmp rdx, rax + - - - - - 1.00 - - ja .LBB5_1 + - - 0.96 0.04 - - - - lea r8d, [rsi + rdi] + - - - - - - - - xor ecx, ecx + - - 0.95 0.02 - 0.03 - - mov eax, 0 + - - 0.95 0.05 - - - - test r8b, 1 + - - - - - 1.00 - - jne .LBB5_5 + - - 0.06 0.94 - - - - lea rax, [2*rdx + 4] + - - 0.93 0.07 - - - - sub rsi, rax + - - - - - 1.00 - - jae .LBB5_4 + - - - - - - - - xor eax, eax + - - 0.03 0.95 - 0.02 - - mov edx, 1 + - - - - - 1.00 - - ret + - - 0.97 0.03 - - - - lea r8, [rdi + rsi] + - - - - - - 0.50 0.50 movzx esi, word ptr [rdi + rsi] + - - 0.03 0.97 - - - - cmp si, -16192 + - - 0.05 0.94 - 0.01 - - mov ecx, 2 + - - 0.06 0.98 - 0.96 - - cmove rcx, rdx + - - - - - - - - xor eax, eax + - - 0.97 0.03 - - - - cmp esi, 49344 + - - 0.06 0.96 - 0.98 - - cmove rax, r8 + - - 0.02 0.03 - 0.95 - - mov rdx, rcx + - - - - - 1.00 - - ret diff --git a/benches/try_transmute_ref.rs b/benches/try_transmute_ref.rs new file mode 100644 index 0000000000..de16076a82 --- /dev/null +++ b/benches/try_transmute_ref.rs @@ -0,0 +1,25 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +use zerocopy::try_transmute_ref; +use zerocopy_derive::*; + +#[path = "formats/coco.rs"] +mod format; + +#[derive(IntoBytes, KnownLayout, Immutable)] +#[repr(C, align(2))] +struct MinimalViableSource { + header: [u8; 4], + trailer: [[u8; 2]], +} + +#[unsafe(no_mangle)] +fn codegen_test(source: &MinimalViableSource) -> Option<&format::CocoPacket> { + try_transmute_ref!(source).ok() +} diff --git a/benches/try_transmute_ref.x86-64.mca b/benches/try_transmute_ref.x86-64.mca new file mode 100644 index 0000000000..24914d2aed --- /dev/null +++ b/benches/try_transmute_ref.x86-64.mca @@ -0,0 +1,49 @@ +Iterations: 100 +Instructions: 500 +Total Cycles: 209 +Total uOps: 700 + +Dispatch Width: 4 +uOps Per Cycle: 3.35 +IPC: 2.39 +Block RThroughput: 1.8 + + +Instruction Info: +[1]: #uOps +[2]: Latency +[3]: RThroughput +[4]: MayLoad +[5]: MayStore +[6]: HasSideEffects (U) + +[1] [2] [3] [4] [5] [6] Instructions: + 1 1 0.33 mov rdx, rsi + 1 0 0.25 xor eax, eax + 2 6 0.50 * cmp word ptr [rdi], -16192 + 2 2 0.67 cmove rax, rdi + 1 1 1.00 U ret + + +Resources: +[0] - SBDivider +[1] - SBFPDivider +[2] - SBPort0 +[3] - SBPort1 +[4] - SBPort4 +[5] - SBPort5 +[6.0] - SBPort23 +[6.1] - SBPort23 + + +Resource pressure per iteration: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] + - - 1.02 1.99 - 1.99 0.50 0.50 + +Resource pressure by instruction: +[0] [1] [2] [3] [4] [5] [6.0] [6.1] Instructions: + - - 0.03 0.96 - 0.01 - - mov rdx, rsi + - - - - - - - - xor eax, eax + - - - 0.03 - 0.97 0.50 0.50 cmp word ptr [rdi], -16192 + - - 0.99 1.00 - 0.01 - - cmove rax, rdi + - - - - - 1.00 - - ret diff --git a/tests/codegen.rs b/tests/codegen.rs new file mode 100644 index 0000000000..c3d90a1a07 --- /dev/null +++ b/tests/codegen.rs @@ -0,0 +1,74 @@ +// Copyright 2026 The Fuchsia Authors +// +// Licensed under a BSD-style license , Apache License, Version 2.0 +// , or the MIT +// license , at your option. +// This file may not be copied, modified, or distributed except according to +// those terms. + +#![cfg(__ZEROCOPY_INTERNAL_USE_ONLY_NIGHTLY_FEATURES_IN_TESTS)] + +use std::{path::PathBuf, process::Command}; + +fn run_codegen_test(bench_name: &str, target_cpu: &str, bless: bool) { + let manifest_path = env!("CARGO_MANIFEST_PATH"); + let target_dir = env!("CARGO_TARGET_DIR"); + + let output = Command::new("cargo") + .args([ + "asm", + "-p", + "zerocopy", + "--manifest-path", + manifest_path, + "--target-dir", + target_dir, + "--bench", + bench_name, + "--target-cpu", + target_cpu, + "--mca", + "codegen_test", + ]) + .output() + .expect("failed to execute process"); + + let actual_result = output.stdout; + + if !(output.status.success()) { + panic!("{}", String::from_utf8_lossy(&output.stderr)); + } + + let expected_file_path = { + let mut path: PathBuf = env!("CARGO_MANIFEST_DIR").into(); + path.push("benches"); + let file_name = format!("{bench_name}.{target_cpu}.mca"); + path.push(file_name); + path + }; + + if bless { + std::fs::write(expected_file_path, &actual_result).unwrap(); + } else { + let expected_result = std::fs::read(expected_file_path).unwrap_or_default(); + if actual_result != expected_result { + let expected = String::from_utf8_lossy(&expected_result[..]); + panic!("Bless codegen tests with BLESS=1\nGot unexpected output:\n{}", expected); + } + } +} + +#[test] +#[cfg_attr(miri, ignore)] +fn codegen() { + let bless = std::env::var("BLESS").is_ok(); + let paths = std::fs::read_dir("benches").unwrap(); + for path in paths { + let path = path.unwrap().path(); + if !path.extension().map(|s| s == "rs").unwrap_or(false) { + continue; + } + let path = path.file_stem().unwrap().to_str().unwrap(); + run_codegen_test(path, "x86-64", bless); + } +} diff --git a/tools/update-expected-test-output.sh b/tools/update-expected-test-output.sh index 118bda799f..f25ef9b428 100755 --- a/tools/update-expected-test-output.sh +++ b/tools/update-expected-test-output.sh @@ -10,7 +10,9 @@ set -eo pipefail -# Update the `.stderr` reference files used to validate our UI tests. +# Update the `.stderr` reference files used to validate our UI tests and the +# `.x86-64.mca` files used to validate our codegen tests. +BLESS=1 ./cargo.sh +nightly test --test codegen -p zerocopy --all-features BLESS=1 ./cargo.sh +nightly test --test ui -p zerocopy --all-features BLESS=1 ./cargo.sh +stable test --test ui -p zerocopy --features=__internal_use_only_features_that_work_on_stable BLESS=1 ./cargo.sh +msrv test --test ui -p zerocopy --features=__internal_use_only_features_that_work_on_stable