Map

Lucky Code โ€” Your code is fast, if you're lucky

Sources Christof Kasersource โ†ณ show in map Markdown
title
Lucky Code โ€” Your code is fast, if you're lucky
author
Christof Kaser
type
source
created
2026-07-18

Lucky Code

Your code is fast - if you're lucky

Recently, while I was working on an optimized Quicksort implementation, I came across a rather interesting quirk. Modern compilers (especially Clang) optimize loops using fast, branch-free instructions - provided you use the right programming style.

sort.h is a branchless quicksort using sorting networks and loop unrolling (MIT, christof.kaser@gmail.com). The hot loop lives in the partition / partition_small functions. test.c sorts 50 million doubles seeded from rand().

// test.c
#define BLQS_CMP(a, b) ((a) < (b))
#define BLQS_TYPE double
#include "sort.h"
#define SIZE 50000000
double data[SIZE];
int main() {
    for (int i = 0; i < SIZE; i++) data[i] = rand() / 1024.0;
    double t0 = ts();
    sort(data, SIZE);
    printf("Time: %.2fs\n", ts() - t0);
}

On macOS/M1 (Clang, -O3): Time: 4.39s. C++ std::sort needs 1.33 seconds for the same input.

A few cosmetic changes

The code is already micro-optimized using sorting networks and loop unrolling. Only a few cosmetic changes remain. The beginner-friendly style, which explicitly shows how the pointers are moved:

if (BLQS_CMP(x, piv)) { *lwr = x; lwr++; }
else { *rwr = x; rwr--; }

is rewritten into a more idiomatic and compact C form:

if (BLQS_CMP(x, piv)) *lwr++ = x;
else *rwr-- = x;

After this change: Time: 0.70s. More than 6 times faster than before, and nearly twice as fast as std::sort.

But what actually happened?

This "small cosmetic" change causes Clang to replace branches with csel.

With branches (AArch64):

loop:
    ldr  d0, [x12], #8
    fcmp d0, d8         ; compare value against pivot
    b.pl ge_case
    str  d0, [x20], #8  ; left++
    b    next
ge_case:
    str  d0, [x9], #-8  ; right--
next:
    cmp  x12, x_end
    b.lt loop

Fast with csel (branchless):

loop:
    ldr d0, [x9], #8
    fcmp  d0, d8            ; compare value against pivot
    csel x11, x0, x20, mi   ; target is left (x0) or right (x20)
    str d0, [x11]           ; store value to the selected destination
    csel  x12, x8, xzr, mi  ; left_step is 8 or 0
    csel  x13, xzr, x10, mi ; right_step is 0 or -8
    add   x0, x0, x12       ; left += left_step
    add   x20, x20, x13     ; right += right_step
    b.ls  loop

On x86, Clang behaves similarly: with the compact if, it generates branchless code using cmov (conditional move). GCC does not exhibit this quirk (different code generation for logically equivalent source). It consistently generates the slower branch-based version.

  • blqsort - Fast Quicksort with C and C++ Interface
  • "When 'if' slows you down, avoid it"
  • Interactive sorting demo

(Source note: the article reproduces the full ~200-line sort.h twice, before and after the change. Only the differing hot-loop lines are transcribed above; the sorting-network macros and partition scaffolding are identical between the two versions.)