<p>In original implementations of the B language, the caller was responsible for saving and restoring any registers it cares about before calling a function.<br />
But in the C language, the called function is responsible for saving and restoring any registers it is going to use.</p>
<p>Consider this code:</p>
<pre><code>for (index=0; index&lt;1000; ++index) {
    tally += f(index);
}
</code></pre>
<p>In B, the active registers can be saved before the loop and restored after it.<br />
That's 1 save and 1 restore.</p>
<p>In C, the function will preserve and restore the same register values every time it is called.<br />
That's 1000 saves and 1000 restores.</p>
<p>The first convention seems far more efficient, especially in cases where the function uses many registers.<br />
There doesn't appear to be <em>any</em> advantage to the second convention.</p>
<p>Yet, C was designed and implemented <em>after</em> B, and most other compiled languages developed since then follow that same convention.</p>
<p>Here is a description from 1981 by Johnson and Ritchie:</p>
<blockquote>
<p>The Basic Call/Return Process<br />
…<br />
3. Control passes to the called procedure.<br />
4. The bookkeeping registers and register variables of the calling procedure are saved so that their values can be restored on return<br />
…<br />
8. The returned value, if any, is put in a safe place while the stack space is freed, the calling procedure’s
register variables and bookkeeping registers are restored, and the return address is obtained and transferred to.<br />
— <a href="https://www.bell-labs.com/usr/dmr/www/clcs.pdf" rel="noreferrer">The C Language Calling Sequence</a></p>
</blockquote>
<p>A current definition from The Linux Foundation:</p>
<blockquote>
<p>Registers r6 through r13, r15, and f8 through f15 are nonvolatile; that is, they &quot;belong&quot; to the calling function.<br />
A called function shall save these registers' values before it changes them, restoring their values before it returns.<br />
— <a href="https://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_zSeries/x410.html" rel="noreferrer"><em>Function calling sequence</em></a></p>
</blockquote>
<p>If a function uses any of r6 through r13, it must save and restore them <em>each time</em> it is called.</p>
<p>It is more efficient for the <em>caller</em> to preserve whichever registers it needs, so why was this seemingly far less efficient convention chosen?</p>
<h3>NOTE:</h3>
<p>This question is about actual <em>implementations</em>, not about the <em>design</em> of the language itself, which says nothing about how calling stacks etc. should be implemented.</p>
<p>Also note that I'm asking about why this decision to change the protocols already in use with B was made for the very first C compilers in the 1970s.
I am not asking whether it is a good or bad idea for more recent hardware architectures, but why such as major change was made at that time.</p>

