On Fri, Sep 5, 2025 at 9:23 AM Jakub Jelinek <ja...@redhat.com> wrote: > > 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).
Yes. I'll note that while we fixed some issues with code motion across possible exit points we do not have good means of testing for invalid code motion of UB invoking stmts. Guessing from the ones that actually caused traps the problem is likely bigger for UB causing stmts (I for example fixed PRE for trap(), but not for general UB - we'd have to avoid PREing all variable shifts or any signed arithmetic). For what you describe returns_twice would work given it adds an incoming edge, making the call first in a BB. This prevents any code motion upwards, it doesn't require us to classify stmts into those we can speculate and those we can't. On RTL a BARRIER might do the trick? Richard. > > Jakub >