public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* riscv64 dep. computation
@ 2019-02-14 11:13 Paulo Matos
  2019-02-14 18:56 ` Jim Wilson
  0 siblings, 1 reply; 5+ messages in thread
From: Paulo Matos @ 2019-02-14 11:13 UTC (permalink / raw)
  To: gcc

Hello,

While working on a private port of riscv, I noticed that upstream shows
the same behaviour.

For the code:
#define TYPE unsigned short

struct foo_t
{
  TYPE a;
  TYPE b;
  TYPE c;
};

void
func (struct foo_t *x, struct foo_t *y)
{
  y->a = x->a;
  y->b = x->b;
  y->c = x->c;
}

If I compile this with -O2, sched1 groups all loads and all stores
together. That's perfect. However, if I change TYPE to unsigned char and
recompile, the stores and loads are interleaved.

Further investigation shows that for unsigned char there are extra
dependencies that block the scheduler from grouping stores and loads.

For example, there's a dependency between:
(insn 8 3 9 2 (set (mem:QI (reg/v/f:DI 76 [ yD.1533 ]) [0
y_6(D)->aD.1529+0 S1 A8])
        (subreg/s/v:QI (reg:DI 72 [ _1 ]) 0)) "test.c":13:8 142
{*movqi_internal}
     (expr_list:REG_DEAD (reg:DI 72 [ _1 ])
        (nil)))

and
(insn 11 10 12 2 (set (reg:DI 74 [ _3 ])
        (zero_extend:DI (mem:QI (plus:DI (reg/v/f:DI 75 [ xD.1532 ])
                    (const_int 2 [0x2])) [0 x_5(D)->cD.1531+0 S1 A8])))
"test.c":15:11 89 {zero_extendqidi2}
     (expr_list:REG_DEAD (reg/v/f:DI 75 [ xD.1532 ])
        (nil)))

which didn't exist in the `unsigned short' case.

I can't find where this dependency is coming from but also can't justify
it so it seems like a bug to me. Is there a reason for this to happen
that I might not be aware of?

While I am at it, debugging compute_block_dependencies in sched-rgn.c is
a massive pain. This calls sched_analyze which receives a struct
deps_desc that tracks the dependencies in the insn list. Is there a way
to pretty print this structure in gdb?

Kind regards,

-- 
Paulo Matos

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

* Re: riscv64 dep. computation
  2019-02-14 11:13 riscv64 dep. computation Paulo Matos
@ 2019-02-14 18:56 ` Jim Wilson
  2019-02-15  7:33   ` Paulo Matos
  0 siblings, 1 reply; 5+ messages in thread
From: Jim Wilson @ 2019-02-14 18:56 UTC (permalink / raw)
  To: Paulo Matos, gcc

On 2/14/19 3:13 AM, Paulo Matos wrote:
> If I compile this with -O2, sched1 groups all loads and all stores
> together. That's perfect. However, if I change TYPE to unsigned char and
> recompile, the stores and loads are interleaved.
> 
> Further investigation shows that for unsigned char there are extra
> dependencies that block the scheduler from grouping stores and loads.

The ISO C standard says that anything can be casted to char *, and char 
* can be casted to anything.  Hence, a char * pointer aliases everything.

If you look at the alias set info in the MEMs, you can see that the char 
* references are in alias set 0, which means that they alias everything. 
  The short * references are in alias set 2 which means they only alias 
other stuff in alias set 2.  The difference here is that short * does 
not alias the structure pointers, but char * does.  I haven't tried 
debugging your example, but this is presumably where the difference 
comes from.

Because x and y are pointer parameters, the compiler must assume that 
they might alias.  And because char * aliases everything, the char 
references alias them too.  If you change x and y to global variables, 
then they no longer alias each other, and the compiler will schedule all 
of the loads first, even for char.

Jim

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