<implementation><c><optimization><calling-conventions><registers>
Why was C implemented with a register preservation convention that seems to be far less efficient than its predecessor's?
CC BY-SA 4.0
2023-05-19T01:54:54.057Z
[Register windows](https://en.wikipedia.org/wiki/Register_window) mitigate a lot of the cost of saving/restoring registers, as long as the call stack isn't too deep.
chrisaycock
CC BY-SA 4.0
2023-05-19T02:05:36.070Z
@chrisaycock, that concept didn't exist in the 1970s.
Ray Butterworth
CC BY-SA 4.0
2023-05-19T07:37:04.000Z
Your question is not clear: are you talking about the first implementation of C on the PDP-11? Modern implementations typically have some registers be caller-saved and some be callee-saved, with rules (part of the ABI specification) that depend on the CPU type (and on some platforms, also on the OS). I have no idea where you're going with “most other compiled languages developed since then follow that same convention”: languages don't define register conventions, implementations do, and implementations typically follow the platform's ABI to be able to link with system libraries.
Gilles 'SO- stop being evil'
CC BY-SA 4.0
2023-05-19T12:23:12.827Z
@Gilles'SO-stopbeingevil', I'm talking about every implementation of C that I've seen.  And as you say, libraries could have been written in any language, and those languages too must follow this convention of having the registers preserved by the called function. (I've added a couple of real examples.)
Ray Butterworth
<p>How registers behave across function calls is part of the <a href="https://en.wikipedia.org/wiki/Calling_convention" rel="noreferrer">calling conventions</a> defined by a particular language implementation. To facilitate cross-implementation and cross-language calls, most platforms specify a calling convention that holds for all programs on a particular CPU architecture, or at least on a particular operating system on a particular architecture. The standard term for a register that a function must save if it modifies it is <em>callee-saved register</em>, also called <em>preserved register</em> or <em>nonvolatile register</em>. The standard term for a register that the caller must save before calling a function is <em>caller-saved register</em>, also called <em>clobbered register</em> or <em>volatile register</em>.</p>
<p>Note that this is not particularly related to the programming language. C, in particular, does not mandate any particular rule. I am not aware that C is markedly different to other programming language in terms of favoring caller-saved or callee-saved registers.</p>
<p>Your assertion that making all registers caller-saved is more efficient is simply wrong. Sometimes caller-saved registers are more efficient, sometimes callee-saved registers are more efficient. Having both gives a chance to pick the more efficient kind where it matters.</p>
<p>Let's look at your example:</p>
<pre><code>for (index=0; index&lt;1000; ++index) {
    tally += f(index);
}
</code></pre>
<p>Let's suppose that <code>tally</code> and <code>index</code> are each stored in a register. What's the most efficient way to manage these registers? It depends on what <code>f</code> does!</p>
<p>If the compiler puts the variables in a caller-saved register, they have to be saved and restored around each loop iteration. If the compiler puts the variable in a callee-saved register, then whether they are saved or not depends on <code>f</code>. If <code>f</code> is a small function that doesn't do much (e.g. it's just an array lookup), then maybe it doesn't touch these registers, and so the registers don't need to be saved at all. On the other hand, if <code>f</code> is a complex function that needs all the registers it can have, it will need to save those registers at each call. So that's either a significant saving with callee-saved registers (if <code>f</code> uses very few registers, then typically it doesn't do much, and saving registers would be costly relative to the code of <code>f</code>), or indifferent.</p>
<p>On the other hand, for variables that don't change across the loop, having caller-saved registers is more efficient, as you note.</p>
<p>Another advantage of callee-saved registers is that a function has only one implementation, but is typically called from many sites. If the code to save registers (and also code to adjust the stack pointer) is inside the function, this leads to more compact code. More compact code is faster code since it spends less time getting loaded and it uses caches more efficiently.</p>
<p>Certain kinds of registers practically have to be of a particular type. Registers that influence how the processor works (for example, configuring memory mappings or floating point rounding modes) are pretty much always callee-saved, because most functions don't modify them: the rare functions that need a nonstandard value have to save and restore such registers. Conversely, some registers that are very frequently modified, such as condition flag registers, are typically caller-saved, because almost all functions will modify them, but callers often don't need to preserve them across function calls. Registers that contain function parameters are effectively caller-saved since the calling code itself modifies them, and registers that contain function return values are effectively caller-saved since it's the callee's job not to preserve them.</p>
<p>As a special case, when function calls take place across a privilege level, it's always the job of the most privileged side to save and restore registers: when privileged code starts, it can't trust anything about the values in registers that were written by the non-privileged code, so it needs to restore anything that it cares about; and when privileged code ends, it must wipe any confidential data from registers, since it can't trust that the non-privileged code won't read them.</p>
<p>See also:</p>
<ul>
<li><a href="https://stackoverflow.com/questions/9268586/what-are-callee-and-caller-saved-registers">What are callee and caller saved registers?</a></li>
<li><a href="https://stackoverflow.com/questions/65864046/why-make-some-registers-caller-saved-and-others-callee-saved-why-not-make-the-c">Why make some registers caller-saved and others callee-saved? Why not make the caller save everything it wants saved?</a></li>
<li><a href="https://cs.stackexchange.com/questions/108986/why-are-both-caller-save-registers-and-callee-save-registers-needed">Why are both caller-save registers and callee save registers needed?</a></li>
</ul>

