assert: Wrap __assert_fail in templated function
Noah Goldstein
goldstein.w.n@gmail.com
Sat Mar 8 23:37:16 GMT 2025
On Fri, Jul 26, 2024 at 4:15 AM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
>
> On Fri, Jul 26, 2024 at 3:22 PM Florian Weimer <fweimer@redhat.com> wrote:
> >
> > * Noah Goldstein:
> >
> > > The idea of this commit to essentially save code side in the "hot"
> > > `assert` passes case.
> > >
> > > By wrapping `__assert_fail` with a templated function and using the
> > > quasi unique `__LINE__` constant as the template parameter, we
> > > essentially ensure that each `assert` gets forwarded through a unique
> > > function. This then allows any reasonable optimizing compiler the
> > > clone the wrapper function and constant propagate the arguments passed
> > > (starts at -O2 for GCC/Clang). The result of the seperate, is that the
> > > codegen for setting up `__expression`, `__line`, `__file`, and
> > > `__functions` for the function call are moved to the presumed cold
> > > code on the assertion failure path. Having a seperate cold function
> > > allows the compiler/linker to move assertion setup code to a cold
> > > section ultimately saving space in potentially hot regions.
> > >
> > > See examples: https://godbolt.org/z/vMvrjnvaE
> >
> > Maybe the compiler can do this for us if we apply __COLD to
> > __assert_fail?
>
> https://godbolt.org/z/caox8YMY1
>
> This works on GCC, I'll post an independent patch and rebase this one
> one top.
>
> It doesn't help LLVM, however. LLVM has `--hot-cold-splitting`
> although at the moment it is regrettably unwilling fully de-optimize
> `noreturn` paths because of `longjmp`.... I know right.
> https://github.com/llvm/llvm-project/blob/main/llvm/lib/Transforms/IPO/HotColdSplitting.cpp#L151
>
> And since `__assert_fail` is non-standard (and not all libc implementations
> even agree on its definition (i.e `musl` using a `signed int` for
> line) it's hard
> to recognize this one case.
>
> If there were an attribute like `exits` that might be usable. But even
> so `--hot-cold-splitting` is not on any default pipelines so its seems
> unlikely that it will solve this problem anytime soon. (I am *slowly*
> working on patches to handle this, but not anytime soon).
>
> >
> > Thanks,
> > Florian
> >
Florian, any chance something like:
```
#if defined __cplusplus && __cplusplus >= 201103L
# define __ASSERT_FAIL_WRAPPER(assert_failure) \
[]() __attribute__ ((__noreturn__)) __COLD __attribute_noinline__ \
{ \
assert_failure; \
} \
()
#else
# define __ASSERT_FAIL_WRAPPER(assert_failure) assert_failure
#endif
```
Is clean enough you would accept it?
More information about the Libc-alpha
mailing list