* Re: riscv64 dep. computation
  2019-02-14 18:56 ` Jim Wilson
@ 2019-02-15  7:33   ` Paulo Matos
  2019-02-15 18:15     ` Jim Wilson
  0 siblings, 1 reply; 5+ messages in thread
From: Paulo Matos @ 2019-02-15  7:33 UTC (permalink / raw)
  To: Jim Wilson, gcc



On 14/02/2019 19:56, Jim Wilson wrote:
> On 2/14/19 3:13 AM, Paulo Matos wrote:
>> If I compile this with -O2, sched1 groups all loads and all stores
>> together. That's perfect. However, if I change TYPE to unsigned char and
>> recompile, the stores and loads are interleaved.
>>
>> Further investigation shows that for unsigned char there are extra
>> dependencies that block the scheduler from grouping stores and loads.
> 
> The ISO C standard says that anything can be casted to char *, and char
> * can be casted to anything.  Hence, a char * pointer aliases everything.
> 
> If you look at the alias set info in the MEMs, you can see that the char
> * references are in alias set 0, which means that they alias everything.
>  The short * references are in alias set 2 which means they only alias
> other stuff in alias set 2.  The difference here is that short * does
> not alias the structure pointers, but char * does.  I haven't tried
> debugging your example, but this is presumably where the difference
> comes from.
>

OK, that seems to make sense. Indeed if I use restrict on the argument
pointers, the compiler will sort itself out and group the loads and stores.

> Because x and y are pointer parameters, the compiler must assume that
> they might alias.  And because char * aliases everything, the char
> references alias them too.  If you change x and y to global variables,
> then they no longer alias each other, and the compiler will schedule all
> of the loads first, even for char.
> 

Are global variables not supposed to alias each other?
If I indeed do that, gcc still won't group loads and stores:
https://cx.rv8.io/g/rFjGLa

-- 
Paulo Matos

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

* Re: riscv64 dep. computation
  2019-02-15  7:33   ` Paulo Matos
@ 2019-02-15 18:15     ` Jim Wilson
  2019-02-15 19:27       ` Paulo Matos
  0 siblings, 1 reply; 5+ messages in thread
From: Jim Wilson @ 2019-02-15 18:15 UTC (permalink / raw)
  To: Paulo Matos; +Cc: gcc

On Thu, Feb 14, 2019 at 11:33 PM Paulo Matos <pmatos@linki.tools> wrote:
> Are global variables not supposed to alias each other?
> If I indeed do that, gcc still won't group loads and stores:
> https://cx.rv8.io/g/rFjGLa

I meant something like
struct foo_t x, y;
and now they clearly don't alias.  As global pointers they may still alias.

Jim

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

* Re: riscv64 dep. computation
  2019-02-15 18:15     ` Jim Wilson
@ 2019-02-15 19:27       ` Paulo Matos
  0 siblings, 0 replies; 5+ messages in thread
From: Paulo Matos @ 2019-02-15 19:27 UTC (permalink / raw)
  To: Jim Wilson; +Cc: gcc



On 15/02/2019 19:15, Jim Wilson wrote:
> On Thu, Feb 14, 2019 at 11:33 PM Paulo Matos <pmatos@linki.tools> wrote:
>> Are global variables not supposed to alias each other?
>> If I indeed do that, gcc still won't group loads and stores:
>> https://cx.rv8.io/g/rFjGLa
> 
> I meant something like
> struct foo_t x, y;
> and now they clearly don't alias.  As global pointers they may still alias.
> 

Ah ok, of course. Like that it makes sense they don't alias.

Thanks,

-- 
Paulo Matos

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

end of thread, other threads:[~2019-02-15 19:27 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-14 11:13 riscv64 dep. computation Paulo Matos
2019-02-14 18:56 ` Jim Wilson
2019-02-15  7:33   ` Paulo Matos
2019-02-15 18:15     ` Jim Wilson
2019-02-15 19:27       ` Paulo Matos

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).