On Sunday, 30 June 2024 08:33:35 GMT+2 Martin Uecker wrote:
> Am Sonntag, dem 30.06.2024 um 05:03 +0200 schrieb Matthias Kretz:
> > On Saturday, 29 June 2024 16:20:55 GMT+2 Martin Uecker wrote:
> > > Am Samstag, dem 29.06.2024 um 08:50 -0500 schrieb Matthias Kretz via 
Gcc:
> > > > I.e. once UB becomes IFNDR, the dreaded time-travel optimizations
> > > > can't
> > > > happen anymore. Instead precondition checks bubble up because
> > > > otherwise
> > > > the program is ill-formed.
> > > 
> > > It is not clear to mean what you mean by this?
> > 
> > It would help if you could point out what is unclear to you. I assume you
> > know IFNDR? And I gave an example for the "bubbling up" of precondition
> > checks directly above your quoted paragraph.
> 
> I think I understood it now:  You want to make UB be IFNDR so
> that the compiler is allowed to diagnose it at translation
> time in certain cases (although this would not generally be
> required for IFNDR).

Right, diagnosis of the error depends on const-prop and thus on compiler 
abilities and compiler flags. Which is why I'm asking for IFNDR on UB.

> > > Note that in C time-travel optimizations are already not allowed.
> > 
> > Then, calling __builtin_unreachable is non-conforming for C? ... at least
> > in the English sense of "this code is impossible to reach", which implies
> > that the condition leading up to it must be 'false', allowing time-travel
> > optimization. Or how would C define 'unreachable'?
> 
> __builtin_uneachable is an extension, it can do whatever it wants.

Sure. But it's nice ;) if the behavior of a function/builtin is reflected by 
its name (or the other way around).

> But note that compilers do not seem to eliminate the control flow path
> leading to it:
> 
> https://godbolt.org/z/coq9Yra1j

It seems like GCC and Clang consider function calls and volatile stores to 
have side effects that could potentially make the __builtin_unreachable 
unreachable :)
If you drop the 'volatile' like in

int i = 0;
int g(int x)
{
    if (x)  {
        i = 1;
        __builtin_unreachable();
    }
    return i;
}

... then the store to i is elided.

> So even if it is defined in terms of C's UB, these implementations
> would still be conforming to C.
> 
> > > But I am not sure how this is relevant here as this affects only
> > > observable behavior and the only case where GCC does not seem to
> > > already conform to this is volatile.
> > 
> > Now you lost me.
> 
> Consider the following example:
> 
> int f(int x)
> {
>  int r = 0;
>  if (x < 10)
>    r = 1;
>  if (x < 10)
>    __builtin_unreachable();
>  return r;
> }
> 
> But removing the store to 'r' here as GCC does:
> 
> https://godbolt.org/z/h7qqrGsbz
> 
> can simply be justified by the "as if" principle as
> any other optimization, it does not need to rely on a weird
> intepretation that the UB from __builin_unreachable() travels
> back in time.

I don't know of anybody saying that "time-travel optimization" refers to 
anything different than what you're showing here. The part that people find 
scary is when this "as if" happens at a distance, like in
https://godbolt.org/z/jP4x1c3E6

> > > Of course, C++ may be different but I suspect that some of the
> > > discussion is confusing compiler bugs with time-travel:
> > "some of the discussion" is referring to what?
> 
> To discussions inside WG21 that seems to believe that it
> is important that compilers can do  time-travel optimizations,
> when this is actually not the case.

In light of the above clarification (what we mean with "time-travel 
optimization"), this is simply about allowing inlining and as-if 
transformations. Therefore, yes, it is important.

> > [...]
> 
> I think it is a good idea. The compiler can optionally treat UB as
> a translation time error. We discussed similar ideas in the past
> in WG14. But this will only work for very specific instances of UB
> under certain conditions.

Yes. But it's an exact match of the "time-travel" cases. I.e. whenever const-
prop determines "unreachable" the code could be ill-formed.


> > > Also IMHO this should be split up from
> > > UBsan which has specific semantics and upstream dependencies
> > > which are are not always ideal.  (But UBSan could share the
> > > same infrastructure)
> > 
> > I'm not sure what you're thinking of here. UBsan detects UB at runtime
> > whereas my '-fharden=1' proposal is about flagging UB as ill-formed on
> > compile-time. So UBsan is a more verbose '-fharden=2' then?
> 
> Yes, I was talking about the -fharden=2 case. In principle UBSan
> with traps instead of diagnostics would do this. In practice,
> I think we need something which is not tied to UBSan.

Yes, basically a deployable variant of UBsan?


On Sunday, 30 June 2024 08:56:41 GMT+2 Martin Uecker wrote:
> 0) nothing
> 1) expands to __builtin_unreachable()
> 2) expands to __builtin_trap()
> 3) expands to a __builtin_warning (as suggested before
> by Martin Sebor) that causes the backend to emit an error
> in a very late pass when the __builtin_warning has not
> been removed during optimization.

This __builtin_warning seems to be equivalent to my __error() function, using 
a [[gnu::warning]] attribute instead of [[gnu::error]]. Which is certainly 
another viable build/-fharden/whateverwecallit mode.

- Matthias

-- 
──────────────────────────────────────────────────────────────────────────
 Dr. Matthias Kretz                           https://mattkretz.github.io
 GSI Helmholtz Center for Heavy Ion Research               https://gsi.de
 std::simd
──────────────────────────────────────────────────────────────────────────

Attachment: signature.asc
Description: This is a digitally signed message part.

Reply via email to