[llvm-dev] RFC: New function attribute HasInaccessibleState

Sanjoy Das via llvm-dev llvm-dev at lists.llvm.org
Sun Dec 13 21:29:12 PST 2015


Vaivaswatha Nagaraj via llvm-dev wrote:
 >  >I'm against adding this as a "subtractive" attribute. We need to add these as new attributes, not as an attribute that
 > makes readonly a little less read only. I believe we're in agreement on this point.
 > Just to make sure I understood right, below are the things that need to be done:
 > (Approach A)
 > 1. We define a new a attribute "HasInaccessibleState" to denote "this function might access globals, but none of these
 > globals can alias with any memory location accessible from the IR being optimized".
 > 2. Mark malloc/free as  (HasInaccessibleState, ReadNone) and printf as (HasInaccessibleState, ArgMemOnly) ... (similarly
 > other libc functions).

You'll have to mark free as argmemonly + read-write, since the
following transform needs to be illegal:

   val = *ptr
   free(ptr)

=>

  free(ptr)
  val = *ptr

In fact, I think you can mark @free as argmemonly *today* without any
problems.  There is a theoretical issue on whether a "write" can make
a location no longer dereferenceable, but that's not new.

 > 3. Any function whose definition is not available needs to be marked with "HasInaccessibleState" (conservatively).
 > 4. Propagate the flag "HasInaccessibleState" upwards in the call graph. (Do this in FunctionAttrs.cpp?).
 > 5. Since ReadNone and ArgMemOnly has now been redfined, all optimizations that rely on these flags for safety now also
 > need to check the new "HasInaccessibleState" flag and make sure it isn't present.
 > 6. GlobalsAA will be modified according to the diff in the first mail in this email thread.
 >
 > The alternative approach that was discussed would involve the following changes:
 > (Approach B)
 > 1. Define new attributes AlmostReadNone and AlmostArgMemOnly, (with the "Almost" part denoting that the function may
 > accesses globals that are not part of the IR).
 > 2. malloc/free would have AlmostReadNone set and printf would have AlmostArgMemOnly set ... (and similarly other libc
 > calls).
 > 3. In the diff I originally posted for GlobalsAA, the code would check for AlmostReadNone or AlmostArgMemOnly too (along
 > with ReadNone or ArgMemOnly).
 >
 > Approach B seems simpler to me, but I understand the concern about having a "subtractive" attribute which is new to the
 > framework. If there is a consensus on which of these two approaches is the way to go, I can submit a quick prototype
 > patch for further review/discussion.

A third approach is to extend the noalias metadata [1] (I mentioned
this earlier in the thread, but did not do a good job on
expanding on it).  Currently noalias metadata can be used to specify
that a certain call or invoke does not read / modify memory locations
belonging to certain *specific* alias domains.  We could generalize
this mechanism and specify a new kind of alias domain called (say)
!ir-mem.  Calls to @malloc and @printf could be marked with "!noalias
!ir-mem" [2], and we could specify (as an axiom) that no loads and
stores visible at the IR level alias with the !ir-mem domain.  The
advantage of this approach is that we won't have to introduce any
fundamentally new first class concepts to LLVM IR (though it would
still be a fair amount of work).

[1]: http://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata
[2]: We'll also have to introduce an "NoAliasIRMem" attribute, that
can be used denote that all calls to the marked function are !noalias
!ir-mem.

-- Sanjoy


 >
 > Thanks,
 >
 >
 >    - Vaivaswatha
 >
 > On Sat, Dec 12, 2015 at 3:21 AM, Hal Finkel via llvm-dev <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>> 
wrote:
 >
 >     ----- Original Message -----
 >     >  From: "Joseph Tremoulet" <jotrem at microsoft.com <mailto:jotrem at microsoft.com>>
 >     >  To: "Hal Finkel" <hfinkel at anl.gov <mailto:hfinkel at anl.gov>>, "Mehdi Amini" <mehdi.amini at apple.com
 >     <mailto:mehdi.amini at apple.com>>
 >     >  Cc: "llvm-dev" <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>>
 >     >  Sent: Friday, December 11, 2015 3:35:38 PM
 >     >  Subject: RE: [llvm-dev] RFC: New function attribute HasInaccessibleState
 >     >
 >     >  Yeah, I'd agree (rewording slightly) that "state which is only
 >     >  modified by external code" is well-defined (and likely to be in the
 >     >  "other" bucket of any individual analysis).  I do, as other have,
 >     >  find it odd to redefine readonly and argmemonly in terms of this and
 >     >  require its propagation up the call graph, as opposed to introducing
 >     >  new "writes only external" and "writes only arg and external"
 >     >  attributes.
 >
 >     As I stated in some other e-mail, I'm against adding this as a "subtractive" attribute. We need to add these as new
 >     attributes, not as an attribute that makes readonly a little less read only. I believe we're in agreement on this 
