public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/109945] New: Escape analysis hates copy elision: different result with -O1 vs -O2
@ 2023-05-23 14:00 arthur.j.odwyer at gmail dot com
  2023-05-23 16:09 ` [Bug tree-optimization/109945] " rguenth at gcc dot gnu.org
                   ` (32 more replies)
  0 siblings, 33 replies; 34+ messages in thread
From: arthur.j.odwyer at gmail dot com @ 2023-05-23 14:00 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109945

            Bug ID: 109945
           Summary: Escape analysis hates copy elision: different result
                    with -O1 vs -O2
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arthur.j.odwyer at gmail dot com
  Target Milestone: ---

Background:
https://quuxplusone.github.io/blog/2021/03/07/copy-elision-borks-escape-analysis/
The background paradox here is, "When class Widget is subject to copy elision,
then any unseen function can return a prvalue Widget whose address has already
escaped!" Aaron Puchert and I were discussing this, with examples. (He thinks
the resolution of the paradox is "you *must* treat a lot more things as
escaped"; I think an acceptable resolution would be "you may treat copy-elision
itself as a magic that invalidates pointers and references even though the
object is still in the same place.")
But then I came up with an example that didn't rely on copy elision at all. We
both agree this code is perfectly well-defined — yet GCC miscompiles it at -O1!

// https://godbolt.org/z/bTnv68nhG
struct Widget {
    Widget();
    int i = 1;
    int a[4];
};
Widget *global = nullptr;
Widget::Widget() { global = this; }
Widget make() { return Widget(); }
void g() { global->i = 42; }
int main() {
  Widget w = make();
  int i = w.i;
  g();
  return (i == w.i);
    // Does this need to be reloaded and
    // compared? or is it obviously true?  
}

gcc -O0 and gcc -O2 both correctly return 0 from main.
gcc -O1 wrongly returns 1 from main.

*At least* since C++17, I think the -O1 result is flat-out wrong codegen. We
have `global == &w`, and so the call to `g()` can definitely modify `w.i`.

(Clang always treats Widgets' addresses as escaped, no matter what Widget looks
like. MSVC's escape analysis is more complicated and I have not yet been able
to trick it into wrong codegen.)

^ permalink raw reply	[flat|nested] 34+ messages in thread

end of thread, other threads:[~2024-03-01 17:21 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-23 14:00 [Bug c++/109945] New: Escape analysis hates copy elision: different result with -O1 vs -O2 arthur.j.odwyer at gmail dot com
2023-05-23 16:09 ` [Bug tree-optimization/109945] " rguenth at gcc dot gnu.org
2023-05-23 16:11 ` rguenth at gcc dot gnu.org
2023-05-23 16:19 ` pinskia at gcc dot gnu.org
2023-05-23 16:48 ` rguenth at gcc dot gnu.org
2023-05-23 16:53 ` rguenth at gcc dot gnu.org
2023-05-23 16:53 ` pinskia at gcc dot gnu.org
2023-05-23 17:46 ` arthur.j.odwyer at gmail dot com
2023-05-23 17:49 ` pinskia at gcc dot gnu.org
2023-05-23 17:52 ` pinskia at gcc dot gnu.org
2023-05-23 17:53 ` pinskia at gcc dot gnu.org
2023-05-23 19:38 ` arthur.j.odwyer at gmail dot com
2023-05-24  6:48 ` rguenth at gcc dot gnu.org
2023-05-24  7:59 ` rguenth at gcc dot gnu.org
2023-05-24  8:16 ` jakub at gcc dot gnu.org
2023-05-24  8:42 ` rguenther at suse dot de
2023-05-24  8:51 ` jakub at gcc dot gnu.org
2023-05-24  8:55 ` rguenther at suse dot de
2023-05-24  9:00 ` jakub at gcc dot gnu.org
2023-05-24 10:12 ` rguenth at gcc dot gnu.org
2023-07-01 23:37 ` pinskia at gcc dot gnu.org
2023-07-10  8:52 ` rguenth at gcc dot gnu.org
2024-02-20  9:58 ` rguenth at gcc dot gnu.org
2024-02-20 10:45 ` jakub at gcc dot gnu.org
2024-02-20 11:53 ` jakub at gcc dot gnu.org
2024-02-20 12:07 ` redi at gcc dot gnu.org
2024-02-20 12:15 ` redi at gcc dot gnu.org
2024-02-20 12:33 ` rguenth at gcc dot gnu.org
2024-02-20 12:41 ` redi at gcc dot gnu.org
2024-02-20 12:48 ` jakub at gcc dot gnu.org
2024-02-20 15:47 ` arthur.j.odwyer at gmail dot com
2024-02-20 15:52 ` arthur.j.odwyer at gmail dot com
2024-02-20 16:49 ` redi at gcc dot gnu.org
2024-03-01 17:20 ` redi at gcc dot gnu.org

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).