[llvm-dev] Using full restrict to map sets of variables to a universe

Tarique Islam via llvm-dev llvm-dev at lists.llvm.org
Wed Jul 15 12:23:56 PDT 2020


Hi Jeroen,

  Thanks very much for the suggestion. We are going to explore the idea. We
need to think a bit more about representing partially overlapping groups.

Regards,
Tarique Islam
XL Fortran Compiler Development
IBM Toronto Software Lab






From:	Jeroen Dobbelaere <Jeroen.Dobbelaere at synopsys.com>
To:	Kelvin Li <kli at ca.ibm.com>, Tarique Islam <tislam at ca.ibm.com>,
            "llvm-dev at lists.llvm.org" <llvm-dev at lists.llvm.org>
Date:	2020-07-15 06:42 AM
Subject:	[EXTERNAL] Using full restrict to map sets of variables to a
            universe



Hi Kelvin, Tarique,

Based on what I understood from your explanation yesterday in the LLVM AA
Technical call,
you can probably use following technique to map 'sets of global variables'
to their own 'alias scope':

The (rough) c equivalent code looks like:

---
// Conceptual example of mapping an access to a generic set:
// set A
int tgtA01, tgtA02, tgtA03;
int * __restrict pSetA; // restrict to setA

// set B
int tgtB01, tgtB02, tgtB03;
int * __restrict pSetB; // restrict to setB


int* addSingleRestrictInfo(int* p, int * __restrict* pSet) {
  *pSet = p;
  return *pSet;
}

extern int _g2RestrictI; // must not be 'known'
int* addTwoRestrictInfo(int *p, int *__restrict* pSet0, int *__restrict*
pSet1) {
  int * retP;
  if (_g2RestrictI == 0) {
    *pSet0 = p;
    retP = *pSet0;
  } else {
    *pSet1 = p;
    retP = *pSet1;
  }
  return retP;
}

void test(int *pA, int *pB, int *pAB) {
  *addSingleRestrictInfo(pA, &pSetA) = 42;
  *addSingleRestrictInfo(pB, &pSetB) = 43;
  *addTwoRestrictInfo(pAB, &pSetA, &pSetB) = 44;
}
----

It is based on:
- pSetA and pSetB representing two different 'object P', each specifying
its own set of objects
- they work at global level (depending on the "unknown function" scope) ->
after inlining, its information will still apply.
- addSingleRestrictInfo / addTwoRestrictInfo are used to introduce restrict
information to a pointer


Of course, this conceptual example will introduce unnecessary stores to
'pSetA' and 'pSetB', so the actual llvm-ir you would want to produce for
your fortran mapping should look something like:

----
; Function Attrs: nofree nounwind uwtable
define dso_local void @test(i32* %pA, i32* %pB, i32* %pAB)
local_unnamed_addr #1 !noalias !14 {
entry:
  %0 = tail call i32*
@llvm.provenance.noalias.p0i32.p0i8.p0p0i32.p0p0i32.i64(i32* %pA, i8* null,
i32** nonnull @pSetA, i32** undef, i64 0, metadata !14)
#3, !tbaa !5, !noalias !14
  store i32 42, i32* %pA, ptr_provenance i32* %0, align
4, !tbaa !12, !noalias !14
  %1 = tail call i32*
@llvm.provenance.noalias.p0i32.p0i8.p0p0i32.p0p0i32.i64(i32* %pB, i8* null,
i32** nonnull @pSetB, i32** undef, i64 0, metadata !14)
#3, !tbaa !5, !noalias !14
  store i32 43, i32* %pB, ptr_provenance i32* %1, align
4, !tbaa !12, !noalias !14
  %2 = load i32, i32* @_g2RestrictI, align
4, !tbaa !12, !noalias !14                                           ;;
NOTE: unnecessary load
  %cmp.i = icmp eq i32 %2, 0
  %3 = tail call i32*
@llvm.provenance.noalias.p0i32.p0i8.p0p0i32.p0p0i32.i64(i32* %pAB, i8*
null, i32** nonnull @pSetA, i32** undef, i64 0, metadata !14)
#4, !tbaa !5, !noalias !14
  %4 = tail call i32*
@llvm.provenance.noalias.p0i32.p0i8.p0p0i32.p0p0i32.i64(i32* %pAB, i8*
null, i32** nonnull @pSetB, i32** undef, i64 0, metadata !14)
#4, !tbaa !5, !noalias !14
  %prov.retP.0.i = select i1 %cmp.i,  i32* %3, i32*  %4
  store i32 44, i32* %pAB, ptr_provenance i32* %prov.retP.0.i, align
4, !tbaa !12, !noalias !14
  ret void
}
----

This still contains an unnecessary load from '_g2RestrictI' (which should
be optimized away at MIR level).

For these kind of use cases, it makes sense to introduce a new intrinsic
that joins the possible @llvm.provenance.noalias paths.
It should replace the load/cmp/select; something like:
    %prov.retP.0.i = call i32* @llvm.provenance.depends i32* %3, i32* %4

You also do not need to map 'pSetA' and 'pSetB' to real memory locations.
After lowering to MIR, those dependencies should be gone.

Greetings,

Jeroen Dobbelaere



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200715/a06f74ac/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: graycol.gif
Type: image/gif
Size: 105 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200715/a06f74ac/attachment.gif>


More information about the llvm-dev mailing list