CC BY-SA 4.0
2023-05-20T20:37:09.847Z
2023-05-20T20:37:09.847Z
Gilles 'SO- stop being evil'
CC BY-SA 4.0
2023-05-21T01:20:08.823Z
Thanks (+1).
One problem I have trouble with is that most of the modern registers didn't exist back when C was first implemented, and it was the programmer, not the compiler, that suggested which variables should be in registers. Anyone writing that loop wouldn't bother to suggest that `index` or `tally` should be registers, since their use is trivial compared with whatever it is the function does.
The other problem is that before C, I was intimate with the workings of B, which had caller-saved registers, and I still don't understand *why* the switch was made from one method to the other.
Ray Butterworth
CC BY-SA 4.0
2023-05-21T10:08:54.170Z
@RayButterworth In response to my comment under your question, you clarified that you were asking about C implementations in general, and not about the specific case of the original C implementation on the PDP-11 (which is extremely register-starved by modern standards). If you want to know what choices went into that specific implementation, that would be a different (also on-topic) question.
Gilles 'SO- stop being evil'
CC BY-SA 4.0
2023-05-21T13:10:50.883Z
I did ask in context of "*C was designed and implemented after B*". I've just added a note about this at the end to make it more explicit.
Ray Butterworth
CC BY-SA 4.0
2023-05-21T19:14:58.187Z
Your latest edit completely contradicts your previous one where you stated you were asking about “every implementation”! Please don't edit answered questions in ways that invalidate answers. There's really room for separate questions here, go ahead and ask a second one!
Gilles 'SO- stop being evil'
CC BY-SA 4.0
2023-05-21T20:33:02.160Z
"*you stated you were asking about “every implementation”*" — No. That wasn't an edit, it was in a comment. And it meant that this situation was true in "*every implementation*". Once a decision has been made, future versions will have to use the same conventions so that the libraries stay compatible.  The language B was written by Ken Thompson and Dennis Ritchie in 1969, so I guess the fundamental question is why Ritchie changed the convention when he wrote and implemented C.
Ray Butterworth
CC BY-SA 4.0
2023-05-21T20:39:19.610Z
@RayButterworth It's not true in every implementation of C: the disposition of registers depends on the platform. Do you mean every implemntation of C *on the PDP-11*? (I don't even know if the PDP-11 does have a standard calling convention: that wasn't such a big deal back then.)
Gilles 'SO- stop being evil'
<p>Guess 1: Time.  B's ABI assumed that the callee would destroy everything, and thus required that the caller preserve itself.  The C authors perhaps thought that wasteful of time, especially when calling tiny little leaf functions that did <em>not</em> much perturb the machine's state, and decided to flip that on its head:  Callees now responsible for preserving the machine's state if they were going to get a bit wild beyond using the resources deemed to be volatile in the ABI.  (r0 and r1 in the PDP-11, for example.)  Calling 'little' functions is now faster.  (More speed is always welcome, especially on the earlier machines that weren't all that fast to begin with.) Note that a large part of early libc was merely the OS interface.  Heavily-used 'functions' like open/close/read/write that were written in assembly language and were mere traps that did not perturb <em>any</em> of the machine state so far as the callers were concerned.</p>
<p>Guess 2: Space.  Lots of functions are 'utility', in that they're called from more than one place.  By making the callee responsible for cleaning up its own mess that cleanup code is in <em>one</em> place instead of being replicated in all the callers.  Calling functions, period, is now smaller if a function is called in more than one place.  (A PDP-11 is not a particularly spacious machine, especially the first ones.)</p>
<p>It was perhaps an experiment as much as a formal decision.  &quot;I don't like this (B) for <em>X</em> reasons, let's try it the other way this time and see how that works out.&quot;</p>
<p>C was early enough that it was still feeling such things out.  It obviously was enormously successful, so much so that it influenced most subsequent ABIs.</p>
<blockquote>
<p>In B, the active registers can be saved before the loop and restored
after it.</p>
</blockquote>
<p><em>Was</em> it that smart?  (Esp. on the PDP-11.)  If not, that argument is voided.  (I personally have no experience with B at all.)</p>

CC BY-SA 4.0
2024-10-13T15:53:44.423Z
2024-10-13T16:23:08.673Z
2024-10-13T16:23:08.673Z
jimc
CC BY-SA 4.0
2024-11-22T13:08:22.273Z
Pure speculation: Perhaps the change from B to C was in part motivated by an intention to favour small short utility functions, as a language design decision. Make it so that there is little reason, not even performance-wise, to not split code into functions.
Pablo H
<p>The C language does not require that it be implemented on a register transfer machine, let alone define which registers are callee-save and which registers are caller-save.</p>
<p>This is the job of the ABI on a given platform. For example, there is <a href="https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170" rel="noreferrer">an ABI for x64 on Windows</a>, and the <a href="https://www.uclibc.org/docs/psABI-x86_64.pdf" rel="noreferrer">SysV ABI is used for x64</a> pretty much everywhere else.</p>
<p>The ABI document says which registers are used for various purposes, such as:</p>
<ul>
<li>parameter passing,</li>
<li>return values,</li>
<li>return location on CPUs without call and return instructions,</li>
<li>thread-local storage,</li>
<li>position-independent code on CPUs that need to reserve a register for this, and</li>
<li>which general-purpose registers are callee-save and which are caller-save across a call.</li>
</ul>

