Re: riscv64 dep. computation

2019-02-15 Thread Paulo Matos



On 15/02/2019 19:15, Jim Wilson wrote:
> On Thu, Feb 14, 2019 at 11:33 PM Paulo Matos  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


Re: riscv64 dep. computation

2019-02-15 Thread Jim Wilson
On Thu, Feb 14, 2019 at 11:33 PM Paulo Matos  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


Re: riscv64 dep. computation

2019-02-14 Thread Paulo Matos



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


Re: riscv64 dep. computation

2019-02-14 Thread Jim Wilson

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


riscv64 dep. computation

2019-02-14 Thread Paulo Matos
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