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