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

Reply via email to