public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
From: Matthias Kretz <m.kretz@gsi.de>
To: GCC Mailing List <gcc@gcc.gnu.org>
Cc: Andrew Pinski <pinskia@gmail.com>, <libstdc++@gcc.gnu.org>
Subject: IFNDR on UB? [was: Straw poll on shifts with out of range operands]
Date: Sat, 29 Jun 2024 08:50:53 -0500	[thread overview]
Message-ID: <4588024.GUh0CODmnK@vir-laptop> (raw)
In-Reply-To: <CA+=Sn1m+2inAtFXMMz1M2VsJ178hDJiwsCJdVrp8wRHf7jYRuw@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 3116 bytes --]

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 #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

  parent reply	other threads:[~2024-06-29 13:50 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-26  2:44 Straw poll on shifts with out of range operands Andrew Pinski
2024-06-26  2:57 ` Jeff Law
2024-06-26  6:46   ` Richard Biener
2024-06-29 13:50 ` Matthias Kretz [this message]
2024-06-29 14:20   ` IFNDR on UB? [was: Straw poll on shifts with out of range operands] Martin Uecker
2024-06-30  3:03     ` Matthias Kretz
2024-06-30  6:33       ` Martin Uecker
2024-06-30  6:56         ` Martin Uecker
2024-07-01 13:19         ` Matthias Kretz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4588024.GUh0CODmnK@vir-laptop \
    --to=m.kretz@gsi.de \
    --cc=gcc@gcc.gnu.org \
    --cc=libstdc++@gcc.gnu.org \
    --cc=pinskia@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).