public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug tree-optimization/100004] New: Dead write not removed when indirection is introduced.
@ 2021-04-09 17:01 hiraditya at msn dot com
  2021-04-09 17:01 ` [Bug tree-optimization/100004] " hiraditya at msn dot com
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: hiraditya at msn dot com @ 2021-04-09 17:01 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 100004
           Summary: Dead write not removed when indirection is introduced.
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: hiraditya at msn dot com
  Target Milestone: ---

struct Foo {
    int x;
};

struct Bar {
    int x;
};

void alias(Foo* foo, Bar* bar) {
    foo->x = 5;
    foo->x = bar->x;
}

struct Wrap1 {
    Foo foo;
};

struct Wrap2 {
    Foo foo;
};

void assign_direct(Wrap1* w1, Wrap2* w2)
{
    w1->foo.x = 5;
    w1->foo.x = w2->foo.x;
}

void assign_via_pointer(Wrap1* w1, Wrap2* w2)
{
    Foo* f1 = &w1->foo;
    Foo* f2 = &w2->foo;
    f1->x = 5;
    f1->x = f2->x;
}


$ gcc-arm64 -O2 -std=c++17 -fstrict-aliasing -S -o -

alias(Foo*, Bar*):
        ldr     w1, [x1]
        str     w1, [x0]
        ret
assign_direct(Wrap1*, Wrap2*):
        ldr     w1, [x1]
        str     w1, [x0]
        ret
assign_via_pointer(Wrap1*, Wrap2*):
        mov     w2, 5
        str     w2, [x0]
        ldr     w1, [x1]
        str     w1, [x0]
        ret

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

* [Bug tree-optimization/100004] Dead write not removed when indirection is introduced.
  2021-04-09 17:01 [Bug tree-optimization/100004] New: Dead write not removed when indirection is introduced hiraditya at msn dot com
@ 2021-04-09 17:01 ` hiraditya at msn dot com
  2021-04-09 17:23 ` dancol at dancol dot org
  2021-04-12  8:02 ` rguenth at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: hiraditya at msn dot com @ 2021-04-09 17:01 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from AK <hiraditya at msn dot com> ---
godbolt link: https://gcc.godbolt.org/z/f7Y6G1svf

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

* [Bug tree-optimization/100004] Dead write not removed when indirection is introduced.
  2021-04-09 17:01 [Bug tree-optimization/100004] New: Dead write not removed when indirection is introduced hiraditya at msn dot com
  2021-04-09 17:01 ` [Bug tree-optimization/100004] " hiraditya at msn dot com
@ 2021-04-09 17:23 ` dancol at dancol dot org
  2021-04-12  8:02 ` rguenth at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: dancol at dancol dot org @ 2021-04-09 17:23 UTC (permalink / raw)
  To: gcc-bugs

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

Daniel Colascione <dancol at dancol dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dancol at dancol dot org

--- Comment #2 from Daniel Colascione <dancol at dancol dot org> ---
Let's talk about this. GCC might, surprisingly, actually be correct here:
pointers are allowed to be cast from one object type to another object type and
then back while retaining their validity; in principle, w1 and w2 might be
"fake" wrapper instances created by casts from a struct Foo --- it's legal to
form these fake pointers as long as no access occurs through them. If
assign_via_pointer had reinterpret_cast<Foo*>()-ed w1 and w2 to Foo* (yielding
f1 and f2 respectively) and then accessed f1->x and f2->x, I think we'd agree 
that f1->x and f2->x could alias. 

The difference between the code in this bug and the reinterpret_cast<> scenario
is that here we're deriving f1 and f2 *not* via reinterpet_cast, but via
regular member access --- &w1->foo and &w2->foo. Should the use of a member
access instead of a cast propagate aliasing information? On one hand, it seems
logical to do so; on the other hand, the standard *does* say that access
through legally-derived same-type pointers can alias, and we *really do* have
two legally-derived same-type pointers here.

So what's the correct interpretation of the standard?

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

* [Bug tree-optimization/100004] Dead write not removed when indirection is introduced.
  2021-04-09 17:01 [Bug tree-optimization/100004] New: Dead write not removed when indirection is introduced hiraditya at msn dot com
  2021-04-09 17:01 ` [Bug tree-optimization/100004] " hiraditya at msn dot com
  2021-04-09 17:23 ` dancol at dancol dot org
@ 2021-04-12  8:02 ` rguenth at gcc dot gnu.org
  2 siblings, 0 replies; 4+ messages in thread
From: rguenth at gcc dot gnu.org @ 2021-04-12  8:02 UTC (permalink / raw)
  To: gcc-bugs

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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |rguenth at gcc dot gnu.org
            Version|unknown                     |11.0
           Keywords|                            |missed-optimization
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |WONTFIX

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
void assign_via_pointer(Wrap1* w1, Wrap2* w2)
{
    Foo* f1 = &w1->foo;
    Foo* f2 = &w2->foo;
    f1->x = 5;
    f1->x = f2->x;

to GCC &wN->foo is just address arithmetic - GCC does not assume that at
w1 or w2 dynamic types of type Wrap1 or Wrap2 reside and thus it cannot
disambiguate f1->x and f2->x here because the actual accesses only involve
the type Foo.

In the assign_direct case the access paths contain Wrap1 and Wrap2 and thus
we _do_ assume dynamic types Wrap1 and Wrap2 are in effect and thus we can
disambiguate.

This is how GIMPLEs memory model works, there's no bug here.  Maybe the
C++ language makes more strict guarantees (but I think it would run
against standard coding practices).

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

end of thread, other threads:[~2021-04-12  8:02 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-09 17:01 [Bug tree-optimization/100004] New: Dead write not removed when indirection is introduced hiraditya at msn dot com
2021-04-09 17:01 ` [Bug tree-optimization/100004] " hiraditya at msn dot com
2021-04-09 17:23 ` dancol at dancol dot org
2021-04-12  8:02 ` rguenth 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).