[llvm-dev] FW: Restrict qualifier on class members

Bandhav Veluri via llvm-dev llvm-dev at lists.llvm.org
Wed Jun 24 13:19:01 PDT 2020


Hi Jeroen,

Does that mean in this case, even though the frontend correctly interprets
__restrict on struct fields, the backend is only considering nolias
metadata on function arguments?

Thanks,
Bandhav

On Wed, Jun 24, 2020 at 1:32 AM Jeroen Dobbelaere <
Jeroen.Dobbelaere at synopsys.com> wrote:

> Hi Bandhav,
>
>
>
> I did notice in the previous example, that the vectorizer used the noalias
> information, but that it also got stripped during the vectorization.
>
> That is certainly one of the places where the noalias handling can be
> improved.
>
>
>
> It would be interesting to see if the necessary information gets through
> to the MIR level when vectorization is disabled.
>
> That should be visible with the 'ptr_provenance' field.
>
>
>
> Greetings,
>
>
>
> Jeroen Dobbelaere
>
>
>
>
>
> *From:* Bandhav Veluri <bandhav.veluri00 at gmail.com>
> *Sent:* Wednesday, June 24, 2020 10:12
> *To:* Jeroen Dobbelaere <dobbel at synopsys.com>
> *Cc:* Neil Henning <neil.henning at unity3d.com>; llvm-dev at lists.llvm.org;
> Kruse, Michael <michael.kruse at anl.gov>
> *Subject:* Re: FW: [llvm-dev] Restrict qualifier on class members
>
>
>
> Hi Jeroen,
>
>
>
> Sorry, I missed that. I tried the patch, and this program:
>
>
> #include <stdint.h>
>
> #define __remote __attribute__((address_space(1)))
>
> __remote int* A;
> __remote int* B;
>
> void vec_add(__remote int* __restrict a,
>              __remote int* __restrict b,
>              int n) {
>   #pragma unroll 4
>   for(int i=0; i<n; ++i) {
>     a[i] += b[i];
>   }
> }
>
> int main(int argc, char** argv) {
>   __remote int* __restrict a = A;
>   __remote int* __restrict b = B;
>
>   #pragma unroll 4
>   for(int i=0; i<4; ++i) {
>     a[i] += b[i];
>   }
>
>   return 0;
> }
>
>
>
> vec_add give following schedule:
>
>
>
> *** Final schedule for %bb.8 ***
> SU(0):   %33:gpr = LW %56:gpr, -8 :: (load 4 from %ir.scevgep8, !tbaa !14,
> !noalias !13, addrspace 1)
> SU(1):   %34:gpr = LW %55:gpr, -8 :: (load 4 from %ir.scevgep14, !tbaa
> !14, !noalias !13, addrspace 1)
> SU(4):   %36:gpr = LW %56:gpr, -4 :: (load 4 from %ir.scevgep10, !tbaa
> !14, !noalias !13, addrspace 1)
> SU(5):   %37:gpr = LW %55:gpr, -4 :: (load 4 from %ir.scevgep16, !tbaa
> !14, !noalias !13, addrspace 1)
> SU(8):   %39:gpr = LW %56:gpr, 0 :: (load 4 from %ir.lsr.iv6, !tbaa !14,
> !noalias !13, addrspace 1)
> SU(9):   %40:gpr = LW %55:gpr, 0 :: (load 4 from %ir.lsr.iv12, !tbaa !14,
> !noalias !13, addrspace 1)
> SU(12):   %42:gpr = LW %56:gpr, 4 :: (load 4 from %ir.scevgep9, !tbaa !14,
> !noalias !13, addrspace 1)
> SU(13):   %43:gpr = LW %55:gpr, 4 :: (load 4 from %ir.scevgep15, !tbaa
> !14, !noalias !13, addrspace 1)
> SU(2):   %35:gpr = nsw ADD %34:gpr, %33:gpr
> SU(3):   SW %35:gpr, %55:gpr, -8 :: (store 4 into %ir.scevgep14, !tbaa
> !14, !noalias !13, addrspace 1)
> SU(6):   %38:gpr = nsw ADD %37:gpr, %36:gpr
> SU(7):   SW %38:gpr, %55:gpr, -4 :: (store 4 into %ir.scevgep16, !tbaa
> !14, !noalias !13, addrspace 1)
> SU(10):   %41:gpr = nsw ADD %40:gpr, %39:gpr
> SU(11):   SW %41:gpr, %55:gpr, 0 :: (store 4 into %ir.lsr.iv12, !tbaa !14,
> !noalias !13, addrspace 1)
> SU(14):   %44:gpr = nsw ADD %43:gpr, %42:gpr
> SU(15):   SW %44:gpr, %55:gpr, 4 :: (store 4 into %ir.scevgep15, !tbaa
> !14, !noalias !13, addrspace 1)
> SU(16):   %57:gpr = nuw nsw ADDI %57:gpr, 4
> SU(17):   %56:gpr = ADDI %56:gpr, 16
> SU(18):   %55:gpr = ADDI %55:gpr, 16
>
>
>
> And main gives following schedule:
>
>
>
>  *** Final schedule for %bb.0 ***
>  SU(0):   %2:gpr = LUI target-flags(riscv-hi) @A
>  SU(2):   %4:gpr = LUI target-flags(riscv-hi) @B
>  SU(3):   %5:gpr = LW %4:gpr, target-flags(riscv-lo) @B ::
> (dereferenceable load 4 from @B, !tbaa !9, !noalias !22)
>  SU(1):   %3:gpr = LW %2:gpr, target-flags(riscv-lo) @A ::
> (dereferenceable load 4 from @A, !tbaa !9, !noalias !22)
>  SU(4):   %6:gpr = LW %5:gpr, 0 :: (load 4 from %ir.3, !tbaa !14, !noalias
> !22, addrspace 1)
>  SU(5):   %7:gpr = LW %3:gpr, 0 :: (load 4 from %ir.1, !tbaa !14, !noalias
> !22, addrspace 1)
>  SU(6):   %8:gpr = nsw ADD %7:gpr, %6:gpr
>  SU(7):   SW %8:gpr, %3:gpr, 0 :: (store 4 into %ir.1, !tbaa !14, !noalias
> !22, addrspace 1)
>  SU(8):   %9:gpr = LW %5:gpr, 4 :: (load 4 from %ir.arrayidx.1, !tbaa !14,
> !noalias !22, addrspace 1)
>  SU(9):   %10:gpr = LW %3:gpr, 4 :: (load 4 from %ir.arrayidx1.1, !tbaa
> !14, !noalias !22, addrspace 1)
>  SU(10):   %11:gpr = nsw ADD %10:gpr, %9:gpr
>  SU(11):   SW %11:gpr, %3:gpr, 4 :: (store 4 into %ir.arrayidx1.1, !tbaa
> !14, !noalias !22, addrspace 1)
>  SU(12):   %12:gpr = LW %5:gpr, 8 :: (load 4 from %ir.arrayidx.2, !tbaa
> !14, !noalias !22, addrspace 1)
>  SU(13):   %13:gpr = LW %3:gpr, 8 :: (load 4 from %ir.arrayidx1.2, !tbaa
> !14, !noalias !22, addrspace 1)
>  SU(14):   %14:gpr = nsw ADD %13:gpr, %12:gpr
>  SU(15):   SW %14:gpr, %3:gpr, 8 :: (store 4 into %ir.arrayidx1.2, !tbaa
> !14, !noalias !22, addrspace 1)
>  SU(16):   %15:gpr = LW %5:gpr, 12 :: (load 4 from %ir.arrayidx.3, !tbaa
> !14, !noalias !22, addrspace 1)
>  SU(17):   %16:gpr = LW %3:gpr, 12 :: (load 4 from %ir.arrayidx1.3, !tbaa
> !14, !noalias !22, addrspace 1)
>  SU(18):   %17:gpr = nsw ADD %16:gpr, %15:gpr
>  SU(20):   $x10 = COPY $x0
>  SU(19):   SW %17:gpr, %3:gpr, 12 :: (store 4 into %ir.arrayidx1.3, !tbaa
> !14, !noalias !22, addrspace 1)
>
>
>
> This is great! Memory accesses are marked noalias. I wanted memory
> accesses to be annotated as noalias to basically remove loop-carried
> dependencies so that I can reorder them for efficient scheduling. But when
> I look at Schedule DAG,
>
>
>
> For vec_add I see something like this (note BotQ.A, scheduler can choose
> any of those => no loop carried dependence):
>
>   - Latency limited.
> ** ScheduleDAGMILive::schedule picking next node
> Queue BotQ.P:
> Queue BotQ.A: 16 15 11 7 3
>   Cand SU(16) ORDER
> Pick Bot ORDER
>
>
>
> For main, at best I see something like this:
>
> ** ScheduleDAGMILive::schedule picking next node
> Cycle: 45 BotQ.A
> Queue BotQ.P:
> Queue BotQ.A: 12 13
>   Cand SU(12) ORDER
>   Cand SU(13) ORDER
>
>
>
> In theory, schedules for vec_add and main should be the same right? Is
> there anything else I should do to make the __restrict remove loop-carried
> dependence in main?
>
>
>
> Attaching IR and scheduler log for reference...
>
>
>
>
>
> On Mon, Jun 22, 2020 at 3:03 PM Jeroen Dobbelaere <
> Jeroen.Dobbelaere at synopsys.com> wrote:
>
> Hi Bandhav,
>
>
>
> as mentioned in the summary of https://reviews.llvm.org/D69542
> <https://urldefense.com/v3/__https:/reviews.llvm.org/D69542__;!!A4F2R9G_pg!OmBKB80qBacnrqnvVVCAWFkwISI7m6FZ1z4B8XOkDZKUndeom24G2GmH_KktbhCAqzAnX4K4$>
> :
>
>
>
>    The base version is b2a37cfe2bda0bc8c4d2e981922b5ac59c429bdc
> <https://urldefense.com/v3/__https:/reviews.llvm.org/rGb2a37cfe2bda0bc8c4d2e981922b5ac59c429bdc__;!!A4F2R9G_pg!OmBKB80qBacnrqnvVVCAWFkwISI7m6FZ1z4B8XOkDZKUndeom24G2GmH_KktbhCAq3tq-EY3$>
> (June 12, 2020)
>
>
>
> Greetings,
>
>
>
> Jeroen Dobbelaere
>
>
>
>
>
>
>
> *From:* llvm-dev <llvm-dev-bounces at lists.llvm.org> *On Behalf Of *Bandhav
> Veluri via llvm-dev
> *Sent:* Monday, June 22, 2020 18:32
> *To:* Neil Henning <neil.henning at unity3d.com>
> *Cc:* llvm-dev <llvm-dev at lists.llvm.org>; Kruse, Michael <
> michael.kruse at anl.gov>
> *Subject:* Re: [llvm-dev] Restrict qualifier on class members
>
>
>
> Hi Jeroen,
>
>
>
> That's great! I was trying to use the patch, what's the latest version of
> the project we could apply it on?
>
>
>
> Hi Neil,
>
>
>
> That seems like what I can do as well! Do you happen to have some examples
> lying around? Maybe a pointer to the planned presentation, if that's okay?
>
>
>
> Thank you,
>
> Bandhav
>
>
>
> On Mon, Jun 22, 2020 at 1:55 AM Neil Henning <neil.henning at unity3d.com>
> wrote:
>
> I was originally going to cover this in my now defunct EuroLLVM talk
> but... we had this exact same problem on Unity's HPC# Burst compiler - how
> to track no-aliasing on structs. We were constrained in that we had to make
> it work with LLVM versions all the way back to shipped LLVM 6, so what we
> did was:
>
>    - Add module-level metadata that tracked whether a given struct member
>    field was no-alias.
>    - Added our own alias analysis using createExternalAAWrapperPass to
>    register it in the pass pipeline.
>
> This allowed us to have zero modifications to LLVM and do something useful
> with aliasing. The one 'issue' with it is if you have a stack-allocated
> struct that is SROA'ed you will lose the info that it was a struct, or if
> you are in a private/internal linkage function that has the struct as an
> argument, the opt passes can modify the function signature to lose the
> struct too. We had to do some mitigations here to get perfect aliasing on
> our usecases.
>
>
>
> Hope this helps,
>
> -Neil.
>
>
>
> On Mon, Jun 22, 2020 at 5:44 AM Michael Kruse via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
> Unfortunately
> https://llvm.org/docs/LangRef.html#llvm-loop-parallel-accesses-metadata
> <https://urldefense.com/v3/__https:/llvm.org/docs/LangRef.html*llvm-loop-parallel-accesses-metadata__;Iw!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLJxlIVzl$>
> is not a solution here. A loop-parallel access does not imply
> non-aliasing. The obvious case is when only reading from a location,
> but even when a location is written to I'd be careful to deduce that
> they do not alias since it might be a "benign data race" or the value
> never used. Additionally, LLVM's loop unroller is known to now handle
> noalias metadata correctly as it just copies it.
>
> There has been a discussion here:
> http://lists.llvm.org/pipermail/llvm-dev/2020-May/141587.html
> <https://urldefense.com/v3/__http:/lists.llvm.org/pipermail/llvm-dev/2020-May/141587.html__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLAvIBb7x$>
>
> Michael
>
>
> Am So., 21. Juni 2020 um 12:24 Uhr schrieb Johannes Doerfert via
> llvm-dev <llvm-dev at lists.llvm.org>:
> >
> > Hi Bandhav,
> >
> >
> > Jeroen Dobbelaere (CC'ed) is currently working on support for restrict
> qualified local variables and struct members.
> >
> > The patches exist but are not merged yet. If you want to give it a try
> apply https://reviews.llvm.org/D69542
> <https://urldefense.com/v3/__https:/reviews.llvm.org/D69542__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLLzXOdAP$>
> .
> >
> >
> > Initially I could only think of this solution for your problem:
> https://godbolt.org/z/6WtPXJ
> <https://urldefense.com/v3/__https:/godbolt.org/z/6WtPXJ__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLEju0wQ6$>
> >
> > Michael (CC'ed) might now another annotation to get `llvm.access`
> metadata for the loop, which should do what you intend.
> >
> >
> > Cheers,
> >
> >   Johannes
> >
> >
> > On 6/21/20 11:56 AM, Bandhav Veluri via llvm-dev wrote:
> >
> > Hi,
> >
> > I'm trying to abstract some special pointers with a class, like in the
> > example program below:
> >
> >   1 #define __remote __attribute__((address_space(1)))
> >   2 #include <stdint.h>
> >   3
> >   4 __remote int* A;
> >   5 __remote int* B;
> >   6
> >   7 class RemotePtr {
> >   8   private:
> >   9     __remote int* __restrict a;
> >  10
> >  11   public:
> >  12     RemotePtr(__remote int* a) : a(a) {}
> >  13
> >  14     __remote int& at(int n) {
> >  15       return a[n];
> >  16     }
> >  17 };
> >  18
> >  19 int main(int argc, char** argv) {
> >  20   RemotePtr a(A);
> >  21   RemotePtr b(B);
> >  22
> >  23   #pragma unroll 4
> >  24   for(int i=0; i<4; ++i) {
> >  25     a.at
> <https://urldefense.com/v3/__http:/a.at__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLOY-9qOq$>(i)
> += b.at
> <https://urldefense.com/v3/__http:/b.at__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLBIWnTL5$>
> (i);
> >  26   }
> >  27
> >  28   return 0;
> >  29 }
> >
> > It's given that pointer a, in each object of the class RemotePtr, is the
> > only pointer that can access the array pointed by it. So, I tried
> __remote
> > int* __restrict a; (line 9) construct to tell Clang the same. This
> doesn't
> > seem to work and I see no noliass in the generated IR. Specifically, I
> want
> > lines 23-26 optimized assuming no aliasing between A and B. Any reason
> why
> > Clang shouldn't annotate memory accesses in lines 23-26 with noaliass
> > taking line 9 into account?
> >
> > The higher level problem is this: is there a way to compile lines 23-26
> > assuming no aliasing between A and B, by just doing something in the
> > RemotePtr class (so that main is clear of ugly code)? If that's not
> > possible, is there a way to tell Clang that lines 23-26 should assume no
> > aliasing at all, by some pragma?
> >
> > Thank you,
> > Bandhav
> >
> >
> > _______________________________________________
> > LLVM Developers mailing list
> > llvm-dev at lists.llvm.org
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> <https://urldefense.com/v3/__https:/lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLD9-lkj8$>
> >
> > _______________________________________________
> > LLVM Developers mailing list
> > llvm-dev at lists.llvm.org
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> <https://urldefense.com/v3/__https:/lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLD9-lkj8$>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> <https://urldefense.com/v3/__https:/lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLD9-lkj8$>
>
>
>
> --
>
> [image: Image removed by sender.]
>
> *Neil Henning*
>
> Senior Software Engineer Compiler
>
> unity.com
> <https://urldefense.com/v3/__http:/unity.com__;!!A4F2R9G_pg!KbQb7EC98K_vFVBRDQoSveXuMcvOvKcWvTers1QW_g1LmGPsOh-wI0r2mV_c2G1yLJhMkp2Z$>
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200624/146c2eb8/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: image001.jpg
Type: image/jpeg
Size: 380 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200624/146c2eb8/attachment.jpg>


More information about the llvm-dev mailing list