point.
 >
 >       -Hal
 >
 >      >
 >      > Thanks
 >      > -Joseph
 >      >
 >      > -----Original Message-----
 >      > From: Hal Finkel [mailto:hfinkel at anl.gov <mailto:hfinkel at anl.gov>]
 >      > Sent: Friday, December 11, 2015 4:00 PM
 >      > To: Mehdi Amini <mehdi.amini at apple.com <mailto:mehdi.amini at apple.com>>
 >      > Cc: llvm-dev <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>>; Joseph Tremoulet
 >      > <jotrem at microsoft.com <mailto:jotrem at microsoft.com>>
 >      > Subject: Re: [llvm-dev] RFC: New function attribute
 >      > HasInaccessibleState
 >      >
 >      > ----- Original Message -----
 >      > > From: "Mehdi Amini" <mehdi.amini at apple.com <mailto:mehdi.amini at apple.com>>
 >      > > To: "Joseph Tremoulet" <jotrem at microsoft.com <mailto:jotrem at microsoft.com>>
 >      > > Cc: "Hal Finkel" <hfinkel at anl.gov <mailto:hfinkel at anl.gov>>, "llvm-dev"
 >      > > <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>>
 >      > > Sent: Friday, December 11, 2015 1:28:05 PM
 >      > > Subject: Re: [llvm-dev] RFC: New function attribute
 >      > > HasInaccessibleState
 >      > >
 >      > >
 >      > > > On Dec 11, 2015, at 11:16 AM, Joseph Tremoulet
 >      > > > <jotrem at microsoft.com <mailto:jotrem at microsoft.com>> wrote:
 >      > > >
 >      > > > <<<
 >      > > > I may misunderstand, but it seems to me that this solves only
 >      > > > query
 >      > > > for aliasing with a pointer known to be pointing only to globals
 >      > > > defined in the current compilation unit.
 >      > > > For any pointer which "may point somewhere else”, you won’t be
 >      > > > able
 >      > > > to resolve the non-aliasing with the “internal state” for
 >      > > > malloc/free, right?
 >      > > >
 >      > > > To take the original example in this thread:
 >      > > >
 >      > > > int *x = malloc(4);
 >      > > > *x = 2;
 >      > > > int *y = malloc(4);
 >      > > > *y = 4;
 >      > > >
 >      > > > A pointer analysis can solve this case, but I’m not sure it scale
 >      > > > inter procedurally and will have a limited impact outside of LTO
 >      > > > anyway.
 >      > > >>>>
 >      > > >
 >      > > > I think you're understanding correctly, but I don't understand
 >      > > > what
 >      > > > you're saying will go badly with the malloc example.  Quoting the
 >      > > > start of the thread:
 >      > > >
 >      > > > <<<
 >      > > > The intention behind introducing this attribute is to relax the
 >      > > > conditions in GlobalsAA as below:
 >      > > > (this code is in GlobalsAAResult::AnalyzeCallGraph)
 >      > > >       if (F->isDeclaration()) {
 >      > > >         // Try to get mod/ref behaviour from function attributes.
 >      > > > -        if (F->doesNotAccessMemory()) {
 >      > > > +        if (F->doesNotAccessMemory() ||
 >      > > > F->onlyAccessesArgMemory()) {
 >      > > >           // Can't do better than that!
 >      > > >         } else if (F->onlyReadsMemory()) {
 >      > > >           FunctionEffect |= Ref;
 >      > > >           if (!F->isIntrinsic())
 >      > > >             // This function might call back into the module and
 >      > > >             read a global -
 >      > > >             // consider every global as possibly being read by
 >      > > >             this
 >      > > >             function.
 >      > > >             FR.MayReadAnyGlobal = true;
 >      > > >         } else {
 >      > > >           FunctionEffect |= ModRef;
 >      > > >           // Can't say anything useful unless it's an intrinsic -
 >      > > >           they don't
 >      > > >           // read or write global variables of the kind
 >      > > >           considered
 >      > > >           here.
 >      > > >           KnowNothing = !F->isIntrinsic();
 >      > > >         }
 >      > > >         continue;
 >      > > >       }
 >      > > > This relaxation allows functions that (transitively) call library
 >      > > > functions (such as printf/malloc) to still maintain and propagate
 >      > > > GlobalsAA info. In general, this adds more precision to the
 >      > > > description of these functions.
 >      > > > Concerns regarding impact on other optimizations (I'm repeating a
 >      > > > few examples that Hal mentioned earlier).
 >      > > >
 >      > > > 1.
 >      > > >> A readnone function is one whose output is a function only of
 >      > > >> its
 >      > > >> inputs, and if you have this:
 >      > > >>
 >      > > >> int *x = malloc(4);
 >      > > >> *x = 2;
 >      > > >> int *y = malloc(4);
 >      > > >> *y = 4;
 >      > > >> you certainly don't want EarlyCSE to replace the second call to
 >      > > >> malloc with the result of the first (which it will happily do if
 >      > > >> you mark malloc as readnone).
 >      > > >>>>
 >      > > >
 >      > > > It sounded like improving GlobalsAA (and thus disambiguation
 >      > > > against
 >      > > > globals) was the explicit goal, and that the concern with the
 >      > > > malloc
 >      > > > case was that you don't want EarlyCSE to start combining those
 >      > > > two
 >      > > > calls; I may be misunderstanding the code, but I wouldn't expect
 >      > > > EarlyCSE to start combining those calls just because they have a
 >      > > > new
 >      > > > meaningful-only-to-GlobalsAA "almost-readnone" attribute.
 >      > >
 >      > > Sure, my point is not that your solution would enable CSE where we
 >      > > don’t want, but rather that it is not as powerful as what the
 >      > > attribute “HasInaccessibleState” would model, which I saw as "this
 >      > > function might access globals, but none of these globals can alias
 >      > > with any memory location accessible from the IR being optimized”.
 >      >
 >      > This is also, essentially, what I had in mind. I think it is
 >      > sufficiently well defined in this form.
 >      >
 >      >  -Hal
 >      >
 >      > > For instance:
 >      > >
 >      > > void foo(int *x) {
 >      > >   int *y = malloc(4);
 >      > >   *x = 2;
 >      > > }
 >      > >
 >      > > If you don’t know anything about x, can you execute the write to *x
 >      > > before the call to malloc?
 >      > > This is something that the HasInaccessibleState would allow, but I
 >      > > don’t believe would be possible with your categorization.
 >      > >
 >      > > I’m don’t know how much it matters in practice, but I’d rather be
 >      > > sure
 >      > > we’re on the same track about the various tradeoff.
 >      > >
 >      > > —
 >      > > Mehdi
 >      > >
 >      > >
 >      > >
 >      > > >
 >      > > >
 >      > > > To the larger point of whether there are other similar cases that
 >      > > > extending GlobalsAA wouldn't allow us to optimize -- yes,
 >      > > > certainly.
 >      > > > I'm just saying that I think that the notion of "external state"
 >      > > > is
 >      > > > much easier to define in the context of a particular analysis
 >      > > > than
 >      > > > the IR as a whole, and that I'd expect that coordinating the
 >      > > > notion
 >      > > > across analyses would require methods on the analysis API
 >      > > > explicitly
 >      > > > for that coordination.
 >      > > >
 >      > > >
 >      > > >
 >      > > > —
 >      > > > Mehdi
 >      > > >
 >      > >
 >      > >
 >      >
 >      > --
 >      > Hal Finkel
 >      > Assistant Computational Scientist
 >      > Leadership Computing Facility
 >      > Argonne National Laboratory
 >      >
 >
 >     --
 >     Hal Finkel
 >     Assistant Computational Scientist
 >     Leadership Computing Facility
 >     Argonne National Laboratory
 >     _______________________________________________
 >     LLVM Developers mailing list
 >     llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>
 >     http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
 >
 >
 > _______________________________________________
 > LLVM Developers mailing list
 > llvm-dev at lists.llvm.org
 > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev


More information about the llvm-dev mailing list