On Tuesday, 25 June 2024 21:44:15 CDT Andrew Pinski via Gcc wrote:
> I am in the middle of improving the isolation path pass for shifts
> with out of range operands.
> There are 3 options we could do really:
> 1) isolate the path to __builtin_unreachable
> 2) isolate the path to __builtin_trap
>     This is what is currently done for null pointer and divide by zero
> 3) isolate the path and turn the shift into zero constant
>    This happens currently for explicit use in both match (in many
> cases) and VRP for others.

IIUC, I vote for __builtin_unreachable. However, I understand that there's no 
one-size-fits-all solution here.

Have you considered
4) ill-formed (no diagnostic required)?

I was told yesterday in WG21 session that an implementation is allowed to make 
a program ill-formed on precondition violation/UB. FWIW, I don't believe it. 
But there's an opportunity to be explored here.

Consider the following sketch

  [[gnu::noinline, gnu::error("precondition violation")]]
  void
  __error()
  { __builtin_unreachable(); }

  [[gnu::always_inline]]
  inline void
  __check_precondition(bool cond)
  {
    if (__builtin_constant_p(cond) && !cond)
      __error();
    else if (!cond)
  #ifdef __HARDEN__
      __builtin_trap();
  #else
      __builtin_unreachable();
  #endif
  }

  int
  operator<<(int a, int b) {
    __check_precondition(b >= 0 && b < 32);
    return // actual shift
  }

Then the following is ill-formed, which I think is fairly sensible:

  int f1(int x) { return x << 40; }

But the next example seems questionable:

  // precondition: c == false
  int f2(int x, bool c) { return c ? x << 40 : x; }

until one recognizes that 'f2' is missing a precondition check:

  int f2(int x, bool c) {
    __check_precondition(c == false);
    return c ? x << 40 : x;
  }

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.

Again, I don't believe this would be conforming to the C++ standard. But I 
believe it's a very interesting mode to add as a compiler flag.

-fharden=0 (default)
-fharden=1 (make UB ill-formed or unreachable)
-fharden=2 (make UB ill-formed or trap)

If there's interest I'd be willing to look into a patch to libstdc++, building 
upon the above sketch as a starting point. Ultimately, if this becomes a 
viable build mode, I'd like to have a replacement for the [[gnu::error("")]] 
hack with a dedicated builtin.

- 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