From 5b5782c20e492e7a3d36778c7bad63050c54ad77 Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Mon, 11 May 2015 18:49:34 +0000 Subject: [PATCH] [RewriteStatepointsForGC] Fix a bug on creating gc_relocate for pointer to vector of pointers Summary: In RewriteStatepointsForGC pass, we create a gc_relocate intrinsic for each relocated pointer, and the gc_relocate has the same type with the pointer. During the creation of gc_relocate intrinsic, llvm requires to mangle its type. However, llvm does not support mangling of all possible types. RewriteStatepointsForGC will hit an assertion failure when it tries to create a gc_relocate for pointer to vector of pointers because mangling for vector of pointers is not supported. This patch changes the way RewriteStatepointsForGC pass creates gc_relocate. For each relocated pointer, we erase the type of pointers and create an unified gc_relocate of type i8 addrspace(1)*. Then a bitcast is inserted to convert the gc_relocate to the correct type. In this way, gc_relocate does not need to deal with different types of pointers and the unsupported type mangling is no longer a problem. This change would also ease further merge when LLVM erases types of pointers and introduces an unified pointer type. Some minor changes are also introduced to gc_relocate related part in InstCombineCalls, CodeGenPrepare, and Verifier accordingly. Patch by Chen Li! Reviewers: reames, AndyAyers, sanjoy Reviewed By: sanjoy Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D9592 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237009 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenPrepare.cpp | 44 ++++++++++++++++++++-- lib/IR/Verifier.cpp | 6 +-- lib/Transforms/InstCombine/InstCombineCalls.cpp | 13 +++++-- lib/Transforms/Scalar/RewriteStatepointsForGC.cpp | 17 +++++++-- .../RewriteStatepointsForGC/base-pointers-11.ll | 4 +- .../RewriteStatepointsForGC/base-pointers.ll | 4 +- .../gc_relocate_creation.ll | 20 ++++++++++ .../RewriteStatepointsForGC/live-vector.ll | 19 +++++++--- .../RewriteStatepointsForGC/liveness-basics.ll | 27 ++++++++----- .../RewriteStatepointsForGC/preprocess.ll | 5 ++- .../relocate_invoke_result.ll | 3 +- .../RewriteStatepointsForGC/relocation.ll | 15 ++++---- 12 files changed, 135 insertions(+), 42 deletions(-) create mode 100644 test/Transforms/RewriteStatepointsForGC/gc_relocate_creation.ll diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp index 49836254356..641316105c0 100644 --- a/lib/CodeGen/CodeGenPrepare.cpp +++ b/lib/CodeGen/CodeGenPrepare.cpp @@ -600,13 +600,51 @@ simplifyRelocatesOffABase(IntrinsicInst *RelocatedBase, // Create a Builder and replace the target callsite with a gep IRBuilder<> Builder(ToReplace); Builder.SetCurrentDebugLocation(ToReplace->getDebugLoc()); + + // If gc_relocate does not match the actual type, cast it to the right type. + // In theory, there must be a bitcast after gc_relocate if the type does not + // match, and we should reuse it to get the derived pointer. But it could be + // cases like this: + // bb1: + // ... + // %g1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(...) + // br label %merge + // + // bb2: + // ... + // %g2 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(...) + // br label %merge + // + // merge: + // %p1 = phi i8 addrspace(1)* [ %g1, %bb1 ], [ %g2, %bb2 ] + // %cast = bitcast i8 addrspace(1)* %p1 in to i32 addrspace(1)* + // + // In this case, we can not find the bitcast any more. So we insert a new bitcast + // no matter there is already one or not. In this way, we can handle all cases, and + // the extra bitcast should be optimized away in later passes. + Instruction *ActualRelocatedBase = RelocatedBase; + if (RelocatedBase->getType() != Base->getType()) { + ActualRelocatedBase = + cast(Builder.CreateBitCast(RelocatedBase, Base->getType())); + ActualRelocatedBase->removeFromParent(); + ActualRelocatedBase->insertAfter(cast(RelocatedBase)); + } Value *Replacement = Builder.CreateGEP( - Derived->getSourceElementType(), RelocatedBase, makeArrayRef(OffsetV)); + Derived->getSourceElementType(), ActualRelocatedBase, makeArrayRef(OffsetV)); Instruction *ReplacementInst = cast(Replacement); ReplacementInst->removeFromParent(); - ReplacementInst->insertAfter(RelocatedBase); + ReplacementInst->insertAfter(ActualRelocatedBase); Replacement->takeName(ToReplace); - ToReplace->replaceAllUsesWith(Replacement); + // If the newly generated derived pointer's type does not match the original derived + // pointer's type, cast the new derived pointer to match it. Same reasoning as above. + Instruction *ActualReplacement = ReplacementInst; + if (ReplacementInst->getType() != ToReplace->getType()) { + ActualReplacement = + cast(Builder.CreateBitCast(ReplacementInst, ToReplace->getType())); + ActualReplacement->removeFromParent(); + ActualReplacement->insertAfter(ReplacementInst); + } + ToReplace->replaceAllUsesWith(ActualReplacement); ToReplace->eraseFromParent(); MadeChange = true; diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 374f8f210be..a5d5829b071 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -3384,10 +3384,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { "'gc parameters' section of the statepoint call", &CI); - // Assert that the result type matches the type of the relocated pointer - GCRelocateOperands Operands(&CI); - Assert(Operands.getDerivedPtr()->getType() == CI.getType(), - "gc.relocate: relocating a pointer shouldn't change its type", &CI); + // gc_relocate does not need to be the same type as the relocated pointer. + // It can casted to the correct type later if it's desired break; } }; diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index cae611f21b2..3b925eda16b 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1202,6 +1202,7 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // preserve relocation semantics. GCRelocateOperands Operands(II); Value *DerivedPtr = Operands.getDerivedPtr(); + auto *GCRelocateType = cast(II->getType()); // Remove the relocation if unused, note that this check is required // to prevent the cases below from looping forever. @@ -1212,14 +1213,18 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // TODO: provide a hook for this in GCStrategy. This is clearly legal for // most practical collectors, but there was discussion in the review thread // about whether it was legal for all possible collectors. - if (isa(DerivedPtr)) - return ReplaceInstUsesWith(*II, DerivedPtr); + if (isa(DerivedPtr)) { + // gc_relocate is uncasted. Use undef of gc_relocate's type to replace it. + return ReplaceInstUsesWith(*II, UndefValue::get(GCRelocateType)); + } // The relocation of null will be null for most any collector. // TODO: provide a hook for this in GCStrategy. There might be some weird // collector this property does not hold for. - if (isa(DerivedPtr)) - return ReplaceInstUsesWith(*II, DerivedPtr); + if (isa(DerivedPtr)) { + // gc_relocate is uncasted. Use null-pointer of gc_relocate's type to replace it. + return ReplaceInstUsesWith(*II, ConstantPointerNull::get(GCRelocateType)); + } // isKnownNonNull -> nonnull attribute if (isKnownNonNull(DerivedPtr)) diff --git a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp index 9cb0748c515..7f33295f828 100644 --- a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -1075,7 +1075,10 @@ static void CreateGCRelocates(ArrayRef liveVariables, // the IR, but removes the need for argument bitcasts which shrinks the IR // greatly and makes it much more readable. SmallVector types; // one per 'any' type - types.push_back(liveVariables[i]->getType()); // result type + // All gc_relocate are set to i8 addrspace(1)* type. This could help avoid + // cases where the actual value's type mangling is not supported by llvm. A + // bitcast is added later to convert gc_relocate to the actual value's type. + types.push_back(Type::getInt8PtrTy(M->getContext(), 1)); Value *gc_relocate_decl = Intrinsic::getDeclaration( M, Intrinsic::experimental_gc_relocate, types); @@ -1342,8 +1345,16 @@ insertRelocationStores(iterator_range gcRelocs, Value *alloca = allocaMap[originalValue]; // Emit store into the related alloca - StoreInst *store = new StoreInst(relocatedValue, alloca); - store->insertAfter(relocatedValue); + // All gc_relocate are i8 addrspace(1)* typed, and it must be bitcasted to + // the correct type according to alloca. + assert(relocatedValue->getNextNode() && "Should always have one since it's not a terminator"); + IRBuilder<> Builder(relocatedValue->getNextNode()); + Value *CastedRelocatedValue = + Builder.CreateBitCast(relocatedValue, cast(alloca)->getAllocatedType(), + relocatedValue->hasName() ? relocatedValue->getName() + ".casted" : ""); + + StoreInst *store = new StoreInst(CastedRelocatedValue, alloca); + store->insertAfter(cast(CastedRelocatedValue)); #ifndef NDEBUG visitedLiveValues.insert(originalValue); diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-11.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-11.ll index 2fc9d42ee1f..11e252f43aa 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-11.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-11.ll @@ -12,11 +12,11 @@ entry: loop: ; preds = %loop, %entry ; CHECK-LABEL: loop: ; CHECK: phi i64 addrspace(1)* -; CHECK-DAG: [ %base_obj.relocated, %loop ] +; CHECK-DAG: [ %base_obj.relocated.casted, %loop ] ; CHECK-DAG: [ %base_obj, %entry ] ; CHECK: %current = phi i64 addrspace(1)* ; CHECK-DAG: [ %obj, %entry ] -; CHECK-DAG: [ %next.relocated, %loop ] +; CHECK-DAG: [ %next.relocated.casted, %loop ] %current = phi i64 addrspace(1)* [ %obj, %entry ], [ %next, %loop ] %next = getelementptr i64, i64 addrspace(1)* %current, i32 1 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers.ll index e88f6dfe152..2652d361ce3 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers.ll @@ -13,7 +13,7 @@ entry: loop: ; CHECK: phi i64 addrspace(1)* -; CHECK-DAG: [ %obj.relocated, %loop ] +; CHECK-DAG: [ %obj.relocated.casted, %loop ] ; CHECK-DAG: [ %obj, %entry ] call void @use_obj(i64 addrspace(1)* %obj) %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) @@ -78,7 +78,7 @@ loop: ; preds = %loop, %entry ; CHECK-DAG: [ %base_obj, %entry ] ; Given the two selects are equivelent, so are their base phis - ideally, ; we'd have commoned these, but that's a missed optimization, not correctness. -; CHECK-DAG: [ [[DISCARD:%base_select.*.relocated]], %loop ] +; CHECK-DAG: [ [[DISCARD:%base_select.*.relocated.casted]], %loop ] ; CHECK-NOT: base_phi2 ; CHECK: next = select ; CHECK: base_select diff --git a/test/Transforms/RewriteStatepointsForGC/gc_relocate_creation.ll b/test/Transforms/RewriteStatepointsForGC/gc_relocate_creation.ll new file mode 100644 index 00000000000..ab57f3113cf --- /dev/null +++ b/test/Transforms/RewriteStatepointsForGC/gc_relocate_creation.ll @@ -0,0 +1,20 @@ +; RUN: opt %s -rewrite-statepoints-for-gc -S 2>&1 | FileCheck %s +; This test is to verify gc.relocate can handle pointer to vector of +; pointers (<2 x i32 addrspace(1)*> addrspace(1)* in this case). +; The old scheme to create a gc.relocate of <2 x i32 addrspace(1)*> addrspace(1)* +; type will fail because llvm does not support mangling vector of pointers. +; The new scheme will create all gc.relocate to i8 addrspace(1)* type and +; then bitcast to the correct type. + +declare void @foo() +declare void @use(...) +declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()*, i32, i32, ...) + +define void @test1(<2 x i32 addrspace(1)*> addrspace(1)* %obj) gc "statepoint-example" { +entry: + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) +; CHECK: %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %safepoint_token, i32 5, i32 5) +; CHECK-NEXT: %obj.relocated.casted = bitcast i8 addrspace(1)* %obj.relocated to <2 x i32 addrspace(1)*> addrspace(1)* + call void (...) @use(<2 x i32 addrspace(1)*> addrspace(1)* %obj) + ret void +} \ No newline at end of file diff --git a/test/Transforms/RewriteStatepointsForGC/live-vector.ll b/test/Transforms/RewriteStatepointsForGC/live-vector.ll index 451368147a6..b827133489b 100644 --- a/test/Transforms/RewriteStatepointsForGC/live-vector.ll +++ b/test/Transforms/RewriteStatepointsForGC/live-vector.ll @@ -7,7 +7,8 @@ define i64 addrspace(1)* @test(i64 addrspace(1)* %obj) gc "statepoint-example" { ; CHECK-LABEL: test ; CHECK: gc.statepoint ; CHECK-NEXT: gc.relocate -; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated.casted entry: %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %obj @@ -20,10 +21,12 @@ define <2 x i64 addrspace(1)*> @test2(<2 x i64 addrspace(1)*> %obj) gc "statepoi ; CHECK-NEXT: extractelement ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast ; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast ; CHECK-NEXT: insertelement ; CHECK-NEXT: insertelement -; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %5 +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %7 entry: %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) ret <2 x i64 addrspace(1)*> %obj @@ -37,10 +40,12 @@ define <2 x i64 addrspace(1)*> @test3(<2 x i64 addrspace(1)*>* %ptr) gc "statepo ; CHECK-NEXT: extractelement ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast ; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast ; CHECK-NEXT: insertelement ; CHECK-NEXT: insertelement -; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %5 +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %7 entry: %obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) @@ -63,19 +68,23 @@ entry: ; CHECK-LABEL: normal_return: ; CHECK: gc.relocate +; CHECK-NEXT: bitcast ; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast ; CHECK-NEXT: insertelement ; CHECK-NEXT: insertelement -; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %6 +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %8 normal_return: ; preds = %entry ret <2 x i64 addrspace(1)*> %obj ; CHECK-LABEL: exceptional_return: ; CHECK: gc.relocate +; CHECK-NEXT: bitcast ; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast ; CHECK-NEXT: insertelement ; CHECK-NEXT: insertelement -; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %10 +; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %14 exceptional_return: ; preds = %entry %landing_pad4 = landingpad { i8*, i32 } personality i32 ()* @fake_personality_function cleanup diff --git a/test/Transforms/RewriteStatepointsForGC/liveness-basics.ll b/test/Transforms/RewriteStatepointsForGC/liveness-basics.ll index 6da6b7c189e..a4b427c7f79 100644 --- a/test/Transforms/RewriteStatepointsForGC/liveness-basics.ll +++ b/test/Transforms/RewriteStatepointsForGC/liveness-basics.ll @@ -13,7 +13,8 @@ entry: taken: ; CHECK-LABEL: taken: ; CHECK-NEXT: gc.statepoint -; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)* +; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)* +; CHECK-NEXT: bitcast ; CHECK-NEXT: br label %merge call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %merge @@ -21,14 +22,15 @@ taken: untaken: ; CHECK-LABEL: untaken: ; CHECK-NEXT: gc.statepoint -; CHECK-NEXT: %obj.relocated1 = call coldcc i64 addrspace(1)* +; CHECK-NEXT: %obj.relocated1 = call coldcc i8 addrspace(1)* +; CHECK-NEXT: bitcast ; CHECK-NEXT: br label %merge call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %merge merge: ; CHECK-LABEL: merge: -; CHECK-NEXT: %.0 = phi i64 addrspace(1)* [ %obj.relocated, %taken ], [ %obj.relocated1, %untaken ] +; CHECK-NEXT: %.0 = phi i64 addrspace(1)* [ %obj.relocated.casted, %taken ], [ %obj.relocated1.casted, %untaken ] ; CHECK-NEXT: ret i64 addrspace(1)* %.0 ret i64 addrspace(1)* %obj } @@ -48,7 +50,8 @@ taken: ; CHECK-NEXT: %obj = load ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: gc.relocate -; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated.casted %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) @@ -70,7 +73,8 @@ taken: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: %obj = load ; CHECK-NEXT: gc.statepoint -; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)* +; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)* +; CHECK-NEXT: bitcast ; CHECK-NEXT: br label %merge call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc @@ -97,13 +101,17 @@ entry: ; CHECK-LABEL: entry: ; CHECK-NEXT: %derived = getelementptr ; CHECK-NEXT: gc.statepoint -; CHECK-NEXT: %derived.relocated = +; CHECK-NEXT: %derived.relocated = +; CHECK-NEXT: bitcast ; CHECK-NEXT: %obj.relocated = +; CHECK-NEXT: bitcast ; CHECK-NEXT: gc.statepoint -; CHECK-NEXT: %derived.relocated1 = +; CHECK-NEXT: %derived.relocated1 = +; CHECK-NEXT: bitcast ; Note: It's legal to relocate obj again, but not strictly needed ; CHECK-NEXT: %obj.relocated2 = -; CHECK-NEXT: ret i64 addrspace(1)* %derived.relocated1 +; CHECK-NEXT: bitcast +; CHECK-NEXT: ret i64 addrspace(1)* %derived.relocated1.casted ; %derived = getelementptr i64, i64 addrspace(1)* %obj, i64 8 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) @@ -125,7 +133,8 @@ entry: taken: ; CHECK-LABEL: taken: ; CHECK-NEXT: gc.statepoint -; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)* +; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)* +; CHECK-NEXT: bitcast ; CHECK-NEXT: br label %merge call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %merge diff --git a/test/Transforms/RewriteStatepointsForGC/preprocess.ll b/test/Transforms/RewriteStatepointsForGC/preprocess.ll index ffdfe5be350..39567b12227 100644 --- a/test/Transforms/RewriteStatepointsForGC/preprocess.ll +++ b/test/Transforms/RewriteStatepointsForGC/preprocess.ll @@ -13,8 +13,9 @@ next: ; CHECK-LABEL: next: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: gc.relocate -; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated) -; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated) +; CHECK-NEXT: bitcast +; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated.casted) +; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated.casted) %obj2 = phi i64 addrspace(1)* [ %obj, %entry ] call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) call void (...) @consume(i64 addrspace(1)* %obj2) diff --git a/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll b/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll index 80579e66050..9afd61db149 100644 --- a/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll +++ b/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll @@ -23,7 +23,8 @@ unwind_dest: normal_dest: ;; CHECK-LABEL: normal_dest: ;; CHECK-NEXT: gc.statepoint -;; CHECK-NEXT: %obj.relocated = call coldcc i64* addrspace(1)* +;; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)* +;; CHECK-NEXT: bitcast %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @gc_call, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i64* addrspace(1)* %obj } diff --git a/test/Transforms/RewriteStatepointsForGC/relocation.ll b/test/Transforms/RewriteStatepointsForGC/relocation.ll index f604885162e..b274c642101 100644 --- a/test/Transforms/RewriteStatepointsForGC/relocation.ll +++ b/test/Transforms/RewriteStatepointsForGC/relocation.ll @@ -14,7 +14,7 @@ entry: joint: ; CHECK-LABEL: joint: -; CHECK: %phi1 = phi i64 addrspace(1)* [ %obj.relocated, %entry ], [ %obj3, %joint2 ] +; CHECK: %phi1 = phi i64 addrspace(1)* [ %obj.relocated.casted, %entry ], [ %obj3, %joint2 ] %phi1 = phi i64 addrspace(1)* [ %obj, %entry ], [ %obj3, %joint2 ] br i1 %condition, label %use, label %joint2 @@ -23,8 +23,8 @@ use: joint2: ; CHECK-LABEL: joint2: -; CHECK: %phi2 = phi i64 addrspace(1)* [ %obj.relocated, %use ], [ %obj2.relocated, %joint ] -; CHECK: %obj3 = getelementptr i64, i64 addrspace(1)* %obj2.relocated, i32 1 +; CHECK: %phi2 = phi i64 addrspace(1)* [ %obj.relocated.casted, %use ], [ %obj2.relocated.casted, %joint ] +; CHECK: %obj3 = getelementptr i64, i64 addrspace(1)* %obj2.relocated.casted, i32 1 %phi2 = phi i64 addrspace(1)* [ %obj, %use ], [ %obj2, %joint ] %obj3 = getelementptr i64, i64 addrspace(1)* %obj2, i32 1 br label %joint @@ -45,9 +45,9 @@ entry: loop: ; CHECK: loop: -; CHECK-DAG: [ %obj_init.relocated, %loop.backedge ] +; CHECK-DAG: [ %obj_init.relocated.casted, %loop.backedge ] ; CHECK-DAG: [ %obj_init, %entry ] -; CHECK-DAG: [ %obj.relocated, %loop.backedge ] +; CHECK-DAG: [ %obj.relocated.casted, %loop.backedge ] ; CHECK-DAG: [ %obj, %entry ] %index = phi i32 [ 0, %entry ], [ %index.inc, %loop.backedge ] ; CHECK-NOT: %location = getelementptr i64, i64 addrspace(1)* %obj, i32 %index @@ -108,6 +108,7 @@ entry: ; CHECK-LABEL: @test3 ; CHECK: gc.statepoint ; CHECK-NEXT: gc.relocate +; CHECK-NEXT: bitcast ; CHECK-NEXT: gc.statepoint %safepoint_token = call i32 (void (i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi64f(void (i64)* undef, i32 1, i32 0, i64 undef, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) %safepoint_token1 = call i32 (i32 (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i32 (i64 addrspace(1)*)* undef, i32 1, i32 0, i64 addrspace(1)* %obj, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) @@ -262,10 +263,10 @@ callbb: join: ; CHECK-LABEL: join: -; CHECK: phi i64 addrspace(1)* [ %obj.relocated, %callbb ], [ %obj, %entry ] +; CHECK: phi i64 addrspace(1)* [ %obj.relocated.casted, %callbb ], [ %obj, %entry ] ; CHECK: phi i64 addrspace(1)* ; CHECK-DAG: [ %obj, %entry ] -; CHECK-DAG: [ %obj2.relocated, %callbb ] +; CHECK-DAG: [ %obj2.relocated.casted, %callbb ] ; This is a phi outside the dominator region of the new defs inserted by ; the safepoint, BUT we can't stop the search here or we miss the second ; phi below. -- 2.11.0