movmem pattern and missed alignment

2018-10-08 Thread Paul Koning
I have a movmem pattern in my target that pays attention to the alignment 
argument.

GCC isn't passing in the expected alignment part of the time.  I have this test 
case:

extern int *i, *j;
extern int iv[40], jv[40];

void f1(void)
{
__builtin_memcpy (i, j, 32);
}

void f2(void)
{
__builtin_memcpy (iv, jv, 32);
}

When the movmem pattern is called for f1, alignment is 1.  In f2, it is 2 (int 
is 2 bytes in pdp11) as expected.

The compiler clearly knows that int* points to aligned data, since it generates 
instructions that assume alignment (this is a strict-alignment target) when I 
dereference the pointer.  But somehow it gets it wrong for block move.

I also see this for the individual move operations that are generated for very 
short memcpy operations; if the count is 4, I get four move byte operations for 
f1, but two move word operations for f2.  

This seems like a bug.  Am I missing something?

paul



Re: movmem pattern and missed alignment

2018-10-08 Thread Richard Biener
On Mon, Oct 8, 2018 at 3:57 PM Paul Koning  wrote:
>
> I have a movmem pattern in my target that pays attention to the alignment 
> argument.
>
> GCC isn't passing in the expected alignment part of the time.  I have this 
> test case:
>
> extern int *i, *j;
> extern int iv[40], jv[40];
>
> void f1(void)
> {
> __builtin_memcpy (i, j, 32);
> }
>
> void f2(void)
> {
> __builtin_memcpy (iv, jv, 32);
> }
>
> When the movmem pattern is called for f1, alignment is 1.  In f2, it is 2 
> (int is 2 bytes in pdp11) as expected.
>
> The compiler clearly knows that int* points to aligned data, since it 
> generates instructions that assume alignment (this is a strict-alignment 
> target) when I dereference the pointer.  But somehow it gets it wrong for 
> block move.
>
> I also see this for the individual move operations that are generated for 
> very short memcpy operations; if the count is 4, I get four move byte 
> operations for f1, but two move word operations for f2.
>
> This seems like a bug.  Am I missing something?

Yes, memcpy doesn't require anything bigger than byte alignment and
GCC infers alignemnt
only from actual memory references or from declarations (like iv /
jv).  For i and j there
are no dereferences and thus you get alignment of 1.

Richard.

>
> paul
>


Re: movmem pattern and missed alignment

2018-10-08 Thread Paul Koning



> On Oct 8, 2018, at 11:09 AM, Richard Biener  
> wrote:
> 
> On Mon, Oct 8, 2018 at 3:57 PM Paul Koning  wrote:
>> 
>> I have a movmem pattern in my target that pays attention to the alignment 
>> argument.
>> 
>> GCC isn't passing in the expected alignment part of the time.  I have this 
>> test case:
>> 
>> extern int *i, *j;
>> extern int iv[40], jv[40];
>> 
>> void f1(void)
>> {
>>__builtin_memcpy (i, j, 32);
>> }
>> 
>> void f2(void)
>> {
>>__builtin_memcpy (iv, jv, 32);
>> }
>> 
>> When the movmem pattern is called for f1, alignment is 1.  In f2, it is 2 
>> (int is 2 bytes in pdp11) as expected.
>> 
>> The compiler clearly knows that int* points to aligned data, since it 
>> generates instructions that assume alignment (this is a strict-alignment 
>> target) when I dereference the pointer.  But somehow it gets it wrong for 
>> block move.
>> 
>> I also see this for the individual move operations that are generated for 
>> very short memcpy operations; if the count is 4, I get four move byte 
>> operations for f1, but two move word operations for f2.
>> 
>> This seems like a bug.  Am I missing something?
> 
> Yes, memcpy doesn't require anything bigger than byte alignment and
> GCC infers alignemnt
> only from actual memory references or from declarations (like iv /
> jv).  For i and j there
> are no dereferences and thus you get alignment of 1.
> 
> Richard.

Ok, but why is that not a bug?  The whole point of passing alignment to the 
movmem pattern is to let it generate code that takes advantage of the 
alignment.  So we get a missed optimization.

paul



Re: movmem pattern and missed alignment

2018-10-08 Thread Michael Matz
Hi,

On Mon, 8 Oct 2018, Paul Koning wrote:

> >> extern int *i, *j;
> >> extern int iv[40], jv[40];
> >> 
> >> void f1(void)
> >> {
> >>__builtin_memcpy (i, j, 32);
> >> }
> >> 
> >> void f2(void)
> >> {
> >>__builtin_memcpy (iv, jv, 32);
> >> }
> > 
> > Yes, memcpy doesn't require anything bigger than byte alignment and
> > GCC infers alignemnt
> > only from actual memory references or from declarations (like iv /
> > jv).  For i and j there
> > are no dereferences and thus you get alignment of 1.
> > 
> > Richard.
> 
> Ok, but why is that not a bug?  The whole point of passing alignment to 
> the movmem pattern is to let it generate code that takes advantage of 
> the alignment.  So we get a missed optimization.

Only if you somewhere visibly add accesses to *i and *j.  Without them you 
only have the "accesses" via memcpy, and as Richi says, those don't imply 
any alignment requirements.  The i and j pointers might validly be char* 
pointers in disguise and hence be in fact only 1-aligned.  I.e. there's 
nothing in your small example program from which GCC can infer that those 
two global pointers are in fact 2-aligned.


Ciao,
Michael.


Re: movmem pattern and missed alignment

2018-10-08 Thread Andrew Haley
On 10/08/2018 06:20 PM, Michael Matz wrote:
> Only if you somewhere visibly add accesses to *i and *j.  Without them you 
> only have the "accesses" via memcpy, and as Richi says, those don't imply 
> any alignment requirements.  The i and j pointers might validly be char* 
> pointers in disguise and hence be in fact only 1-aligned.  I.e. there's 
> nothing in your small example program from which GCC can infer that those 
> two global pointers are in fact 2-aligned.

So all you'd actually have to say is

void f1(void)
{
*i; *j;
__builtin_memcpy (i, j, 32);
}

-- 
Andrew Haley
Java Platform Lead Engineer
Red Hat UK Ltd. 
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671


Re: movmem pattern and missed alignment

2018-10-08 Thread Alexander Monakov
On Mon, 8 Oct 2018, Michael Matz wrote:
> > Ok, but why is that not a bug?  The whole point of passing alignment to 
> > the movmem pattern is to let it generate code that takes advantage of 
> > the alignment.  So we get a missed optimization.
> 
> Only if you somewhere visibly add accesses to *i and *j.  Without them you 
> only have the "accesses" via memcpy, and as Richi says, those don't imply 
> any alignment requirements.  The i and j pointers might validly be char* 
> pointers in disguise and hence be in fact only 1-aligned.  I.e. there's 
> nothing in your small example program from which GCC can infer that those 
> two global pointers are in fact 2-aligned.

Well, it's not that simple. C11 6.3.2.3 p7 makes it undefined to form an
'int *' value that is not suitably aligned:

  A pointer to an object type may be converted to a pointer to a different
  object type. If the resulting pointer is not correctly aligned for the
  referenced type, the behavior is undefined.

So in addition to what you said, we should probably say that GCC decides
not to exploit this UB in order to allow code to round-trip pointer values
via arbitrary pointer types?


To put Michael's explanation in different words:

This is not obviously a bug, because static pointer type does not imply the
dynamic pointed-to type. The caller of 'f1' could look like

void call_f1(void)
{
  short ibuf[20] = {0}, jbuf[20] = {0};
  i = (void *) ibuf;
  j = (void *) jbuf;
  f1();
}

and it's valid to memcpy from jbuf to ibuf, memcpy does not "see" the
static pointer type, and works as if by dereferencing 'char *' pointers.
(although as mentioned above it's more subtly invalid when assigning to
i and j).

If 'f1' dereferences 'i', GCC may deduce that dynamic type of '*i' is 'int' and
therefore 'i' must be suitably aligned. But in absence of dereferences GCC
does not make assumptions about dynamic type and alignment.

Alexander


Re: movmem pattern and missed alignment

2018-10-08 Thread Michael Matz
Hi,

On Mon, 8 Oct 2018, Alexander Monakov wrote:

