[LLVMdev] C99 restrict
Dan Gohman
djg at cray.com
Mon Mar 26 16:47:38 PDT 2007
On Mon, Mar 26, 2007 at 12:47:04PM -0500, Christopher Lamb wrote:
>
>
> On Mar 26, 2007, at 10:10 AM, Dan Gohman wrote:
>
> >On Mon, Mar 26, 2007 at 02:14:56AM -0500, Christopher Lamb wrote:
> >>
> >>
> >>On Mar 25, 2007, at 5:22 PM, Chris Lattner wrote:
> >>
> >>>On Sun, 25 Mar 2007, Christopher Lamb wrote:
> >>>>What about an approach not unlike how debugging information is
> >>>>handled? That
> >>>>is have an llvm intrinsic that encodes the known alias free range
> >>>>for a
> >>>>pointer.
> >>>
> >>>That is another great possibility. One issue is that I haven't had
> >>>time
> >>>to study the implications of C99 restrict, so I don't feel
> >>>qualified to
> >>>propose a concrete solution yet. Ideally, the mechanism added to
> >>>LLVM
> >>>would be able to handle restrict as well as fortran argument
> >>>parameters
> >>>(even if the fortran functions are inlined!), etc. IOW, we don't
> >>>want to
> >>>have an feature that just implements C99 restrict, we want a more
> >>>general
> >>>mechanism which C99 restrict can be implemented in terms of. It
> >>>seems
> >>>like an intrinsic would be a good way to do that.
> >>
> >>Certainly language independence is a requirement.
> >>
> >>I think your point about inlined functions is also valid for restrict
> >>parameters to functions that have been inlined in C/C++. The aliasing
> >>guarantees are limited to within that function's scope For an
> >>intrinsics approach this would require intrinsics which estrict/
> >>unrestrict the pointer bounding it's life within the function where
> >>it is declared restrict. The other approach would be to add
> >>attributes that mark all uses of the pointers as explicitly alias
> >>free, which would be much more invasive.
> >
> >For representing scoping information, a relatively non-invasive
> >approach is to introduce a special "copy" operation, which in LLVM
> >might look like
> > %a = copy %b
> >This operation has to be somewhat special in that can't be folded away
> >in most cases, but it can otherwise be pretty straight-forward to
> >optimizers. The idea is to allow %a to be used in whatever alias
> >intrinsics are available without tainting %b. An inliner would
> >generate
> >these special instructions for each of the arguments, and then all
> >references to the arguments within the inlined body would be made
> >through these copies.
BTW, I misspoke here; this doesn't address the scoping problem.
> >
> >An alias-free attribute wouldn't be usable in general because pointers
> >are almost never completely alias-free. For example in C:
>
> From my understanding the 'restrict' qualifier is a directive to the
> compiler that the pointer or reference should be treated as alias
> free within the scope of the function, regardless. For the below code
> alias(p, q) == No, and alias(p, r) == No, even though q is "based-on"
> p and r may be "based-on" p. This is both the power and danger of
> 'restrict', as it is up to the programmer to use it correctly.
The definition of restrict is more involved than that. A restrict-qualified
pointer may alias a pointer "based-on" it. And if the "based-on" relationships
aren't known, then the answer to the associated alias queries must be Maybe.
In the test I posted below, the program is correct if x, y, and z are all
the same, so the stores cannot be reordered.
> > int * restrict p = ...;
> > p[x] = 0;
> > p[y] = 1;
> > int * q = p + z;
> > *q = 2;
> > *p = 3;
> > int * r = foo(p);
> > *r = 4;
> >
> >Translated to LLVM:
> >
> > %t0 = getelementptr %p, %x
> > store 0, %t0
> > %t1 = getelementptr %p, %y
> > store 1, %t1
> > %q = getelementptr %p, %z
> > store 2, %q
> > store 3, %p
> > %r = call @foo(%p)
> > store 4, %r
> >
> >C's restrict keyword allows pointers to be "based-on" restrict-
> >qualified
> >pointers, such as q in this example. The definition of "based-on" does
> >not require the relationship to be obvious though. r in this
> >example may
> >or may not be "based-on" p, so an optimizer must make very
> >conservative
> >assumptions unless it can get more information about foo.
>
> My understanding of 'restrict' is that the compiler isn't required to
> check that the semantics of restrict aren't violated. I would assume
> that FORTRAN arguments are the same way, since determining whether or
> not the semantics of are being violated is just as hard as normal
> alias analysis.
>
> It may even be incorrect for the compiler to enforce the semantics of
> restrict pointers (with an error), even when the compilers alias
> analysis determines that there is a may-alias relationship between to
> pointers. Take the following example, which the compiler is now free
> to unroll and reschedule:
>
> struct element { int a, b; };
>
> void swap(element * arr, int size)
> {
> int * __restrict a = &arr[0].a;
> int * __restrict b = &arr[0].b;
> for (int i=0; i!=size; ++i)
> {
> int tmp = a[i];
> a[i] = b[i];
> b[i] = tmp;
> a += 2;
> b += 2;
> }
> }
Yes; this test case is relatively simple to analyze.
> >Beyond C, some form of "based-on" relationship would also be needed
> >for
> >LLVM IR, at least so that it could cope with things like %t0 and %t1
> >aliasing each other and %p in this example.
> >
> >Dan
> >
> >--
> >Dan Gohman, Cray Inc.
>
> --
> Christopher Lamb
> christopher.lamb at gmail.com
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
More information about the llvm-dev
mailing list