Index: llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp =================================================================== --- llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -700,14 +700,19 @@ class BDVState { public: enum StatusTy { - // Starting state of lattice - Unknown, - // Some specific base value -- does *not* mean that instruction - // propagates the base of the object - // ex: gep %arg, 16 -> %arg is the base value - Base, - // Need to insert a node to represent a merge. - Conflict + // Starting state of lattice + Unknown, + // The original value is the base itself. + Base, + // Some specific base value -- does *not* mean that instruction + // propagates the base of the object + // ex: gep %arg, 16 -> %arg is the base value + Derived, + // Merging several different base values. + DifferentBases, + // Merging several derived values from different bases. + // Need to insert a node to represent a merge. + Conflict }; BDVState() { @@ -716,8 +721,9 @@ explicit BDVState(Value *OriginalValue) : OriginalValue(OriginalValue) {} - explicit BDVState(Value *OriginalValue, StatusTy Status, Value *BaseValue = nullptr) - : OriginalValue(OriginalValue), Status(Status), BaseValue(BaseValue) { + explicit BDVState(Value *OriginalValue, StatusTy Status, + Value *BaseValue = nullptr) + : OriginalValue(OriginalValue), Status(Status), BaseValue(BaseValue) { assert(Status != Base || BaseValue); } @@ -727,6 +733,9 @@ bool isBase() const { return getStatus() == Base; } bool isUnknown() const { return getStatus() == Unknown; } + bool isDerived() const { return getStatus() == Derived; } + bool isBaseOrDerived() const { return isBase() || isDerived(); } + bool isDifferentBases() const { return getStatus() == DifferentBases; } bool isConflict() const { return getStatus() == Conflict; } // Values of type BDVState form a lattice, and this function implements the @@ -737,6 +746,10 @@ Status = BDVState::Conflict; BaseValue = nullptr; }; + auto markDifferentBases = [&]() { + Status = BDVState::DifferentBases; + BaseValue = nullptr; + }; // Conflict is a final state. if (isConflict()) return; @@ -746,25 +759,32 @@ BaseValue = Other.getBaseValue(); return; } - // We are base. - assert(isBase() && "Unknown state"); + + assert((isBase() || isDerived() || isDifferentBases()) && "Unknown state"); // If other is unknown - just keep our state. if (Other.isUnknown()) return; // If other is conflict - it is a final state. if (Other.isConflict()) return markConflict(); - // Other is base as well. - assert(Other.isBase() && "Unknown state"); - // If bases are different - Conflict. - if (getBaseValue() != Other.getBaseValue()) + if (isBaseOrDerived() && Other.isBaseOrDerived() && + getBaseValue() == Other.getBaseValue()) { + if (Other.isDerived()) + Status = BDVState::Derived; + return; + } + // If merging two values that are not bases themselves, then we are in a + // conflict state. + if (isDerived() || Other.isDerived()) return markConflict(); - // We are identical, do nothing. + assert((Other.isBase() || Other.isDifferentBases()) && "Unknown state"); + // Otherwise we are merging two or more base values. + return markDifferentBases(); } bool operator==(const BDVState &Other) const { - return OriginalValue == Other.OriginalValue && BaseValue == Other.BaseValue && - Status == Other.Status; + return OriginalValue == Other.OriginalValue && + BaseValue == Other.BaseValue && Status == Other.Status; } bool operator!=(const BDVState &other) const { return !(*this == other); } @@ -783,6 +803,12 @@ case Base: OS << "B"; break; + case Derived: + OS << "D"; + break; + case DifferentBases: + OS << "DB"; + break; case Conflict: OS << "C"; break; @@ -795,7 +821,8 @@ private: AssertingVH OriginalValue; // instruction this state corresponds to StatusTy Status = Unknown; - AssertingVH BaseValue = nullptr; // Non-null only if Status == Base. + AssertingVH BaseValue = + nullptr; // Non-null only if Status == Base or Derived. }; } // end anonymous namespace @@ -967,7 +994,10 @@ if (I != States.end()) return I->second; assert(areBothVectorOrScalar(BaseValue, Input)); - return BDVState(BaseValue, BDVState::Base, BaseValue); + BDVState::StatusTy Status = BDVState::Base; + if (Input->stripPointerCasts() != BaseValue) + Status = BDVState::Derived; + return BDVState(BaseValue, Status, BaseValue); }; bool Progress = true; @@ -1000,6 +1030,8 @@ if (OldState != NewState) { Progress = true; States[BDV] = NewState; + LLVM_DEBUG(dbgs() << "New state " << NewState << " for " << *BDV + << "\n"); } } @@ -1028,7 +1060,7 @@ "why did it get added?"); assert(!State.isUnknown() && "Optimistic algorithm didn't complete!"); - if (!State.isBase() || !isa(BaseValue->getType())) + if (!State.isBaseOrDerived() || !isa(BaseValue->getType())) continue; // extractelement instructions are a bit special in that we may need to // insert an extract even when we know an exact base for the instruction. @@ -1236,7 +1268,11 @@ // relation and one of the base pointer relation! FIXME for (auto Pair : States) { auto *BDV = Pair.first; - Value *Base = Pair.second.getBaseValue(); + auto &State = Pair.second; + Value *Base = State.getBaseValue(); + // If the state is merging different bases, then its value is base itself. + if (State.isDifferentBases()) + Base = State.getOriginalValue(); assert(BDV && Base); // Only values that do not have known bases or those that have differing // type (scalar versus vector) from a possible known base should be in the Index: llvm/test/Transforms/RewriteStatepointsForGC/base-pointers-14.ll =================================================================== --- llvm/test/Transforms/RewriteStatepointsForGC/base-pointers-14.ll +++ llvm/test/Transforms/RewriteStatepointsForGC/base-pointers-14.ll @@ -6,8 +6,6 @@ declare void @foo() gc "statepoint-example" -; FIXME: In this test case %b6.base, which is inserted by RS4GC, is identical -; to %b6. define i8 addrspace(1)* @test1(i1 %c, i8 addrspace(1)* %b1, i8 addrspace(1)* %b2) gc "statepoint-example" { ; CHECK-LABEL: @test1( ; CHECK-NEXT: left: @@ -16,11 +14,9 @@ ; CHECK-NEXT: [[B5:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[LEFT:%.*]] ], [ [[B5]], [[LOOP]] ] ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[MERGE2]] ; CHECK: merge2: -; CHECK-NEXT: [[B6_BASE:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B2]], [[LOOP]] ], !is_base_value !0 -; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] -; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]], i8 addrspace(1)* [[B6_BASE]]) ] -; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) -; CHECK-NEXT: [[B6_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) +; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] +; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] ; left: @@ -50,11 +46,9 @@ ; CHECK-NEXT: i32 2, label [[LEFT]] ; CHECK-NEXT: ] ; CHECK: merge2: -; CHECK-NEXT: [[B6_BASE:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B2]], [[LOOP]] ], !is_base_value !0 -; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] -; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]], i8 addrspace(1)* [[B6_BASE]]) ] -; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) -; CHECK-NEXT: [[B6_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) +; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] +; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] ; entry: @@ -82,15 +76,12 @@ ; CHECK-NEXT: left: ; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] ; CHECK: loop: -; CHECK-NEXT: [[B5_BASE:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[LEFT:%.*]] ], [ [[B5_BASE]], [[LOOP]] ], [ [[B6_BASE_RELOCATED:%.*]], [[MERGE2]] ], !is_base_value !0 -; CHECK-NEXT: [[B5:%.*]] = phi i8 addrspace(1)* [ [[B2]], [[LEFT]] ], [ [[B5]], [[LOOP]] ], [ [[B6_RELOCATED:%.*]], [[MERGE2]] ] +; CHECK-NEXT: [[B5:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[LEFT:%.*]] ], [ [[B5]], [[LOOP]] ], [ [[B6_RELOCATED:%.*]], [[MERGE2]] ] ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[MERGE2]] ; CHECK: merge2: -; CHECK-NEXT: [[B6_BASE:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5_BASE]], [[LOOP]] ], !is_base_value !0 -; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] -; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6_BASE]], i8 addrspace(1)* [[B6]]) ] -; CHECK-NEXT: [[B6_BASE_RELOCATED]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) -; CHECK-NEXT: [[B6_RELOCATED]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 1) +; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] +; CHECK-NEXT: [[B6_RELOCATED]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] @@ -121,11 +112,9 @@ ; CHECK-NEXT: [[B5]] = bitcast i32 addrspace(1)* [[B4]] to i8 addrspace(1)* ; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[MERGE2]] ; CHECK: merge2: -; CHECK-NEXT: [[B6_BASE:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B2]], [[LOOP]] ], !is_base_value !0 -; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] -; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]], i8 addrspace(1)* [[B6_BASE]]) ] -; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) -; CHECK-NEXT: [[B6_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) +; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] +; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] ; left: @@ -155,11 +144,9 @@ ; CHECK-NEXT: [[B5]] = addrspacecast i8* [[B4]] to i8 addrspace(1)* ; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[MERGE2]] ; CHECK: merge2: -; CHECK-NEXT: [[B6_BASE:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[ENTRY]] ], [ [[B2]], [[LOOP]] ], [ [[B2]], [[LEFT]] ], !is_base_value !0 -; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B5]], [[LEFT]] ] -; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]], i8 addrspace(1)* [[B6_BASE]]) ] -; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) -; CHECK-NEXT: [[B6_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) +; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B5]], [[LEFT]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] +; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] ; entry: @@ -190,11 +177,9 @@ ; CHECK: left: ; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[MERGE2]] ; CHECK: merge2: -; CHECK-NEXT: [[B6_BASE:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[ENTRY]] ], [ [[B2]], [[LOOP]] ], [ [[B2]], [[LEFT]] ], !is_base_value !0 -; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B3]], [[LEFT]] ] -; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]], i8 addrspace(1)* [[B6_BASE]]) ] -; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) -; CHECK-NEXT: [[B6_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) +; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B3]], [[LEFT]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] +; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] ; entry: @@ -271,11 +256,9 @@ ; CHECK-NEXT: i32 2, label [[LEFT]] ; CHECK-NEXT: ] ; CHECK: merge2: -; CHECK-NEXT: [[B6_BASE:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B2]], [[LOOP]] ], !is_base_value !0 -; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] -; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]], i8 addrspace(1)* [[B6_BASE]]) ] -; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) -; CHECK-NEXT: [[B6_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) +; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] +; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] ; entry: