[PATCH] D37419: Teach scalar evolution to handle inttoptr/ptrtoint

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 4 00:01:46 PDT 2017


Hi all,

This is a "batched" reply:

On Sun, Sep 3, 2017 at 6:35 PM, Daniel Berlin <dberlin at dberlin.org> wrote:
> I'll also point out, you didn't read or write anything in your example.
> Which is strange to me because the usual semantic is "allowed to alias, but
> not allowed to be used to load/store".
> IE if you ask if the two pointers alias, the answer is yes.
> If you ask if a load can touch a given store, the answer is no.
>
> Here you are saying the pointer aliasing rules apply even to
> unwritten/unread pointers.
> That to me, is ... very strange.

I agree that it is odd to assign aliasing relationship between
pointers, and that isn't central to what I was trying to say.  The
behavior remains if I add a load and a store:

```
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define void @f(i64 %arg, i64 %arg1) {
bb:
  %p0 = tail call noalias i8* @malloc(i64 %arg) #3
  %p1 = tail call noalias i8* @malloc(i64 %arg) #3
  %offset = tail call i64 @subtract(i8* %p1, i8* %p0)
  %gep = getelementptr i8, i8* %p0, i64 %offset  ;; not inbounds
  %v0 = load i8, i8* %gep
  store i8 40, i8* %p1
  ret void
}

declare noalias i8* @malloc(i64)
declare i64 @subtract(i8*, i8*)
```

opt -basicaa -aa-eval -print-all-alias-modref-info
-evaluate-aa-metadata ir.ll |& grep NoAlias
  NoAlias:      i8* %p0, i8* %p1
  NoAlias:      i8* %gep, i8* %p1
  NoAlias:   %v0 = load i8, i8* %gep <->   store i8 40, i8* %p1

On Sun, Sep 3, 2017 at 10:26 PM, Xinliang David Li <davidxl at google.com> wrote:
> SCEV itself can be canonicalized plus one bit to show it if is commutable.
> If it is, generate the conservative/aliasing losing add form, otherwise
> generate the GEP form.

Yes, something like that can work; but at that point I'd rather have
ptrtoint and inttoptr be explicitly modeled in SCEV.

> However I find this situation extremely rare to be worth the effort: a
> really deferencible pointer is used as an offset. If the pointer is not
> dereferenced, the false aliasing does not really matter.

I may not have fully grasped what you're suggesting (so what I'm about
to say may be off base), but if a SCEV->SCEV expander round-trip has
to transform:

```
%a0 = alloca
%a1 = alloca
escape(%a1)
%offset = f()
%ptr = gep %a0, %offset
```

to

```
%a0 = alloca
%a1 = alloca
escape(%a1)
%offset = f()
%i0 = ptrtoint %a0
%ptr.int = add %i0, %offset
%ptr = inttoptr %ptr.int
```

to be correct in possible but rare (pointer adding) cases, then we
lose the fact that %ptr no-alias %a1.  IOW compensating for the rare
but possible case can regress aliasing for the normal cases.

On Sun, Sep 3, 2017 at 11:40 PM, Daniel Berlin <dberlin at dberlin.org> wrote:
> So, i instrumented llvm to add runtime asserts about the noaliasing pointers
> before free (IE it adds an assert that, for each pointer that is noaliased
> with the pointer passed to free, free is not destroying that pointer), and
> it fails really quickly.

That's not too surprising; a simple case where this may happen is:

  %p0 = malloc(10)
  free(%p0)
  %p1 = malloc(10);
  free(%p1)

In the second free %p0 no-alias %p1, but they're very likely the same
bitwise value.  NoAlias does not mean "different bitwise values".

Having said that, there are known issues with how we model memory in
LLVM.  Nuno (CC'ed), Gil, John et. al. are working on fixing this.

-- Sanjoy


More information about the llvm-commits mailing list