On Fri, Sep 05, 2025 at 08:35:43AM +0200, Richard Biener wrote: > > i.e. keep it as a call to an optimization barrier until runtime > > but don't really do anything at that point. > > That's probably equivalent to the builtin.
But to a builtin which is preserved until end of expansion (not sure in what form, we can easily have just inline asm for optimization barriers in RTL, or perhaps emit a CALL_INSN and somehow optimize it away during final. The reason to use inline function was just not to commit to it as ABI for now, of course we could just also export a dummy nop function from libstdc++.so and just use some attributes on it. > I'll note that both are > less strong of a barrier than setjmp() or longjmp() which we > arrange to have abnormal incoming/outgoing edges so even > register computations cannot be moved across them. So > for extra barrier-ness you want to add returns_twice. Guess that depends on what exact side-effects we are fighting against. The paper in short says that UB which happens after calling these functions should not modify program behavior before these calls. I'd say we need to treat like that any external function we don't know anything about (e.g. because the function can possibly exit (0) or call this std::observable_checkpoint () function). So I think anything that acts as a (or possible) call to external unknown function (at least until final, doesn't have to be assembled as a call but unsure if we can assemble it on all targets as nothing) should have the right behavior. E.g. if we have [[gnu::const]] int bar (); void baz (); void foo (int *p) { int a = 42; if (p == nullptr) a = bar (); baz (); *p = a; } we can't really optimize away the p == nullptr check because the baz () function could call exit (0). Jakub