[PATCH] D84860: [LangRef] Add uniqueptr attribute.

Hal Finkel via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 29 10:00:49 PDT 2020


hfinkel added a comment.

In D84860#2182432 <https://reviews.llvm.org/D84860#2182432>, @fhahn wrote:

> In D84860#2182375 <https://reviews.llvm.org/D84860#2182375>, @hfinkel wrote:
>
>>> We cannot remove the second load, because nothing guarantees that %x did not escape before calling the function. The new attribute provides exactly this guarantee, allowing us to remove the second load.
>>
>> Why does noalias not provide the relevant guarantee? Even if the pointer had escaped, your call to `@sideeffect` would not be allowed to access the value through that escaped pointer (unless it were passed as an argument to `@sideeffect`) because that would violate the rule that all values accessed through a noalias pointer are accessed only through pointers based on the noalias pointer within the scope of the noalias pointer.
>
> I think it boils down to the exact interpretation of `noalias` for the IR example below. Assume `%0` would be marked as `noalias`. IIUC your comment correctly, `@sideffect` would not be allowed to modify the underlying object of `%0` (this also matches my reading of the `based-on` rules, with `value` referring to LLVM IR/SSA value).
>
>   %struct.Foo = type { i8*, i8*, i32 }
>   
>   @PTR = dso_local local_unnamed_addr global %struct.Foo* null, align 8
>   
>   define dso_local i32 @test(%struct.Foo* %0) local_unnamed_addr #0 {
>     %2 = getelementptr inbounds %struct.Foo, %struct.Foo* %0, i64 0, i32 2
>     %3 = load i32, i32* %2, align 8, !tbaa !2
>     store %struct.Foo* %0, %struct.Foo** @PTR, align 8, !tbaa !8
>     tail call void bitcast (void (...)* @sideeffect to void ()*)() #2
>     %4 = load i32, i32* %2, align 8, !tbaa !2
>     %5 = add nsw i32 %4, %3
>     ret i32 %5
>   }
>   
>   declare dso_local void @sideeffect(...) local_unnamed_addr #1
>
> If the above is true, then `noalias` would be too strict, because modifications via an escaped pointer in the function should be allowed with the `uniqueptr` semantics. IIUC we need to allow modifications, because references to passed-by-value objects can escape and used to modify the object in callees, as in something like the code below, where `@sideeffect` would be allowed to modify `x` via `PTR`
>
>   struct Foo *PTR;
>   
>   int test(struct Foo x) {
>       int a = x.i;
>       PTR = &x;
>       sideeffect();
>       return x.i + a;
>   }

No, that's okay. The "based on" relationship flows through memory as well. The C spec for restrict does a better job than the LangRef does in this respect in formalizing that, but our semantics need to allow this too (otherwise our SSA conversation in SROA/mem2reg would not be sound for noalias pointers). In this case, PTR is based on &x, and accesses through it in `sideeffect` are allowed even if x is noalias. One of the things that makes handling noalais pointers more-difficult than one might expect is, specifically, that we do need to check for cases where the restrict pointer itself escapes because then any other pointer of unknown provenance might be based on it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D84860/new/

https://reviews.llvm.org/D84860



More information about the llvm-commits mailing list