|
|
Log in / Subscribe / Register

Tail-call optimization in C is relatively recent

Tail-call optimization in C is relatively recent

Posted Aug 21, 2025 22:11 UTC (Thu) by anton (subscriber, #25547)
Parent article: Python, tail calls, and performance

Actually tail calls in C have not been around forever. The C calling convention has been that the callee does not remove any stuff the caller has put on the stack. The caller could see the declaration int f();, the actual call could have n>0 arguments, and the actual function could have m≤n parameters. That would not always work if the callee removed the arguments.

So the caller had to remove the arguments between the call and the following return, turning the call into a non-tail call.

When I looked in 1994 at the C compilers of the day, they did not perform tail-call optimization for the kind of usage shown in the article. In 2001 Mark Probst implemented tail-call optimization in GCC with a separate calling convention; he lists the limitations of the then-existing tail-call optimization in GCC in section 6.4, among them: "It cannot handle indirect calls" (which would have been used in tail calls for interpreter dispatch).

I have not looked at the issue since then (GCC's goto * was good enough (well, mostly)), and I had not much reason for assuming that something had changed wrt to GCC support for tail-calls (although one release note mentioned sibcalls, and I remember thinking that I should be checking that out.

Anyway, last year I read the paper on "Copy-and-Patch Compilation" by Xu and Kjolstad, and they use tail-call optimization. In any case, after reading that paper, I made some tests if gcc and clang can do tail-call optimization for the kind of tail calls shown in the article. And it works. And Xu and Kjolstad report that they use 100,000 code snippets, whereas we limit ourselves in Gforth to <2000 (for VM instructions, stack caching variations thereof, static superinstructions etc.). Being able to do 100,000 would allow us to use techniques that need too many different code snippets to be usable in a goto *-based system.

We have not gotten around to putting this into Gforth yet, so congratulations to the Python community for being there first.


to post comments

Tail-call optimization in C is relatively recent

Posted Aug 23, 2025 19:43 UTC (Sat) by lafp (subscriber, #89554) [Link]

For what it's worth, I recently implemented a (toy) interpreter for a variant of Forth that uses tail calls for dispatching instructions. The main gain I had was making all the built-in functions behave like instructions themselves, rather than having a "call a built-in function" instruction; it also has support for a few handfuls of super-instructions, which helped quite a bit as they're not that different than anything else. The performance is pretty decent, but it'll need a bit more work in the optimizer to reach what I need it to reach (ultimately I want this to run on a small computer, expose the interpreter through a browser, and let people write code that's then used to control a LED matrix; think of this project, but in a smaller scale: https://www.noisebridge.net/wiki/Flaschen_Taschen).

The code is here (https://github.com/lpereira/lwan/blob/master/src/samples/...) and it's a variant of the Forth Haiku language, that lets you create art with small bits and pieces of Forth code, not unlike ShaderToy is for GLSL.

Tail-call optimization in C is relatively recent

Posted Aug 10, 2026 17:43 UTC (Mon) by Robbepop (guest, #185603) [Link]

Just today I re-benchmarked the upcoming Wasmi (WebAssembly Interpreter) version.

It makes heavy use of direct-threaded code (tail-calls) for its instruction dispatch but can be configured to use indirect-threading or even an old-school loop-switch dispatch. Benchmarks show an enormous performance difference between switch-loop and threaded-code techniques and that's why all modern and fast Wasm interpreters such as Wasmi, Wasm3 and Stitch are using tail-calls.

To me native tail-calls is one of the fundamentals for any true system programming language.

Further information & links:


Copyright © 2026, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds