Skip to content

Commit e6d8aa3

Browse files
authored
Update 2025-11-30-comptime-c-functions.md
1 parent 22f8176 commit e6d8aa3

1 file changed

Lines changed: 9 additions & 6 deletions

File tree

_posts/2025-11-30-comptime-c-functions.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ macro_version:
1818
ret
1919
```
2020

21-
Here is how it is achieved in C:
21+
The best use-case I can think of for this technique is generating lookup tables at compile-time, since functions like `sin()` *also* successfully get optimized away. This technique seems to also work fine however for implementing runtime-allocated data structures, without needing macros.
22+
23+
# Required tricks
24+
2225
- `static inline` allows inlining across compilation boundaries.
2326
- `__attribute__((always_inline))` *strongly* urges compilers to inline functions.
2427
- `__builtin_unreachable()` is used to teach the optimizer which assumptions it can make about input arguments.
@@ -28,15 +31,15 @@ Here is how it is achieved in C:
2831
- All operations become statically analyzable, reducing to constants.
2932
- `assert()` calls get eliminated when conditions are provably true.
3033

31-
It's not actually "stack vs heap" that matters; what matters is whether the compiler can treat the buffer as a non-escaping, fully analyzable region of memory. Stack allocation makes that easy. Heap allocation only works in very simple cases where the pointer never escapes and all memory operations can be folded away.
34+
[Link-time optimization](https://en.wikipedia.org/wiki/Interprocedural_optimization) with `-flto` should allow Clang and GCC to perform these optimizations even when the code is split across several object files.
3235

33-
The best use-case I can think of for this technique is generating lookup tables at compile-time, since functions like `sin()` *also* successfully get optimized away. This technique seems to also work fine however for implementing runtime-allocated data structures, without needing macros.
36+
# Generic Stack
3437

35-
I added a `main()` function to the programs to prove that they don't crash on any `assert()` calls at runtime, but even when you remove `main()` the `fn_version()` and `macro_version()` functions get optimized just as hard.
38+
In this program I use `malloc()` and `free()` in order to demonstrate that they can be optimized away too.
3639

37-
[Link-time optimization](https://en.wikipedia.org/wiki/Interprocedural_optimization) with `-flto` should allow Clang and GCC to perform these optimizations even when the code is split across several object files.
40+
I added a `main()` function to the program to prove that it doesn't crash on any `assert()` calls at runtime.
3841

39-
# Generic Stack
42+
It's important to note that `fn_version()` and `macro_version()` get optimized just as hard, even when you remove the `main()`.
4043

4144
Copy of the code on [Compiler Explorer](https://godbolt.org/z/fdf5acdcn):
4245

0 commit comments

Comments
 (0)