One of the advantages of hand-written assembly is that you get to opt out of the compiler heuristics and commit to being able to spend the time to optimize the one bit of code that you know is really important for runtime as perfectly as you want, instead of relying on the compiler to get it close enough to perfect before it exhausts its budget of caring about optimizing it.
2. The ability to "cheat" on calling conventions.
3. The ability for techniques like threaded code, and in general, better cache-awareness.
4. Less mov's.
5. Guaranteeing no spilling in important loops.
6. Compilers don't do well with flags registers and you can't read/write them in high level languages. You're hoping your `if (result < a) { carry = 1; }` becomes a direct flag test. Especially important in bignum, you can't really utilise adcx/adox directly from high-level code.
7. Hot/cold layout without PGO. Yes PGO is good but sometimes you know better and PGO isn't very suitable for "configurable" code.
8. Computed goto. See https://github.com/python/cpython/issues/128563 , who doesn't like 10% free performance?
9. Exploiting uninitialised memory for classic party tricks like not initialising a buffer fully (let's say you have a library function with a return buffer. You don't want dynamic allocations for some reason. You can simulate this with a pointer return into a let's say a static 4KB buffer and a count return, you only initialise it until the count. Caller has the responsibility not to overread.)
It's rarely worth the effort.
There a lot of juice in improving the data structures that a compiler cannot do.
See stuff like https://davidlattimore.github.io/posts/2025/09/02/rustforge-...
This doesn't mean Rust is near perfect, it's just that your first move should be "how do I make the Rust better" and not "I need to drop into asm."
Talk about overengineering :P Multithreaded vector initialisation instead of just...skipping it?
Regarding ABI, calee-saved registers also often result in useless data shuffling and prevent the compiler from using them for argument/result passing.
Rust has autovectorization, but a developer knows their algorithms best.
Also AES-NI vs software is no contest.
When people talk about out coding ‘to the metal’ you have to consider what ‘the metal’ provides