Software Prefetch Instructions (PREFETCHT0/T1/T2/NTA): How Programmers Hint the CPU About the Future

2026-07-22

Hardware prefetchers are good at sequential and strided access, but they're blind to pointer chases, hash lookups, and irregular graph traversals. That's why x86 exposes explicit prefetch instructions — hints the CPU treats as loads that don't produce a value, don't fault on bad addresses, and don't stall the pipeline waiting for completion.

The four variants differ only in which cache level they target and how the line is marked for replacement:

The classic use case: linked-list traversal. When you dereference node->next, the CPU can't prefetch node->next->next because it doesn't know the address yet. But you do — as soon as next loads, issue a prefetch for it while processing the current node:

while (node) {
    __builtin_prefetch(node->next, 0, 3);  // T0, read-only
    process(node->data);
    node = node->next;
}

The 3 is the temporal locality hint (3=T0, 2=T1, 1=T2, 0=NTA). If process() takes ~100 cycles and DRAM latency is ~200 cycles, one iteration of prefetch distance isn't enough. Rule of thumb: prefetch distance = memory latency ÷ work per iteration. For 200ns memory and 50ns of work per node, you need to prefetch ~4 nodes ahead — meaning you need node->next->next->next->next, which requires unrolling or a look-ahead pointer.

Where it backfires: prefetching too aggressively pollutes L1 and steals memory bandwidth from demand loads. Prefetching too close (distance too small) means the line arrives after you need it — no benefit, all overhead. And on modern CPUs with beefy stream prefetchers, adding software prefetch to a simple sequential loop typically hurts performance because you're duplicating what hardware already does for free.

Real numbers: on Skylake, a well-tuned prefetch on a pointer-chasing workload commonly recovers 30–50% of the memory stall time. On a sequential loop over an array, the same instructions cost 1–2% with zero benefit.

Key Takeaway: Software prefetch is a scalpel for irregular access patterns the hardware prefetcher can't see — useless (or harmful) anywhere else, and only effective when the prefetch distance matches your loop's work-to-latency ratio.

All newsletters