Re: riscv64 dep. computation
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
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
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
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
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