[RS4GC] Treat inttoptr as base pointer
authorPhilip Reames <listmail@philipreames.com>
Mon, 7 Jun 2021 17:20:45 +0000 (10:20 -0700)
committerPhilip Reames <listmail@philipreames.com>
Mon, 7 Jun 2021 17:27:23 +0000 (10:27 -0700)
This is a modified version of a patch by tolziplohu with a style change, and most importantly, a revised commit message.

inttoptr for a non-integral address space is currently ill defined in the LangRef.  Figuring out exactly what the dynamic semantics of such a cast would be is hard, and not yet settled.  Despite that, we still need to go ahead and implement something in RS4GC for a couple of reasons.

First, as a simple consistency argument.  We're apparently added support for constexpr inttoptrs a while back, and even have tests which exercised them.  Having a lack of constant folding trigger a crash during lowering is non-ideal.

Second, and more fundementally, the optimizer is allowed to insert undefined constructs in unreachable code.  At the same time, we can't assume that dynamically dead code is always pruned before lowering.  As a result, we must assume that inttoptrs can occur (even if completely ill defined) along dead paths.  We need the lowering to not crash.  The stackmaps produced can be garbage (as the assumption is the code is dynamically dead), but the lowering itself can't crash.

Differential Revision: https://reviews.llvm.org/D103492

llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
llvm/test/Transforms/RewriteStatepointsForGC/base-inttoptr.ll [new file with mode: 0644]

index 6590859..53cd90b 100644 (file)
@@ -522,6 +522,14 @@ static BaseDefiningValueResult findBaseDefiningValue(Value *I) {
         ConstantPointerNull::get(cast<PointerType>(I->getType())), true);
   }
 
+  // inttoptrs in an integral address space are currently ill-defined.  We
+  // treat them as defining base pointers here for consistency with the
+  // constant rule above and because we don't really have a better semantic
+  // to give them.  Note that the optimizer is always free to insert undefined
+  // behavior on dynamically dead paths as well.
+  if (isa<IntToPtrInst>(I))
+    return BaseDefiningValueResult(I, true);
+
   if (CastInst *CI = dyn_cast<CastInst>(I)) {
     Value *Def = CI->stripPointerCasts();
     // If stripping pointer casts changes the address space there is an
diff --git a/llvm/test/Transforms/RewriteStatepointsForGC/base-inttoptr.ll b/llvm/test/Transforms/RewriteStatepointsForGC/base-inttoptr.ll
new file mode 100644 (file)
index 0000000..a5ee858
--- /dev/null
@@ -0,0 +1,18 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -rewrite-statepoints-for-gc < %s | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+declare void @foo()
+
+define i8 addrspace(1)* @test(i64 %i) gc "statepoint-example" {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:    [[P:%.*]] = inttoptr i64 [[I:%.*]] to i8 addrspace(1)*
+; CHECK-NEXT:    [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[P]]) ]
+; CHECK-NEXT:    [[P_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0)
+; CHECK-NEXT:    ret i8 addrspace(1)* [[P_RELOCATED]]
+;
+  %p = inttoptr i64 %i to i8 addrspace(1)*
+  call void @foo()
+  ret i8 addrspace(1)* %p
+}