[PATCH] D103492: [RS4GC] Treat inttoptr as base pointer

Sam Dirkswager via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 7 11:26:13 PDT 2021


tolziplohu added a comment.

In D103492#2803236 <https://reviews.llvm.org/D103492#2803236>, @reames wrote:

> When reviewing your https://reviews.llvm.org/D103732 (in particular, the constants.ll test which had inttoptr constant expressions), I realized that this patch is necessary due to unreachable code.  I went ahead and landed a slightly tweaked version of this change.  I believe you should now be able to rebase your  D103732 <https://reviews.llvm.org/D103732> without needing to XFAIL a test.

I tried it, but because `inttoptr` isn't allowed with non-integral pointers and RS4GC doesn't handle `addrspacecast`, both `constants.ll` and `base-inttoptr.ll` can't be rewritten to use non-integral pointers, and both fail with https://reviews.llvm.org/D103732. Actually, with the check for `inttoptr` in the place you have it now, it will never actually trigger with https://reviews.llvm.org/D103732 because it must be behind an `addrspacecast`. Moving the check to inside the `if` but before the address space check would work but I'm not sure if it would have the right semantics; I have another idea below.

> p.s. I think your use case may still be problematic, but let's talk more on that.  Maybe I'm wrong there too.  :)

I actually had another idea which would solve my problems, and also solves the problem above where the tests are failing because `addrspacecast` isn't allowed. If you want we can wait to discuss it through another medium, but otherwise here it is:

You mentioned a "create object from raw memory" operation, and I realized that that operation is enough to implement all these things, and the semantics make sense. You can do whatever you want to construct a raw pointer - inttoptr, constants, allocate from a global slab - and then you call something like `i8 addrspace(1)* @llvm.gc.create_gc_pointer(i8*)`, which is really just an `addrspacecast`. When you call that intrinsic, you promise that either the pointer is valid, or you'll never access memory through it and the GC knows to ignore it. You also promise that you won't use the old raw pointer anymore, and neither will any other code, but in practice that's not necessary if you've pinned the object or have a non-moving collector and the GC doesn't deallocate it. This doesn't prevent the frontend from using the raw pointer after calling the intrinsic, but that would be UB, and the optimizer will never move loads or stores to the raw pointer past the intrinsic because the intrinsic might read or write the memory behind the raw pointer.

Any `inttoptr`s must be behind an `addrspacecast` anyway, and if a "create object from raw memory" operation is allowed at all then casting an integer to a pointer first must be allowed too. It also solves my allocation problem: the allocation block is a raw pointer, because the memory is manually managed. When an object is allocated, the logic is done on the raw pointer and then the final object pointer is converted to a GC pointer, and it starts being "managed", and RS4GC knows that's a base pointer.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D103492



More information about the llvm-commits mailing list