[Bug tree-optimization/61502] == comparison on "one-past" pointer gives wrong result
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61502 --- Comment #29 from Peter Sewell --- On 8 May 2018 at 08:22, rguenth at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61502 > > --- Comment #25 from Richard Biener --- > (In reply to Harald van Dijk from comment #22) > > (In reply to Andrew Pinski from comment #21) > > > Invalid as mentioned a few times already but never actually closed > until now. > > > > I posted a strictly conforming program that with GCC does not behave as > > required by the standard. The issue is valid, even if the original test > case > > is not. > > If you are talking about the one in comment#12 then this is the same issue > as present in a few other "similar" bugs where GCC propagates conditional > equivalences (for example the linked PR65752): > > v = &y; > p = v; > x = 2, y = 1; > if (p == &x + 1) > *p = 2; > > is turned into > > v = &y; > p = v; > x = 2, y = 1; > if (p == &x + 1) > *(&x + 1) = 2; > > by GCC and the store is then no longer possibly aliasing y. > > Conditional equivalences are a difficult thing to exploit for optimization > and there's some work in progress for the standard regarding to pointer > provenance which IIRC says that the comparison result of &y == &x + 1 > returns an unspecified value. Not sure if that helps us FYI, the current state of that work in progress is here: https://cdn.rawgit.com/C-memory-object-model-study-group/c-mom-sg/master/notes/cmom-0001-2018-05-04-sewell-clarifying-provenance-v4.html and comments from a GCC perspective would be much appreciated. It's been informed by useful discussion at the recent WG14 and EuroLLVM meetings. Our current proposal indeed makes that comparison an unspecified value - more generally, allowing any pointer equality comparison to either take provenance into account or not - exactly because we see GCC do so in some cases. If that isn't important for optimisation, returning to a fully concrete semantics for == would be a simpler choice. but then the > only way our for GCC for this particular issue would be to never actually > propagate conditional equivalences. > (Conceivably it could be allowed where the compiler can see that the two have the same provenance. We've no idea how useful that would be.) > > Sth that might be worth investigating, but within the current structure of > the optimization passes that apply this transform it's impossible to decide > whether a value resulted from conditional equivalences or not... I'm also > not sure to what extent simplification results using a conditional > predicate > like p == &x + 1 are affected as well. > > IMHO it's a defect in the language if > > p = &y; > if (p == &x + 1) > *p = 2; > > is valid but > > p = &y; > if (p == &x + 1) > *(&x + 1) = 2; > > is invoking undefined behavior. Or at least a very uncomfortable situation > for a compiler writer. IMHO the pointer provenance work making the > comparison having unspecified result doesn't really help since that doesn't > make it invoke undefined behavior. > It's not clear how this could be resolved. For the source-language semantics, if one wants to be able to do provenance-based alias analysis, we don't see any clean way in which the second could be allowed. And forbidding the first would need one to make == of pointers with different provenances UB, which we imagine would break a lot of C code. That said, in general the intermediate-language semantics might be quite different from the C-source-language semantics (as we discover in discussion with Nuno Lopes and his colleagues about their LLVM semantics), so long as it implements the source semantics. Peter, Kayvan, Victor > > -- > You are receiving this mail because: > You reported the bug. >
[Bug target/76774] atomics on PPC: inconsistent widths for an _Atomic(_Bool) and for atomic_compare_exchange_strong on it
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=76774 --- Comment #4 from Peter Sewell --- (In reply to Andrew Pinski from comment #3) > What code were you expecting anyways? I hadn't noticed how recent the other-size LL/SC were. But then I would have expected a 4-byte representation for _Atomic(_Bool) on the older machines, to minimise the amount of code between the lwarx and stwcx; would that have some other disadvantage? I don't think the code you've got is functionally wrong on normal h/w. We noticed this running in a semantics-based emulator that's very picky about reading from uninitialised memory, but on normal h/w the extra memory will AFAICS always be mapped and be within the same reservation granule.
[Bug c/76774] atomics on PPC: inconsistent widths for an _Atomic(_Bool) and for atomic_compare_exchange_strong on it
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=76774 --- Comment #1 from Peter Sewell --- Created attachment 39439 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39439&action=edit example code
[Bug c/76774] New: atomics on PPC: inconsistent widths for an _Atomic(_Bool) and for atomic_compare_exchange_strong on it
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=76774 Bug ID: 76774 Summary: atomics on PPC: inconsistent widths for an _Atomic(_Bool) and for atomic_compare_exchange_strong on it Product: gcc Version: 4.9.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: Peter.Sewell at cl dot cam.ac.uk Target Milestone: --- On a POWER 7 machine using GCC 4.9.1, something declared as an _Atomic(_Bool) appears to generate a 1-byte object but using atomic_compare_exchange_strong on it generates 4-byte LL/SC (lwarx/stwcx) instructions. We observed this in two ways: a global static _Atomic(_Bool) locked; produces a 1-byte ELF object, and in a packed struct struct __attribute__((__packed__)) s { _Atomic(_Bool) s_locked; char c; }; the c field seems to be 1 byte after the s_locked field.
[Bug c/61502] New: == comparison on "one-past" pointer gives wrong result
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61502 Bug ID: 61502 Summary: == comparison on "one-past" pointer gives wrong result Product: gcc Version: 4.8.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: Peter.Sewell at cl dot cam.ac.uk Created attachment 32934 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=32934&action=edit C code as pasted into bug report The following code can produce a pointer to one-past the x object. When it does, according to the C11 standard text, the result of the pointer comparison should be true, but gcc gives false. #include int y = 2, x=1; int main() { int *p; p = &x +1 ; printf("&x=%p &y=%p p=%p\n",(void*)&x, (void*)&y, (void*)p); _Bool b1 = (p==&y); printf("(p==&y) = %s\n", b1?"true":"false"); return 0; } gcc-4.8 -std=c11 -pedantic -Wall -Wextra -O2 -o a.out pointer_representation_1e.c && ./a.out &x=0x601020 &y=0x601024 p=0x601024 (p==&y) = false gcc-4.8 --version gcc-4.8 (Ubuntu 4.8.1-2ubuntu1~12.04) 4.8.1 The pointer addition is licensed by 6.5.6 "Additive operators", where: 6.5.6p7 says "For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.", and 6.5.6p8 says "[...] Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object [...]". The pointer comparison is licensed by 6.5.9 "Equality operators", where: 6.5.9p7 says "For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.", 6.5.9p6 says "Two pointers compare equal if and only if [...] or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.109)", and Footnote 109 says "Two objects may be adjacent in memory because they are adjacent elements of a larger array or adjacent members of a structure with no padding between them, or because the implementation chose to place them so, even though they are unrelated. [...]".