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

Florian Hahn via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 29 09:46:03 PDT 2020


fhahn added a comment.

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;
  }


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