> > Only if you somewhere visibly add accesses to *i and *j.  Without them 
> > you only have the "accesses" via memcpy, and as Richi says, those 
> > don't imply any alignment requirements.  The i and j pointers might 
> > validly be char* pointers in disguise and hence be in fact only 
> > 1-aligned.  I.e. there's nothing in your small example program from 
> > which GCC can infer that those two global pointers are in fact 
> > 2-aligned.
> 
> Well, it's not that simple. C11 6.3.2.3 p7 makes it undefined to form an 
> 'int *' value that is not suitably aligned:
> 
> So in addition to what you said, we should probably say that GCC decides
> not to exploit this UB in order to allow code to round-trip pointer values
> via arbitrary pointer types?

That's correct, I was explaining from the middle-end perspective.  There 
we are consciously more lenient as we have to support the real world and 
other languages than C.  This is one of the cases.


Ciao,
Michael.


Re: movmem pattern and missed alignment

2018-10-08 Thread Paul Koning



> On Oct 8, 2018, at 1:29 PM, Andrew Haley  wrote:
> 
> On 10/08/2018 06:20 PM, Michael Matz wrote:
>> Only if you somewhere visibly add accesses to *i and *j.  Without them you 
>> only have the "accesses" via memcpy, and as Richi says, those don't imply 
>> any alignment requirements.  The i and j pointers might validly be char* 
>> pointers in disguise and hence be in fact only 1-aligned.  I.e. there's 
>> nothing in your small example program from which GCC can infer that those 
>> two global pointers are in fact 2-aligned.
> 
> So all you'd actually have to say is
> 
> void f1(void)
> {
>*i; *j;
>__builtin_memcpy (i, j, 32);
> }

No, that doesn't help.  Not even if I make it:

void f1(void)
{
k = *i + *j;
__builtin_memcpy (i, j, 4);
}

The first line does word aligned references to *i and *j, but the memcpy 
stubbornly remains a byte move.

paul



Re: movmem pattern and missed alignment

2018-10-08 Thread Michael Matz
Hi,

On Mon, 8 Oct 2018, Paul Koning wrote:

> > So all you'd actually have to say is
> > 
> > void f1(void)
> > {
> >*i; *j;
> >__builtin_memcpy (i, j, 32);
> > }
> 
> No, that doesn't help.  Not even if I make it:
> 
> void f1(void)
> {
> k = *i + *j;
> __builtin_memcpy (i, j, 4);
> }
> 
> The first line does word aligned references to *i and *j, but the memcpy 
> stubbornly remains a byte move.

k is a global, so the loads from i/j can't be optimized away?  If so, now 
you have a missed optimization bug ;-)  Might be non-trivial to fix for 
general situations (basically the natural alignment can only be inferred 
in regions that are dominated by such accesses, but not e.g. for:
   if (cond()) k = *i+*j;
   memcpy(i,j,4);
as cond() might be always false).


Ciao,
Michael.


Re: Pretty print of C++11 scoped enums - request help towards a proper fix

2018-10-08 Thread will wray
Patch submitted:

https://gcc.gnu.org/ml/gcc-patches/2018-10/msg00452.html
[C++ PATCH] Fix pretty-print of enumerator ids (PR c++/87364)

My first GCC patch attempt, so more eyes would be good.

Cheers, Will

On Tue, Sep 25, 2018 at 4:25 PM will wray  wrote:

