mallya's blog

Measuring the return stack size on Alder Lake's P and E cores

14 Nov 2026 · Varun R Mallya · microarchitecture, x86, benchmarking

I wanted to know how big the return address stack (RAS, Intel calls it the RSB) is on my laptop. It’s an i7-12700H, so it has two kinds of cores: Golden Cove P-cores (cpus 0-11) and Gracemont E-cores (cpus 12-19). Intel doesn’t really publish these numbers anymore for newer cores, so the only way is to measure it.

The RAS is a small stack inside the branch predictor. Every call pushes the return address onto it and every ret pops it to guess where it is going back to. If you go deeper than the stack is, the oldest entries get overwritten, and on the way back up those returns get mispredicted. So the idea is simple: nest calls deeper and deeper and look for where ret suddenly gets slow.

The benchmark

I didn’t want the compiler doing anything clever, so the call chain is just raw asm. 256 functions, each one aligned to 16 bytes, each one just calls the next block and returns:

__asm__(
    ".text\n"
    ".balign 16\n"
    "chain_base:\n"
    ".rept 256\n"
    "  call .+16\n"      // call the next 16-byte block
    "  ret\n"
    "  .balign 16\n"
    ".endr\n"
    "  ret\n"
);
extern char chain_base[];

Since every block is the same size, jumping into the chain at chain_base + 16 * (256 - d) gives you a depth of exactly d. Then I just time it a lot of times and divide:

void (*fn)(void) = (void (*)(void))(chain_base + 16 * (MAXD - d));
double t0 = now();
for (int i = 0; i < iters; i++) fn();
double t = (now() - t0) / iters / (d + 1); // +1 for the outer call

Take the best of 7 runs for each depth and pin it to a core with taskset:

gcc -O2 -o ras ras.c
taskset -c 2  ./ras > pcore.csv
taskset -c 14 ./ras > ecore.csv

The full source is here.

Results

call+ret cost vs call depth

This honestly surprised me. The small core has a return stack around 6x the size of the big core. My first run only went up to depth 128 and the E-core line was completely flat, so I assumed it was falling back to the BTB once the RAS ran out (every ret in this chain always goes back to the same place, so the BTB would predict it perfectly). That was wrong. Going to 256 showed the knee was just sitting right at the edge of my range.

Does this match what others found?

Kind of. Intel’s optimization manual only says that Alder Lake gives each hardware thread its own copy of the return stack. No sizes. Agner Fog’s microarchitecture guide has 16 for Haswell through Skylake, and this post quotes 22 for Ice Lake and 128 for Gracemont, also measured. So 128 on the E-core lines up exactly, and ~20 on the P-core is in the same range as the older big cores. I couldn’t find anyone with a number for Golden Cove specifically.

Some caveats: