Am Freitag, dem 05.09.2025 um 11:46 +0200 schrieb Richard Biener: > On Fri, Sep 5, 2025 at 10:07?AM Jakub Jelinek <ja...@redhat.com> wrote: > > > > On Fri, Sep 05, 2025 at 08:51:10AM +0100, Iain Sandoe wrote: > > > > BARRIER in RTL is like __builtin_unreachable (), so the observable > > > > checkpoint certainly can't be represented like that. > > > > Anyway, my point is that one call call std::observable_checkpoint () > > > > or exit (0) in any external function (unless say some standard describes > > > > what the function does), so we really should be creating any non-builtin > > > > call we know nothing about like that. > > > > > > A volatile read would work, I guess - but the issue then is where to read > > > from - the intent of the paper is to generate no code, i.e. that the > > > function > > > is only there for it?s effect as a checkpoint. > > > > I think a volatile read is not sufficient for preventing time travel. > > I think a CALL_INSN is safe (exactly because it could have done exit (0) > > or std::observable_checkpoint () inside of it where the compiler doesn't see > > it) but in RTL has the major disadvantage (even if optimized away during > > final) that RA clobbers all call clobbered registers there. > > I wonder if we treat a volatile asm similarly (especially with "memory" > > clobber), because it actually might contain a call, though obviously RA > > doesn't add the cost of clobbering call clobbered registers there (if one > > calls from inline asm, one needs to save/restore those registers or use > > a different ABI with no call clobbered registers or only the ones specified > > in clobbers of the inline asm). And inline asm can expand to nothing or > > almost nothing (the latter if it has inputs/outputs, but this one doesn't > > need any, just "memory"). > > Just to agree - a call is safe modulo bugs in GCC. A returns-twice call > is "safer" because it avoids a certain class of bugs in GCC. On RTL > there isn't much UB and UB exploiting cases left - it should be mostly > reads from uninitialized storage, so a memory barrier should work there. > TBAA might be another thing, but again a memory barrier should be OK.
In case it helps, one example where GCC "time-travels" UB relative to a volatile store is this one as the potentially trapping division can not be done unconditionally before the volatile store. https://godbolt.org/z/9YcM5Wd4x volatile int x; int foo(int a, int b, _Bool store_to_x) { if (!store_to_x) { return a / b; } x = b; return a / b; } Martin