> BTW The bug is still UNCONFIRMED
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87364
>
> It is easy to CONFIRM:
>
> Follow this Compiler Explorer link https://godbolt.org/z/P4ejiy
> or paste this code into a file and compile with g++:
>
> template  struct wauto;
> enum e { a };
> wauto v;// error
>
>
> Note that GCC reports  error: ... 'wauto v'
>  => It should report   error: ... 'wauto v'
>
> This is a bug; the intent of the code is print the enumerator id
> (clang prints the enumerator id and so do recent MSVC previews).
> There is also test code linked to the bug covering more cases.
>
> I'd appreciate if someone would confirm the bug.
>
> Thanks, Will
>
> On Mon, Sep 24, 2018 at 5:23 PM will wray  wrote:
>
>> Thanks Nathan,
>>
>>
>> In fact, after testing with enums nested in namespaces or structs,
>>
>> or function local, I realised nested specifiers should be printed
>>
>> for both scoped and unscoped enums, but for unscoped enums one
>>
>> level of nested specifier (the enum type) needs to be stripped.
>>
>> So I inverted the IS_SCOPED test and used get_containing_scope:
>>
>>
>> if (value != NULL_TREE)
>> {
>>
>> if (!ENUM_IS_SCOPED (type))
>>
>> type = get_containing_scope (type);
>>
>> pp_cxx_nested_name_specifier (pp, type);
>>
>> pp->id_expression (TREE_PURPOSE (value));
>>
>> }
>>
>>
>> I submitted this fix as a patch to the bug report, with tests.
>>
>> With this fix GCC now has similar output to both Clang and MSVC
>> for enumerated values. For non-enumerated values GCC continues
>> to print a C-style cast while Clang & MSVC print plain digits.
>> Yay! GCC is winning! (gives type info for non-enumerated values).
>>
>> A downside of nested specifiers is that output gets verbose.
>>
>> Richard Smith suggests to use less verbose output for known types
>> compared to auto deduced types. Discussion starts here
>> http://lists.llvm.org/pipermail/cfe-dev/2018-September/059229.html
>>
>> For enum args, I guess that this would mean distinguishing whether
>> the corresponding template parameter was auto or a given enum type
>> and only printing a simple id with no nested specs for given type.
>> I don't know yet if that info is available at the leaf level here.
>>
>> Similarly, type info should be added to deduced Integral values.
>> I may start to investigate how to do this in GCC pretty print.
>> I submitted the related request to MSVC devs:
>>
>> https://developercommunity.visualstudio.com/content/problem/339663/improve-pretty-print-of-integral-non-type-template.html
>>
>> > given the code base ...
>>
>> GCC pretty-print code was committed by GDR mid 2002,
>> K&R style C, updated to C90 'prototype' in mid 2003,
>> untouched since then, not for C++11 or C++17 enum updates.
>>
>> I found this corner of the code base fairly easy to hack,
>> thanks perhaps to GDRs attempts to follow the grammar.
>>
>>
>> On Mon, Sep 24, 2018 at 3:53 PM Nathan Sidwell  wrote:
>>
>>> On 9/19/18 7:41 AM, will wray wrote:
>>> > Re: "Pretty print of enumerator never prints the id,
>>> >   always falls back to C-style cast output"
>>> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87364
>>> >
>>>
>>> > I have a fix which duplicates the code in pp_c_enumeration_constant
>>> > to pp_cxx_enumeration_constant in cxx-pretty print, with modification
>>> >
>>> >if (value != NULL_TREE)
>>> >{
>>> >  if (ENUM_IS_SCOPED (type))
>>> >pp_cxx_nested_name_specifier (pp, type);
>>> >  pp->id_expression (TREE_PURPOSE (value));
>>> >}
>>> >
>>> > This works in my testing so far, but
>>> >   - It duplicates code from c to cxx (not DRY 'Don't Repeat Yourself)
>>> >   - I didn't find a single function to print full nested, scoped id
>>> > so had to check if ENUM_IS_SCOPED to output nested specifiers.
>>>
>>> This seems a fine approach, given the code base.
>>>
>>> nathan
>>>
>>> --
>>> Nathan Sidwell
>>>
>>


Re: Cannot compile using cc1.

2018-10-08 Thread Jim Wilson

On 10/06/2018 06:07 AM, Tejas Joshi wrote:

I have gcc source code, stage1-build and test directories as siblings
and I've been trying to compile test.c in test/ using:

../stage1-build/gcc/cc1 test.c


That isn't expected to work.  You need to use the compiler driver, which 
is called xgcc in the build dir, and pass an option to let it know where 
the cc1 binary is.  So this should instead be


../stage1-build/gcc/xgcc -B../stage1-build/gcc/ test.c

The trailing slash on the -B option path is important.  If that doesn't 
work, then you may have configured your gcc tree wrong.  Some operating 
systems require specific configure options to be used to get a working 
compiler.  You can see the configure options used by the default 
compiler by using "/usr/bin/gcc -v".  Debian/Ubuntu require 
--enable-multiarch for instance, and the compiler build may not succeed 
if that configure option is missing.


If you want to run cc1 directly, you may need to pass in extra default 
options that the compiler driver normally passes to it.  You can see 
these options by passing the -v option to the gcc driver while compiling 
a file.  E.g. running "../stage1-build/gcc/xgcc -B../stage1-build/gcc/ 
-v test.c" and looking at the cc1 line will show you the options you 
need to pass to cc1 to make it work.


