Propagating noalias annotation

Hello,

Do we have a pass that propagate the noalias annotation down to the callee when:

  • it is static
  • it is always called with non aliasing pointers
    ?

Or maybe that is incorrect?

Is this what you are looking for?

https://reviews.llvm.org/D4609

Best,

Haicheng Wu

Hi, Alexandre,

We don't have anything currently which does this. Note that, without further analysis of the uses of the potentially-noalias pointers, you can do this only for arguments with distinct (and identified) underlying objects (i.e., you need something a bit stronger than just "non-aliasing pointers").

  -Hal

Could you elaborate “Note that, without further analysis of the uses of the potentially-noalias pointers, you can do this only …”?
Why the uses, instead of the def, of pointer matter?

Thanks
Hongbin

Both matter. static int foo(int *a, int *b) { return a[0] + b[1]; } int bar(int *x) { return foo(x+1, x); } You can’t mark a and b as noalias here, even though NoAlias(x+1, x) == true. This is why I was saying that, unless the pointers come from distinct, identified underlying objects, you need to look at the uses of the pointers too. -Hal P.S. As discussed in D4609, we probably want to try adding CGSCC AA wrappers, to look back through function arguments, instead of using attribute propagation.

Do you mean a and b are noalias if:

static int foo(int *a, int *b) {
return a[0] + b[0];
}

int bar(int *x) {
return foo(x+1, x);
}

?

To me, because “AA.alias((x+1, MemoryLocation::UnknownSize), (x, MemoryLocation::UnknownSize)) != NoAlias”, so a and b are not noalias.
Maybe my version is too conservative.

Thanks
Hongbin

Could you elaborate "Note that, without further analysis of the uses of
the potentially-noalias pointers, you can do this only ..."?
Why the uses, instead of the def, of pointer matter?

Both matter.

static int foo(int *a, int *b) {
  return a[0] + b[1];
}

int bar(int *x) {
  return foo(x+1, x);
}

You can't mark a and b as noalias here, even though NoAlias(x+1, x) ==
true. This is why I was saying that, unless the pointers come from
distinct, identified underlying objects, you need to look at the uses of
the pointers too.

-Hal

P.S. As discussed in D4609, we probably want to try adding CGSCC AA
wrappers, to look back through function arguments, instead of using
attribute propagation.

Also, is CFLSteensAA able to help D4609?

Thanks
Hongbin

Remember that MemoryLocation::UnknownSize is unknown, but positive. So you need to check both “AA.alias((x+1, MemoryLocation::UnknownSize), (x, MemoryLocation::UnknownSize)) == NoAlias” and “AA.alias((x, MemoryLocation::UnknownSize), (x+1, MemoryLocation::UnknownSize)) == NoAlias” to partition by underlying object. One of these should be false. -Hal

Do you mean a and b are noalias if:

static int foo(int *a, int *b) {
  return a[0] + b[0];
}

int bar(int *x) {
  return foo(x+1, x);
}

?

To me, because "AA.alias((x+1, MemoryLocation::UnknownSize),
(x, MemoryLocation::UnknownSize)) != NoAlias", so a and b are not noalias.

Remember that MemoryLocation::UnknownSize is unknown, but positive. So you
need to check both "AA.alias((x+1, MemoryLocation::UnknownSize), (x,
MemoryLocation::UnknownSize)) == NoAlias" and "AA.alias((x,
MemoryLocation::UnknownSize), (x+1, MemoryLocation::UnknownSize)) ==
NoAlias" to partition by underlying object. One of these should be false.

Thanks a lot for the explanation.
Do you mean AA.alias(X,Y) may not always return the same result as
AA.alias(Y,X)? (otherwise why we need to do both of them)
[1] Didn't mention this detail.

Thanks again
Hongbin

[1] https://llvm.org/docs/AliasAnalysis.html#the-alias-method

Yes, but I should clarify (what I typed gives the wrong implication). If both values have an unknown size, then it should be symmetric. If only one is, however, there can be a difference between: | x | | y … → | and: | x … → | | y | and this is because the unknown size is unknown, but positive. -Hal