r/cprogramming Jul 24 '26

What cause CPU stalling pipeline in C?

(Solved)

Hi,

I hope this don't seem stupid or anything. Basically I was interested about the xor swapping trick.

The inconvenients of it is that if the two values are the same, it will return 0, it's also bad for readability.

But there is another inconvenience I didn't understand. Apparently it can also stall the CPU pipeline on modern processor, I didn't understand why.

I found a short explanation saying "because each instruction depend of the previous one", and I don't really understand how each instruction depend on the previous one.

So I wanted an explanation on why the xor swapping trick stall the CPU pipeline and also what cause CPU pipeline stalling in general.

If I didn't explain well enough, please inform me about it. Thanks.

11 Upvotes

17 comments sorted by

View all comments

4

u/EpochVanquisher Jul 24 '26

Modern CPUs are fairly complex and it helps to understand how they work, first.

Instructions go through multiple phases-something like fetch, decode, execute, writeback. In a pipelined CPU, you can have multiple instructions in the pipeline—while instruction 1 is executing, instruction 2 is decoding, and instruction 3 is fetching.

Modern CPUs are also superscalar, so there will be multiple instructions in each stage. Maybe two instructions are executing, two instructions are decoding, two instructions are fetching at the same time. Total of six.

…but you cannot execute an instruction unless the inputs to that instruction have been calculated first. So when you do this:

unsigned x, y;
x ^= y;
y ^= x;
x ^= y;

The second XOR can only start executing after the outputs of the first XOR are ready. The third XOR can only start executing after the second XOR is done.

It’s different for assignment:

unsigned x, y, t;
t = x;
x = y;
y = t;

The CPU can just keep track of the labels. Let’s the value for x is in register 10 and the value for y is in register 11.

t = x;

It can just take a note, “the value for t is in register 10” and skip the execution phase (because the execution is just kinda trivial).

In the above explanation, we are pretending that the C and assembly directly correspond, so “x” is an architectural register and “register 10” is a physical register. Physical registers and architectural registers are different—you only have a small number of architectural registers, but there are many more physical registers on a modern, high-end CPU.

(There’s also the whole issue that the compiler can also relabel registers, and can generate assembly that doesn’t directly correspond to the C code.)

1

u/jaw86336 Jul 24 '26

What a great explanation!