[Bug tree-optimization/61502] == comparison on "one-past" pointer gives wrong result

2018-05-08 Thread Peter.Sewell at cl dot cam.ac.uk
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

2016-08-16 Thread Peter.Sewell at cl dot cam.ac.uk
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

2016-08-15 Thread Peter.Sewell at cl dot cam.ac.uk
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

2016-08-15 Thread Peter.Sewell at cl dot cam.ac.uk
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

2014-06-13 Thread Peter.Sewell at cl dot cam.ac.uk
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. [...]".