CC BY-SA 4.0
2023-05-19T03:00:25.293Z
2023-05-19T03:00:25.293Z
Pseudonym
CC BY-SA 4.0
2023-05-19T03:25:07.640Z
The question isn't about the design of the language, it's about the implementation. (I've just clarified the Title accordingly.)
Ray Butterworth
CC BY-SA 4.0
2023-05-19T03:45:02.800Z
I don't believe the C language standard mentions this at all. Do you know something that I don't?
Pseudonym
CC BY-SA 4.0
2023-07-17T16:43:15.083Z
@Pseudonym: The C language doesn't fully specify any particular dialect.  Most dialects of C can interoperate with programs written in other languages; calling conventions used for such interop are part of the semantics of the dialects in question, rather than just implementation details.
supercat
CC BY-SA 4.0
2023-07-17T23:36:10.797Z
In the 1980s, the Microsoft C Compiler had a P-code (i.e. stack machine) backend for those times when memory usage was more precious than execution time.
Pseudonym
# Why was C implemented with a register preservation convention that seems to be far less efficient than its predecessor's?
Posted by: username_0 on 2023-05-19
In original implementations of the B language, the caller was responsible for saving and restoring any registers it cares about before calling a function.
But in the C language, the called function is responsible for saving and restoring any registers it is going to use.
Consider this code:
for (index=0; index<1000; ++index) {
    tally += f(index);
}

In B, the active registers can be saved before the loop and restored after it.
That's 1 save and 1 restore.
In C, the function will preserve and restore the same register values every time it is called.
That's 1000 saves and 1000 restores.
The first convention seems far more efficient, especially in cases where the function uses many registers.
There doesn't appear to be any advantage to the second convention.
Yet, C was designed and implemented after B, and most other compiled languages developed since then follow that same convention.
Here is a description from 1981 by Johnson and Ritchie:

The Basic Call/Return Process
…
3. Control passes to the called procedure.
4. The bookkeeping registers and register variables of the calling procedure are saved so that their values can be restored on return
…
8. The returned value, if any, is put in a safe place while the stack space is freed, the calling procedure’s
register variables and bookkeeping registers are restored, and the return address is obtained and transferred to.
— The C Language Calling Sequence

A current definition from The Linux Foundation:

Registers r6 through r13, r15, and f8 through f15 are nonvolatile; that is, they "belong" to the calling function.
A called function shall save these registers' values before it changes them, restoring their values before it returns.
— Function calling sequence

If a function uses any of r6 through r13, it must save and restore them each time it is called.
It is more efficient for the caller to preserve whichever registers it needs, so why was this seemingly far less efficient convention chosen?
NOTE:
This question is about actual implementations, not about the design of the language itself, which says nothing about how calling stacks etc. should be implemented.
Also note that I'm asking about why this decision to change the protocols already in use with B was made for the very first C compilers in the 1970s.
I am not asking whether it is a good or bad idea for more recent hardware architectures, but why such as major change was made at that time.
**Tags:** implementation c optimization calling-conventions registers
> **Comments:**
> **username_1**: [Register windows](https://en.wikipedia.org/wiki/Register_window) mitigate a lot of the cost of saving/restoring registers, as long as the call stack isn't too deep.  
> **username_0**: @chrisaycock, that concept didn't exist in the 1970s.  
> **username_2**: Your question is not clear: are you talking about the first implementation of C on the PDP-11? Modern implementations typically have some registers be caller-saved and some be callee-saved, with rules (part of the ABI specification) that depend on the CPU type (and on some platforms, also on the OS). I have no idea where you're going with “most other compiled languages developed since then follow that same convention”: languages don't define register conventions, implementations do, and implementations typically follow the platform's ABI to be able to link with system libraries.  
> **username_0**: @Gilles'SO-stopbeingevil', I'm talking about every implementation of C that I've seen.  And as you say, libraries could have been written in any language, and those languages too must follow this convention of having the registers preserved by the called function. (I've added a couple of real examples.)  
---
## 3 answers
### Answer by username_2 on 2023-05-20. Score: 14
How registers behave across function calls is part of the calling conventions defined by a particular language implementation. To facilitate cross-implementation and cross-language calls, most platforms specify a calling convention that holds for all programs on a particular CPU architecture, or at least on a particular operating system on a particular architecture. The standard term for a register that a function must save if it modifies it is callee-saved register, also called preserved register or nonvolatile register. The standard term for a register that the caller must save before calling a function is caller-saved register, also called clobbered register or volatile register.
Note that this is not particularly related to the programming language. C, in particular, does not mandate any particular rule. I am not aware that C is markedly different to other programming language in terms of favoring caller-saved or callee-saved registers.
Your assertion that making all registers caller-saved is more efficient is simply wrong. Sometimes caller-saved registers are more efficient, sometimes callee-saved registers are more efficient. Having both gives a chance to pick the more efficient kind where it matters.
Let's look at your example:
for (index=0; index<1000; ++index) {
    tally += f(index);
}

Let's suppose that tally and index are each stored in a register. What's the most efficient way to manage these registers? It depends on what f does!
If the compiler puts the variables in a caller-saved register, they have to be saved and restored around each loop iteration. If the compiler puts the variable in a callee-saved register, then whether they are saved or not depends on f. If f is a small function that doesn't do much (e.g. it's just an array lookup), then maybe it doesn't touch these registers, and so the registers don't need to be saved at all. On the other hand, if f is a complex function that needs all the registers it can have, it will need to save those registers at each call. So that's either a significant saving with callee-saved registers (if f uses very few registers, then typically it doesn't do much, and saving registers would be costly relative to the code of f), or indifferent.
On the other hand, for variables that don't change across the loop, having caller-saved registers is more efficient, as you note.
Another advantage of callee-saved registers is that a function has only one implementation, but is typically called from many sites. If the code to save registers (and also code to adjust the stack pointer) is inside the function, this leads to more compact code. More compact code is faster code since it spends less time getting loaded and it uses caches more efficiently.
Certain kinds of registers practically have to be of a particular type. Registers that influence how the processor works (for example, configuring memory mappings or floating point rounding modes) are pretty much always callee-saved, because most functions don't modify them: the rare functions that need a nonstandard value have to save and restore such registers. Conversely, some registers that are very frequently modified, such as condition flag registers, are typically caller-saved, because almost all functions will modify them, but callers often don't need to preserve them across function calls. Registers that contain function parameters are effectively caller-saved since the calling code itself modifies them, and registers that contain function return values are effectively caller-saved since it's the callee's job not to preserve them.
As a special case, when function calls take place across a privilege level, it's always the job of the most privileged side to save and restore registers: when privileged code starts, it can't trust anything about the values in registers that were written by the non-privileged code, so it needs to restore anything that it cares about; and when privileged code ends, it must wipe any confidential data from registers, since it can't trust that the non-privileged code won't read them.
See also:

What are callee and caller saved registers?
Why make some registers caller-saved and others callee-saved? Why not make the caller save everything it wants saved?
Why are both caller-save registers and callee save registers needed?
> **Comments:**
> **username_0** (2023-05-21): Thanks (+1).
One problem I have trouble with is that most of the modern registers didn't exist back when C was first implemented, and it was the programmer, not the compiler, that suggested which variables should be in registers. Anyone writing that loop wouldn't bother to suggest that `index` or `tally` should be registers, since their use is trivial compared with whatever it is the function does.
The other problem is that before C, I was intimate with the workings of B, which had caller-saved registers, and I still don't understand *why* the switch was made from one method to the other.  
> **username_2** (2023-05-21): @RayButterworth In response to my comment under your question, you clarified that you were asking about C implementations in general, and not about the specific case of the original C implementation on the PDP-11 (which is extremely register-starved by modern standards). If you want to know what choices went into that specific implementation, that would be a different (also on-topic) question.  
> **username_0** (2023-05-21): I did ask in context of "*C was designed and implemented after B*". I've just added a note about this at the end to make it more explicit.  
> **username_2** (2023-05-21): Your latest edit completely contradicts your previous one where you stated you were asking about “every implementation”! Please don't edit answered questions in ways that invalidate answers. There's really room for separate questions here, go ahead and ask a second one!  
> **username_0** (2023-05-21): "*you stated you were asking about “every implementation”*" — No. That wasn't an edit, it was in a comment. And it meant that this situation was true in "*every implementation*". Once a decision has been made, future versions will have to use the same conventions so that the libraries stay compatible.  The language B was written by Ken Thompson and Dennis Ritchie in 1969, so I guess the fundamental question is why Ritchie changed the convention when he wrote and implemented C.  
> **username_2** (2023-05-21): @RayButterworth It's not true in every implementation of C: the disposition of registers depends on the platform. Do you mean every implemntation of C *on the PDP-11*? (I don't even know if the PDP-11 does have a standard calling convention: that wasn't such a big deal back then.)  
---
### Answer by username_5 on 2023-05-19. Score: 8
The C language does not require that it be implemented on a register transfer machine, let alone define which registers are callee-save and which registers are caller-save.

This is the job of the ABI on a given platform. For example, there is [an ABI for x64 on Windows](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170), and the [SysV ABI is used for x64](https://www.uclibc.org/docs/psABI-x86_64.pdf) pretty much everywhere else.

The ABI document says which registers are used for various purposes, such as:

* parameter passing,
* return values,
* return location on CPUs without call and return instructions,
* thread-local storage,
* position-independent code on CPUs that need to reserve a register for this, and
* which general-purpose registers are callee-save and which are caller-save across a call.
> **Comments:**
> **username_0** (2023-05-19): The question isn't about the design of the language, it's about the implementation. (I've just clarified the Title accordingly.)  
> **username_5** (2023-05-19): I don't believe the C language standard mentions this at all. Do you know something that I don't?  
> **username_6** (2023-07-17): @Pseudonym: The C language doesn't fully specify any particular dialect.  Most dialects of C can interoperate with programs written in other languages; calling conventions used for such interop are part of the semantics of the dialects in question, rather than just implementation details.  
> **username_5** (2023-07-17): In the 1980s, the Microsoft C Compiler had a P-code (i.e. stack machine) backend for those times when memory usage was more precious than execution time.  
---
### Answer by username_3 on 2024-10-13. Score: 4
Guess 1: Time. B's ABI assumed that the callee would destroy everything, and thus required that the caller preserve itself. The C authors perhaps thought that wasteful of time, especially when calling tiny little leaf functions that did *not* much perturb the machine's state, and decided to flip that on its head: Callees now responsible for preserving the machine's state if they were going to get a bit wild beyond using the resources deemed to be volatile in the ABI. (r0 and r1 in the PDP-11, for example.) Calling 'little' functions is now faster. (More speed is always welcome, especially on the earlier machines that weren't all that fast to begin with.) Note that a large part of early libc was merely the OS interface. Heavily-used 'functions' like open/close/read/write that were written in assembly language and were mere traps that did not perturb *any* of the machine state so far as the callers were concerned.

Guess 2: Space. Lots of functions are 'utility', in that they're called from more than one place. By making the callee responsible for cleaning up its own mess that cleanup code is in *one* place instead of being replicated in all the callers. Calling functions, period, is now smaller if a function is called in more than one place. (A PDP-11 is not a particularly spacious machine, especially the first ones.)

It was perhaps an experiment as much as a formal decision. "I don't like this (B) for *X* reasons, let's try it the other way this time and see how that works out."

C was early enough that it was still feeling such things out. It obviously was enormously successful, so much so that it influenced most subsequent ABIs.

> In B, the active registers can be saved before the loop and restored
> after it.

*Was* it that smart? (Esp. on the PDP-11.) If not, that argument is voided. (I personally have no experience with B at all.)
> **Comments:**
> **username_4** (2024-11-22): Pure speculation: Perhaps the change from B to C was in part motivated by an intention to favour small short utility functions, as a language design decision. Make it so that there is little reason, not even performance-wise, to not split code into functions.  
---
