From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5831 invoked by alias); 17 Jan 2015 13:04:16 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 5790 invoked by uid 48); 17 Jan 2015 13:04:09 -0000 From: "glisse at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug tree-optimization/64601] Missed PRE on std::vector move assignment Date: Sat, 17 Jan 2015 13:04:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: tree-optimization X-Bugzilla-Version: 5.0 X-Bugzilla-Keywords: missed-optimization X-Bugzilla-Severity: normal X-Bugzilla-Who: glisse at gcc dot gnu.org X-Bugzilla-Status: RESOLVED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_status resolution Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2015-01/txt/msg01644.txt.bz2 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64601 Marc Glisse changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #9 from Marc Glisse --- (In reply to Marc Glisse from comment #8) > The transformation is triggered by dereferences, and compares the types of > objects, not pointers, so it isn't obvious that the issues you were > describing apply to it. It looks like they still do apply. I was just lucky that the folding was done in an order where nothing bad happened in the tests. Your example int *p = &((struct A *)&b)->i; *p = 0; becomes *(int*)&b=0, which is fine. But in a different order, what I wanted could give: (*(struct A *)&b).i=0 (access b as an A) which would be wrong for TBAA. Although I don't see the point of writing that kind of code instead of: int *p = (int*)((char*)&b + offsetof(A, i)); So basically, a struct A * as an argument of a function doesn't carry any more information than a void* :-( It is only if we can see an actual VAR_DECL or similar that we may be able to reconstruct the access, but then we don't often need to... It is strange that [basic.lval] (or 6.5 Expressions in C99) is so lenient. [class.mem] is a little bit more restrictive but still not much. There is a little bit of divergence on function f below: void f(struct A *a){ *&a->i=0; } void g(struct A *a){ int*p=&a->i;*p=0; } void h(struct A *a){ a->i=0; } gcc, intel and oracle handle f like h, while clang is more conservative and handles it like g (I actually tested on a function taking 2 std::pair by reference if a.first and b.second could alias). Ok, I am starting to understand vaguely what C/C++ are saying about type aliasing. I am horrified (this is a huge abstraction penalty), but at least I am less confused. I'll close this PR as INVALID (the trick about the same clobbering value is already in several other PRs, no need to keep this one as well) (if you want to remove some current unsafe transformations, it would probably be less confusing to open a different PR). I wonder how feasible it would be to define a dialect where any non-zero struct A* really points to a struct A... (we already have void* and char* for "untyped" pointers)