Jim


Re: movmem pattern and missed alignment

2018-10-08 Thread Eric Botcazou
> That's correct, I was explaining from the middle-end perspective.  There
> we are consciously more lenient as we have to support the real world and
> other languages than C.  This is one of the cases.

This had worked as Paul expects until GCC 4.4 IIRC and this was perfectly OK 
for every language on strict-alignment platforms.  This was changed only 
because of SSE on x86.

-- 
Eric Botcazou


Re: movmem pattern and missed alignment

2018-10-08 Thread Paul Koning



> On Oct 8, 2018, at 5:43 PM, Eric Botcazou  wrote:
> 
>> That's correct, I was explaining from the middle-end perspective.  There
>> we are consciously more lenient as we have to support the real world and
>> other languages than C.  This is one of the cases.
> 
> This had worked as Paul expects until GCC 4.4 IIRC and this was perfectly OK 
> for every language on strict-alignment platforms.  This was changed only 
> because of SSE on x86.
> 
> -- 
> Eric Botcazou

So does that mean this should be a target-specific behavior, but it isn't at 
the moment?

paul



Re: Actions required

2018-10-08 Thread Dev Guy
On Sat, Sep 29, 2018 at 11:35 PM Notification
 wrote:
>
>


-- 
Kind Regards,
TH


Re: movmem pattern and missed alignment

2018-10-08 Thread Richard Biener
On October 8, 2018 11:43:00 PM GMT+02:00, Eric Botcazou  
wrote:
>> That's correct, I was explaining from the middle-end perspective. 
>There
>> we are consciously more lenient as we have to support the real world
>and
>> other languages than C.  This is one of the cases.
>
>This had worked as Paul expects until GCC 4.4 IIRC and this was
>perfectly OK 
>for every language on strict-alignment platforms.  This was changed
>only 
>because of SSE on x86.

And because we ended up ignoring all pointer casts. 

Richard. 



Re: movmem pattern and missed alignment

2018-10-08 Thread Alexander Monakov
On Tue, 9 Oct 2018, Richard Biener wrote:
> >This had worked as Paul expects until GCC 4.4 IIRC and this was perfectly OK
> >for every language on strict-alignment platforms.  This was changed only
> >because of SSE on x86.
> 
> And because we ended up ignoring all pointer casts. 

It's not quite obvious what SSE has to do with this - any hint please?

(according to my quick check this changed between gcc-4.5 and gcc-4.6)

Alexander


Re: movmem pattern and missed alignment

2018-10-08 Thread Eric Botcazou
> It's not quite obvious what SSE has to do with this - any hint please?

SSE introduced alignment constraints into the non-strict-alignment target x86 
so people didn't really want to play by the rules of strict-alignment targets.

> (according to my quick check this changed between gcc-4.5 and gcc-4.6)

Possibly indeed, I remembered GCC 4.5 as being the turning point.

-- 
Eric Botcazou


FW: PROPOSAL: Extend inline asm syntax with size spec

2018-10-08 Thread David Laight
Resend to gcc@gcc.gnu.org to avoid spam filter

> From: Michael Matz
> > Sent: 07 October 2018 16:53
> ...
> > I think the examples I saw from Boris were all indirect inlines:
> >
> >   static inline void foo() { asm("large-looking-but-small-asm"); }
> >   static void bar1() { ... foo() ... }
> >   static void bar2() { ... foo() ... }
> >   void goo (void) { bar1(); }  // bar1 should have been inlined
> >
> > So, while the immediate asm user was marked as always inline that in turn
> > caused users of it to become non-inlined.  I'm assuming the kernel guys
> > did proper measurements that they _really_ get some non-trivial speed
> > benefit by inlining bar1/bar2, but for some reasons (I didn't inquire)
> > didn't want to mark them all as inline as well.
> 
> Could you add a 'size' attribute to the 'always inlined' foo() above
> rather than trying to add one to the asm() statement itself.
> Then add a warning in the documentation that small size attributes
> might make the assembly fail due to limited branch offsets (etc).
> 
> Size '1' probably ought to be reserved for things that definitely
> fit in a delay slot.
> 
>   David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, 
UK
Registration No: 1397386 (Wales)