Your Code is Fast — If You're Lucky
Compiler optimisation is fragile. A branchless quicksort case study that works on GCC 11 but fails on GCC 13. Plus a COBOL take on why this matters.
There's a piece doing the rounds on Hacker News today — 574 points, which in HN currency is roughly equivalent to a standing ovation from the entire internet — called "How to stop Claude from saying load-bearing."
But that's not the article I want to talk about.
The article I want to talk about is "Your code is fast – if you're lucky" by Christof Käser. It got less attention. It deserves more. Because it contains the single most humbling sentence I've read this month:
A hand-optimised branchless quicksort, with sorting networks, loop unrolling, and careful C — ran in 4.39 seconds on an M1. C++ std::sort ran in 1.33 seconds. After a cosmetic rewrite of the same algorithm — 0.70 seconds.
Same algorithm. Same compiler. Same flags. The only difference was how the code was written — not what it did, but the shape of the sentences on the page.
What actually happened
The original code used a verbose, beginner-friendly pointer style:
if (BLQS_CMP(x, piv)) { *lwr = x; lwr++; }
else { *rwr = x; rwr--; }
The rewritten version used a more idiomatic C style:
if (BLQS_CMP(x, piv)) *lwr++ = x;
else *rwr-- = x;
That's it. That's the change. No algorithmic insight. No clever data structure. No breakthrough. Just a different way of saying the same thing.
And Clang responded by emitting csel instructions — conditional select — instead of branches. The branchy version had mispredictions. The branchless version didn't. 4.39 seconds became 0.70 seconds.
GCC, by the way, doesn't care. It generates the same branchy code for both versions. So even your compiler vendor determines whether you're lucky or not.
The COBOL frog's translation
I spent fifteen years writing COBOL on mainframes. In COBOL, performance came from one thing: not doing I/O. You could write the most elegant, well-structured program in the world, and if you read a file record-by-record instead of in blocks, you were going home at midnight. The compiler was a known quantity. IBM's Enterprise COBOL hadn't changed its optimisation strategy in a decade. You learned the rules, you followed them, and your program ran at a predictable speed.
This article made me realise that modern C/C++ optimisation is the exact opposite. The compiler is not a known quantity. It's a moving target. It's a mood. Clang today is not Clang last year. Your code that ran beautifully on x86 might crawl on ARM. And a cosmetic change — one that no reviewer would ever flag — can be the difference between 0.7 seconds and 4.4 seconds.
That's not optimisation. That's astrology with a compiler flag.
What this means for the rest of us
There's a temptation here to say "write idiomatic code and trust the compiler." And that's good advice, as far as it goes. But it doesn't go very far, because what counts as idiomatic keeps changing. Ten years ago, the compact *lwr++ = x form was considered clever. Now it's just the way you write it if you want Clang to generate branchless code. And next year? Who knows.
I think the real lesson is more uncomfortable:
- Measure before you judge. The author's first version was slower than std::sort. If he'd stopped there and declared "hand-rolled sorting is a waste of time," he'd be wrong — his algorithm was fine, his expression of it was unlucky.
- Compiler optimisation is not deterministic. Not in the way we pretend it is. Two semantically identical programs can produce wildly different assembly. That's not a bug — it's a consequence of heuristic-driven optimisation in a massive search space. But it means your performance intuition is often wrong.
- Portable performance is a myth. The branchless version is only branchless on Clang. GCC produces branches. If your target environment changes — and in 2026, whose doesn't? — your "optimised" code can silently become slower.
The only real optimisation
I spent years in COBOL believing that performance was about knowing the system deeply. And it is — but the system you need to know has gotten bigger. It's not just the CPU and the I/O subsystem anymore. It's the compiler's internal heuristics, the version of LLVM, the target architecture, the exact shape of your source code, and whether today is a Tuesday.
The only optimisation that survives all of that is: write clear code, measure what matters, and accept that some days the compiler just doesn't like your style.
Your code is fast — if you're lucky. And most of the time, you're not as lucky as you think.