llvm.noalias patches

Hal Finkel via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 11 05:20:23 PDT 2016


----- Original Message -----

> From: "Daniel Berlin" <dberlin at dberlin.org>
> To: "Hal Finkel" <hfinkel at anl.gov>
> Cc: "chandlerc" <chandlerc at gmail.com>, "Philip Reames"
> <listmail at philipreames.com>, "John McCall" <rjmccall at apple.com>,
> "David Majnemer" <david.majnemer at gmail.com>, "llvm-commits"
> <llvm-commits at lists.llvm.org>
> Sent: Sunday, July 10, 2016 3:40:30 PM
> Subject: Re: llvm.noalias patches

> On Mon, Jul 11, 2016 at 1:54 AM, Hal Finkel < hfinkel at anl.gov >
> wrote:

> > Hi again,
> 

> > Thanks to David Majnemer for reviewing many of the patches. David
> > made an important observation: Instead of making the "looking
> > through the intrinsic" logic about the llvm.noalias intrinsic
> > specifically, we could add the 'returned' attribute to the relevant
> > parameter and make the patches about looking through calls with a
> > 'returned' parameter. I like this approach much better, and I'll
> > rework the patches to do this. Also, we don't seem to infer the
> > returned attribute; I'll post a patch for that too.
> 

> > Another change I need to make is that I need to add a second
> > metadata
> > parameter to the intrinsic, analogous to the alias.scope metadata
> > we
> > have currently. While the semantics as they stand are fine, they're
> > not completely sufficient for representing local restrict-qualified
> > pointers in C where the pointer variable itself is updated. For
> > example, if we have:
> 

> > void foo(int *a) {
> 
> > int *restrict r = a;
> 
> > *r++ = 1;
> 
> > *r++ = 2;
> 
> > --r;
> 
> > *r = 3;
> 
> > }
> 

> > With the Clang CodeGen patch, the resulting IR looks like this
> > (after
> > optimization):
> 

> > define void @foo(i32* nocapture %a) local_unnamed_addr #0 {
> 
> > entry:
> 
> > %0 = tail call i32* @llvm.noalias.p0i32(i32* %a, metadata !1)
> 
> > %incdec.ptr = getelementptr inbounds i32, i32* %0, i64 1
> 
> > %1 = tail call i32* @llvm.noalias.p0i32(i32* %incdec.ptr, metadata
> > !1)
> 
> > store i32 1, i32* %0, align 4, !tbaa !4, !noalias !1
> 
> > %incdec.ptr1 = getelementptr inbounds i32, i32* %1, i64 1
> 
> > %2 = tail call i32* @llvm.noalias.p0i32(i32* %incdec.ptr1, metadata
> > !1)
> 
> > store i32 2, i32* %1, align 4, !tbaa !4, !noalias !1
> 
> > %incdec.ptr2 = getelementptr inbounds i32, i32* %2, i64 -1
> 
> > %3 = tail call i32* @llvm.noalias.p0i32(i32* %incdec.ptr2, metadata
> > !1)
> 
> > store i32 3, i32* %3, align 4, !tbaa !4, !noalias !1
> 
> > ret void
> 
> > }
> 

> > which yields this:
> 

> > NoAlias: store i32 2, i32* %1, align 4, !tbaa !4, !noalias !1 <->
> > store i32 1, i32* %0, align 4, !tbaa !4, !noalias !1
> 
> > NoAlias: store i32 3, i32* %3, align 4, !tbaa !4, !noalias !1 <->
> > store i32 1, i32* %0, align 4, !tbaa !4, !noalias !1
> 
> > NoAlias: store i32 3, i32* %3, align 4, !tbaa !4, !noalias !1 <->
> > store i32 2, i32* %1, align 4, !tbaa !4, !noalias !1
> 

> > but that's not correct. The common case is that a
> > restrict-qualified
> > pointer is initialized once and then used as a base pointer for
> > further computations. However, nothing prevents updating the
> > pointer
> > variable to point to an object it pointed to previously.
> 
> > The rule, as it stands, is that an access with a noalias scope
> > using
> > a pointer based on the intrinsic's return value (with a compatible
> > scope parameter) does not alias with an access using a pointer with
> > a compatible noalias scope not based on the intrinsics's return
> > value. With a second metadata parameter, this will grow to be: ...
> > not based on the return value from any intrinsic with the same
> > second metadata parameter (the alias.scope parameter).
> 
> Out of curiosity (and we may have talked about this a year ago), is
> this valid, and if so, what is the noalias status of the phi'd
> variable?

It is certainly legal, and the phi'd variable is based on either the first llvm.noalias or the second. As a result, it won't alias with pointers that are themselves not based on either one (if the other pointer is based on either, or both, of the two llvm.noalias intrinsics, then we can't say anything). 

Thanks again, 
Hal 

> define void @foo(i32* nocapture %a) {
> entry:

> br i1 <something> label %if, label %else
> if:

> %foo = llvm.noalias(%a, !1)
> br label %merge
> else:
> %bar = llvm.noalias(%a, !2)
> br label %merge
> merge:
> baz = phi(%foo, %bar)
> <use of baz>

-- 

Hal Finkel 
Assistant Computational Scientist 
Leadership Computing Facility 
Argonne National Laboratory 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160711/5ad3aaca/attachment.html>


More information about the llvm-commits mailing list