Skip to content

Good First Issue: Differential assembly check to guard the zero-overhead guarantee #804

Description

@mpusz

📝 What

Add a small CI check that verifies mp-units compiles to the same machine code as hand-written
equivalents, on one reference configuration.

Concretely:

  • Create a dedicated translation unit with a few abstraction/baseline pairs: an mp-units
    function and the equivalent raw function (for example, speed from distance and time).
  • Emit assembly with -S at the release optimization level.
  • Extract each function's assembly, strip incidental tokens (labels, comments, directives,
    alignment padding), and assert each pair is equivalent. Byte-identical after normalization is
    the target for a truly zero-overhead operation.
  • Wire it as a CTest test on a single reference configuration (for example, the latest Clang,
    Release, x86-64) so it gates pull requests.

Keep the first version deliberately minimal: a handful of operations, one configuration,
byte-identical comparison. The set can grow later.

💡 Why

mp-units promises zero runtime overhead, but today that promise is only checked manually on
Compiler Explorer. A refactor or a new feature could silently introduce overhead, and we would
not notice until a user reports it. A differential check catches that automatically.

It is differential on purpose. Comparing the abstraction against a hand-written baseline
compiled with the exact same toolchain and flags sidesteps the cross-configuration problem,
because we assert "no worse than hand-written" rather than matching a fixed instruction
sequence. That is why one reference configuration is enough to be useful.

🤝 Mentorship

@mpusz will help you through the PR process

📚 Skills Learned

  • Reading and reasoning about compiler-generated assembly
  • How -S and optimization levels affect codegen
  • Writing a small normalization and diff script (Python or shell)
  • CMake and CTest: adding a test that gates CI
  • The idea of zero-overhead abstractions and how to prove them

⏱️ Estimated Time

4-8 hours

🚀 Getting Started

  1. Try the comparison by hand first: put an mp-units function and a raw equivalent in one file,
    compile with -S -O2 on Clang, and look at the two functions side by side.
  2. See how examples and tests are wired in example/CMakeLists.txt and the test/ tree.
  3. Read the CI workflows under .github/workflows/ to see how a CTest-based job runs.
  4. Start with one pair (speed = distance / time) and byte-identical comparison after stripping
    comments and labels, then add a second pair.

✅ Acceptance Criteria

  • A new test compiles a TU of abstraction/baseline pairs with -S at release flags
  • Each pair's assembly is compared after normalization, and the test fails on any divergence
  • At least two representative operations are covered
  • Runs as a CTest test on one reference configuration in CI
  • Passes pre-commit formatting checks

📎 Additional Context

A general-purpose, cross-configuration assembly differ is a much harder, research-grade problem
(normalization and semantic equivalence) and is explicitly out of scope. Compiler Explorer
already covers interactive generation and diffing; the gap this fills is automated CI
regression gating of the zero-overhead guarantee. Where two functions are not byte-identical
but are equivalent, a follow-up can add property checks: no call, no stack spills, and the
same count of arithmetic instructions.

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions