.codex/skills/simd-optimize/SKILL.md
SIMD vectorization for Rust — detects ISA features, identifies vectorizable patterns, generates platform-specific intrinsics (ARM NEON/SVE, x86 SSE/AVX/AVX-512), validates correctness and performance. Uses tiered research with baked-in references and /deep-research fallback.
npx skillsauth add ahrav/gossip-rs simd-optimizeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Philosophy: Detect, analyze, implement, validate. Never guess the ISA.
Every SIMD optimization starts by detecting what the hardware actually supports, analyzing what the compiler already auto-vectorized (and what it missed), choosing the right intrinsics from reference material, implementing with proper fallback chains, and validating correctness + performance.
/performance-analyzer identified a loop-heavy hot function/asm-forge shows the compiler failed to auto-vectorize a loop/asm-forge instead# cargo-show-asm: inspect compiler output
cargo install cargo-show-asm
# jq: parse detection script output
brew install jq # macOS
apt install jq # Linux
# Criterion benchmarks must exist for the target code
# proptest: property-based testing for SIMD vs scalar comparison
# Add to [dev-dependencies]: proptest = "1"
/simd-optimize @file.rs "description of what to vectorize"
Examples:
/simd-optimize @crates/gossip-stdx/src/byte_slab.rs "vectorize the slot search loop"
/simd-optimize @crates/gossip-stdx/src/inline_vec.rs "add SIMD path for element search"
/simd-optimize @crates/scanner-engine/src/engine/simd_classify.rs "SIMD byte classification across x86 and ARM"
/simd-optimize @file.rs "target description"
│
├─ Phase 0: ISA Detection
│ └─ Run detect_simd.sh → JSON capability report
│
├─ Phase 1: Analysis (3 parallel agents)
│ ├─ Agent A: Loop Analyzer — identify vectorizable patterns
│ ├─ Agent B: Autovec Auditor — what did rustc already vectorize?
│ └─ Agent C: Constraint Mapper — data layout, alignment, types
│
├─ Phase 2: Research & Strategy
│ ├─ Load ISA-specific references (tiered: baked-in first)
│ ├─ Match patterns to reference implementations
│ ├─ If gap → invoke /deep-research for specific pattern
│ └─ Select strategy: intrinsics / help-autovec / portable-simd / crate
│
├─ Phase 3: Implementation
│ ├─ Ensure scalar reference exists (for correctness testing)
│ ├─ Write SIMD implementation(s) with cfg gating
│ ├─ Wire runtime dispatch if needed
│ ├─ Handle remainder elements
│ └─ Add unsafe blocks with safety comments
│
└─ Phase 4: Validation (2 parallel agents)
├─ Agent D: Correctness — proptest comparing SIMD vs scalar
└─ Agent E: Performance — /bench-compare against baseline
Run the bundled detection script:
bash <skill_dir>/scripts/detect_simd.sh
This outputs JSON like:
{
"arch": "aarch64",
"os": "darwin",
"rust_target": "aarch64-apple-darwin",
"cpu_model": "Apple M1 Pro",
"features": {
"aes": true, "crc": true, "neon": true,
"sha2": true, "sve": false, "sve2": false
},
"max_vector_width_bits": 128,
"recommended_baseline": "neon",
"recommended_fast_path": null,
"frequency_throttle_risk": false
}
Key fields for subsequent phases:
recommended_baseline — ISA level to target for the primary SIMD implementationrecommended_fast_path — optional higher ISA for runtime dispatch (e.g., "avx512")frequency_throttle_risk — if true, warn about Intel AVX-512 downclockingPresent the capability report to the user before proceeding.
Launch three parallel agents using the Task tool in a single message:
Analyze the target code for vectorizable patterns. For each candidate loop:
1. Classify the pattern:
- Map (element-wise transform)
- Reduction (sum, min, max, count, any/all)
- Search (find first/all matching elements)
- Scan (prefix sum, running accumulator)
- LUT (lookup table, classify/translate)
- Pack/unpack (narrow, widen, interleave)
- Filter (compress matching elements)
2. Identify the iteration pattern:
- Trip count (fixed, bounded, data-dependent?)
- Memory access pattern (contiguous, strided, random?)
- Loop-carried dependencies (accumulator, state machine?)
3. Estimate the vector-friendliness:
- HIGH: Pure map/search on contiguous arrays, no loop-carried deps
- MEDIUM: Reduction with associative op, or strided access
- LOW: Data-dependent iterations, random access, complex control flow
Output a ranked candidate list with pattern classification and confidence.
Check what the compiler already auto-vectorized using check_autovec.sh.
Run: bash <skill_dir>/scripts/check_autovec.sh <crate> '<function_path>'
For each candidate function from the Loop Analyzer:
1. Report whether rustc generated SIMD instructions
2. If yes: what width? What percentage of the loop is vectorized?
3. If no: what likely blocked auto-vectorization?
- Function calls in loop body
- Loop-carried dependencies
- Complex control flow
- Non-contiguous memory access
- Iterator chain that inhibits vectorization
Summarize: which functions need manual SIMD, which are already handled.
Analyze data layout and constraints that affect SIMD implementation:
1. Data layout: AoS (array of structs) or SoA (struct of arrays)?
- AoS needs deinterleaving (vld2/vzip) or transpose
- SoA is directly SIMD-friendly
2. Alignment: Are buffers aligned to 16/32/64 bytes?
- Check allocator usage, struct layout, slice origins
- If unknown, must use unaligned loads
3. Element types: u8, u16, u32, u64, f32, f64?
- Narrower types = more elements per vector = higher speedup
- Mixed types need widening/narrowing
4. Memory access pattern: contiguous, strided, gathered?
- Contiguous: simple vector load
- Strided: may need shuffle after load
- Gathered: expensive on most ISAs (prefer restructuring)
5. Aliasing: Do input and output buffers overlap?
- If yes: must process in correct order or use temporary
Output a constraint report that guides implementation choices.
Based on Phase 0 ISA detection and Phase 1 pattern analysis:
IF arch == "x86_64":
LOAD references/x86-sse-avx.md
IF features.avx512f == true:
LOAD references/x86-avx512.md
ELIF arch == "aarch64":
LOAD references/arm-neon.md
IF features.sve == true OR features.sve2 == true:
LOAD references/arm-sve.md
ALWAYS LOAD:
references/simd-patterns.md (cross-platform pattern cookbook)
references/portability-guide.md (dispatch, fallback chains)
references/pitfalls.md (bugs to avoid)
For each vectorizable candidate from Phase 1:
simd-patterns.mdpitfalls.md that applyIf a pattern isn't covered by the baked-in references:
Invoke /deep-research with query:
"Rust SIMD implementation of [pattern description] using
[ISA: AVX2/NEON/etc] intrinsics from std::arch::[arch].
Include complete code example with #[target_feature] and unsafe."
Choose the implementation approach:
| Strategy | When to Use | Tradeoff |
|----------|-------------|----------|
| Direct intrinsics (std::arch) | Maximum control needed, complex patterns | Most effort, best performance |
| Help auto-vectorizer | Simple loops, compiler almost got it | Least effort, fragile |
| Portable SIMD (std::simd) | Portability > peak performance, nightly OK | Moderate effort, portable |
| Crate (wide, pulp, multiversion) | Need stable Rust + portability | Easy, some overhead |
Default recommendation: Direct intrinsics for hot paths, help auto-vectorizer for secondary paths.
Before writing SIMD code, verify a correct scalar implementation exists. This is the ground truth for correctness testing. If one doesn't exist, write it first.
Follow this template:
#[cfg(target_arch = "x86_64")]
#[target_feature(enable = "avx2")]
unsafe fn process_avx2(data: &[u8]) -> Result {
// SAFETY:
// - Caller ensures `is_x86_feature_detected!("avx2")` returned true
// - `data.len() >= 32` checked by caller (or handled by remainder loop)
// - Unaligned loads used (no alignment requirement)
use core::arch::x86_64::*;
let mut i = 0;
let len = data.len();
// Main SIMD loop: process 32 bytes at a time
while i + 32 <= len {
let chunk = _mm256_loadu_si256(data.as_ptr().add(i) as *const __m256i);
// ... SIMD operations ...
i += 32;
}
// Remainder: scalar fallback for last <32 bytes
while i < len {
// ... scalar processing ...
i += 1;
}
result
}
#[cfg(target_arch = "aarch64")]
#[target_feature(enable = "neon")]
unsafe fn process_neon(data: &[u8]) -> Result {
// SAFETY:
// - NEON is always available on AArch64 (no runtime check needed)
// - `data.len() >= 16` checked by caller
// - vld1q_u8 handles unaligned loads
use core::arch::aarch64::*;
let mut i = 0;
let len = data.len();
while i + 16 <= len {
let chunk = vld1q_u8(data.as_ptr().add(i));
// ... NEON operations ...
i += 16;
}
// Remainder
while i < len {
i += 1;
}
result
}
/// Scalar fallback — always correct, used as reference and fallback
fn process_scalar(data: &[u8]) -> Result {
// ... straightforward scalar implementation ...
}
/// Public dispatch function
pub fn process(data: &[u8]) -> Result {
#[cfg(target_arch = "x86_64")]
{
if is_x86_feature_detected!("avx2") {
return unsafe { process_avx2(data) };
}
}
#[cfg(target_arch = "aarch64")]
{
// NEON is always available on AArch64
return unsafe { process_neon(data) };
}
process_scalar(data)
}
#[target_feature(enable = "...")]unsafe fn with a // SAFETY: comment[])cfg(target_arch) gates each platform-specific functionis_x86_feature_detected!When adding SIMD to this project, follow existing patterns:
crates/gossip-stdx/src/ for data structures that may already use
unsafe pointer operations that could benefit from SIMDcrates/scanner-engine/src/lsm/set_associative_cache.rs and
crates/scanner-engine/src/engine/simd_classify.rs for existing SIMD patternscfg(target_arch) dispatch with separate functions per ISA// SAFETY: comment convention for all unsafe blocksLaunch two parallel agents:
Write property tests comparing SIMD implementation against scalar reference.
Use proptest with these test vectors:
1. Empty input (length 0)
2. Single element
3. Exactly one vector width (16 bytes for NEON/SSE, 32 for AVX2)
4. One less than vector width (15, 31)
5. One more than vector width (17, 33)
6. Random lengths up to 10000
7. All zeros (0x00)
8. All ones (0xFF)
9. Alternating patterns (0xAA, 0x55)
10. Maximum values for the element type
11. Values at type boundaries (127/128, 255/0 for u8)
Template:
```rust
use proptest::prelude::*;
proptest! {
#[test]
fn simd_matches_scalar(data in prop::collection::vec(any::<u8>(), 0..10000)) {
let simd_result = process(&data); // uses dispatch (SIMD when available)
let scalar_result = process_scalar(&data);
prop_assert_eq!(simd_result, scalar_result);
}
}
Run tests and report results.
### Agent E: Performance Validator
Invoke /bench-compare to measure SIMD vs scalar performance.
If Criterion benchmarks exist for the target function: Run: cargo bench --bench <name> -- --save-baseline simd-before Apply SIMD changes Run: cargo bench --bench <name> -- --baseline simd-before
If no benchmarks exist: Create a minimal Criterion benchmark comparing scalar vs SIMD dispatch.
Report:
## Output Format
After all phases complete, present:
```markdown
## SIMD Optimization Report
### Machine Capabilities
- Arch: [x86_64 / aarch64]
- CPU: [model]
- Baseline ISA: [sse2 / avx2 / neon]
- Fast path: [avx512 / sve2 / none]
### Patterns Found
| Pattern | Function | Strategy | Expected Speedup |
|---------|----------|----------|------------------|
| Byte search | find_byte() | Direct intrinsics (AVX2 + NEON) | 8-16x |
| Horizontal sum | reduce_sum() | Help auto-vectorizer | 2-4x |
### Implementation Summary
- Files modified: [list]
- Lines added: [N]
- SIMD paths: [x86_64 AVX2, aarch64 NEON, scalar fallback]
### Validation
- Correctness: [X/Y proptest strategies passing]
- Performance: [Nx speedup measured, Z bytes/sec throughput]
### Remaining Opportunities
[Any patterns not addressed and why]
x86-64:
_mm256_shuffle_epi8 shuffles within 128-bit lanes, NOT across them_mm256_permutevar8x32_epi32 for cross-lane permutesAArch64:
vmaxvq_u8 for horizontal max (single instruction, unlike x86's movemask)Invoke /deep-research when:
simd-patterns.md (e.g., custom hash, crypto, compression)std::simd covers the pattern#[target_feature] → SIMD instructions not emitted/asm-forge — Post-SIMD assembly audit (verify codegen quality)/performance-analyzer — Static hotspot analysis; identify what functions to vectorize (run first)/bench-compare — Quick before/after benchmark comparison/deep-research — Research specific SIMD patterns not in references/linux-perf-profile — Hardware counter analysis for SIMD bottlenecksdevelopment
Deep first-principles code explanation that builds real understanding through phased walkthroughs with diagrams. Covers algorithms, data structures, memory layout, concurrency patterns, and performance tricks — especially for systems code in Rust. Use whenever the user asks to explain, walk through, break down, deep dive into, or understand code. Trigger on "how does this work", "what's happening here", "teach me about this", "why is it done this way", or when the user references a file with @ and wants to understand it. Proactively use when examining code involving lock-free algorithms, atomics/CAS, memory ordering,
development
Use when creating implementation-ready beads tasks that need testing strategy, optimal implementation approach, and documentation requirements baked in — composes /create-task with parallel enrichment agents that analyze the codebase and produce concrete test specifications, algorithm/data-structure guidance, and doc quality standards so implementing agents don't need to re-research
development
--- name: autoresearch description: Autonomous Goal-directed Iteration. Apply Karpathy's autoresearch principles to ANY task. Loops autonomously — modify, verify, keep/discard, repeat. Supports bounded iteration via Iterations: N inline config. version: 1.9.11 --- # Claude Autoresearch — Autonomous Goal-directed Iteration Inspired by [Karpathy's autoresearch](https://github.com/karpathy/autoresearch). Applies constraint-driven autonomous iteration to ANY work — not just ML research. **Core id
development
Use when implementing a new feature and assessing coverage gaps, during periodic test hygiene, when test suites feel bloated, or before merging code that changes coordination or hot paths. Two-phase assess-then-improve testing pipeline.