Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2176,6 +2176,44 @@ case Intrinsic::experimental_gc_statepoint: { GCStatepointInst &GCSP = *cast(&Call); SmallPtrSet LiveGcValues; + // Utilities to eliminate duplicated gc.relocate instruction. + // If there are two relocation with the same base/derived indexes then + // they are identical and we can use one of them instead of another. + // The one thing we should be careful with is that for invoke statepoint + // there may be two relocations in normal and exceptional paths with the + // same indices and we should keep them separately. + // Return true if the same relocation found and we replaced one by another. + DenseMap, + SmallPtrSet > IdxToRel; + auto CheckRelocationForDuplication = [&](GCRelocateInst *GCR) { + Value *Token = GCR->getArgOperand(0); + auto Key = std::make_tuple(GCR->getBasePtrIndex(), + GCR->getDerivedPtrIndex(), Token); + auto &DupSet = IdxToRel.FindAndConstruct(Key).second; + if (!DupSet.size()) { + DupSet.insert(GCR); + return false; + } + SmallVector ToErase; + for (GCRelocateInst *Dup : DupSet) { + if (DT.dominates(Dup, GCR)) { + assert(!ToErase.size() && + "Two entries with domination relationship found!"); + replaceInstUsesWith(*GCR, Dup); + eraseInstFromFunction(*GCR); + return true; + } + if (DT.dominates(GCR, Dup)) + ToErase.push_back(Dup); + } + for (GCRelocateInst *Dup : ToErase) { + DupSet.erase(Dup); + replaceInstUsesWith(*Dup, GCR); + eraseInstFromFunction(*Dup); + } + DupSet.insert(GCR); + return ToErase.size() != 0; + }; for (const GCRelocateInst *Reloc : GCSP.getGCRelocates()) { GCRelocateInst &GCR = *const_cast(Reloc); @@ -2223,6 +2261,9 @@ GCR.setOperand(2, ConstantInt::get(OpIntTy, GCR.getBasePtrIndex())); } + if (CheckRelocationForDuplication(&GCR)) + continue; + // TODO: bitcast(relocate(p)) -> relocate(bitcast(p)) // Canonicalize on the type from the uses to the defs Index: llvm/test/Transforms/InstCombine/statepoint-cleanup.ll =================================================================== --- llvm/test/Transforms/InstCombine/statepoint-cleanup.ll +++ llvm/test/Transforms/InstCombine/statepoint-cleanup.ll @@ -13,17 +13,9 @@ ; CHECK-NEXT: [[D:%.*]] = getelementptr i32, i32 addrspace(1)* [[B:%.*]], i64 16 ; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* nonnull @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[B]], i32 addrspace(1)* [[D]]) ] ; CHECK-NEXT: [[B_NEW_1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) -; CHECK-NEXT: [[B_NEW_2:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: [[D_NEW_1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 1) -; CHECK-NEXT: [[D_NEW_2:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 1) -; CHECK-NEXT: [[D_NEW_3:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 1) -; CHECK-NEXT: [[D_NEW_4:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 1) ; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[B_NEW_1]], align 4 -; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[B_NEW_2]], align 4 ; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[D_NEW_1]], align 4 -; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[D_NEW_2]], align 4 -; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[D_NEW_3]], align 4 -; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[D_NEW_4]], align 4 ; CHECK-NEXT: ret void ; entry: @@ -95,33 +87,17 @@ ; CHECK-NEXT: to label [[NORMAL_DEST:%.*]] unwind label [[UNWIND_DEST:%.*]] ; CHECK: normal_dest: ; CHECK-NEXT: [[B_NEW_1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) -; CHECK-NEXT: [[B_NEW_2:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: [[D_NEW_1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 1) -; CHECK-NEXT: [[D_NEW_2:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 1) -; CHECK-NEXT: [[D_NEW_3:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 1) -; CHECK-NEXT: [[D_NEW_4:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 1) ; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[B_NEW_1]], align 4 -; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[B_NEW_2]], align 4 ; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[D_NEW_1]], align 4 -; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[D_NEW_2]], align 4 -; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[D_NEW_3]], align 4 -; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[D_NEW_4]], align 4 ; CHECK-NEXT: ret void ; CHECK: unwind_dest: ; CHECK-NEXT: [[LPAD:%.*]] = landingpad token ; CHECK-NEXT: cleanup ; CHECK-NEXT: [[LPB_NEW_1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[LPAD]], i32 0, i32 0) -; CHECK-NEXT: [[LPB_NEW_2:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[LPAD]], i32 0, i32 0) ; CHECK-NEXT: [[LPD_NEW_1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[LPAD]], i32 0, i32 1) -; CHECK-NEXT: [[LPD_NEW_2:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[LPAD]], i32 0, i32 1) -; CHECK-NEXT: [[LPD_NEW_3:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[LPAD]], i32 0, i32 1) -; CHECK-NEXT: [[LPD_NEW_4:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[LPAD]], i32 0, i32 1) ; CHECK-NEXT: store i32 2, i32 addrspace(1)* [[LPB_NEW_1]], align 4 -; CHECK-NEXT: store i32 2, i32 addrspace(1)* [[LPB_NEW_2]], align 4 ; CHECK-NEXT: store i32 2, i32 addrspace(1)* [[LPD_NEW_1]], align 4 -; CHECK-NEXT: store i32 2, i32 addrspace(1)* [[LPD_NEW_2]], align 4 -; CHECK-NEXT: store i32 2, i32 addrspace(1)* [[LPD_NEW_3]], align 4 -; CHECK-NEXT: store i32 2, i32 addrspace(1)* [[LPD_NEW_4]], align 4 ; CHECK-NEXT: ret void ; entry: @@ -251,5 +227,67 @@ ret void } +define void @test_two_independent_same_relocs(i32 addrspace(1)* %b, i1 %c) gc "statepoint-example" { +; +; CHECK-LABEL: @test_two_independent_same_relocs( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* nonnull @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[B:%.*]]) ] +; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] +; CHECK: left: +; CHECK-NEXT: [[B_NEW_1:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) +; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[B_NEW_1]], align 4 +; CHECK-NEXT: ret void +; CHECK: right: +; CHECK-NEXT: [[B_NEW_2:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) +; CHECK-NEXT: store i32 2, i32 addrspace(1)* [[B_NEW_2]], align 4 +; CHECK-NEXT: ret void +; +entry: + %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %b)] + br i1 %c, label %left, label %right + +left: + %b.new.1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) + store i32 1, i32 addrspace(1)* %b.new.1 + ret void + +right: + %b.new.2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) + store i32 2, i32 addrspace(1)* %b.new.2 + ret void +} + +define void @test_three_same_relocs(i32 addrspace(1)* %b, i1 %c) gc "statepoint-example" { +; +; CHECK-LABEL: @test_three_same_relocs( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* nonnull @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[B:%.*]]) ] +; CHECK-NEXT: [[B_NEW:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0) +; CHECK-NEXT: store i32 0, i32 addrspace(1)* [[B_NEW]], align 4 +; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] +; CHECK: left: +; CHECK-NEXT: store i32 1, i32 addrspace(1)* [[B_NEW]], align 4 +; CHECK-NEXT: ret void +; CHECK: right: +; CHECK-NEXT: store i32 2, i32 addrspace(1)* [[B_NEW]], align 4 +; CHECK-NEXT: ret void +; +entry: + %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %b)] + %b.new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) + store i32 0, i32 addrspace(1)* %b.new + br i1 %c, label %left, label %right + +left: + %b.new.1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) + store i32 1, i32 addrspace(1)* %b.new.1 + ret void + +right: + %b.new.2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) + store i32 2, i32 addrspace(1)* %b.new.2 + ret void +} + declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) Index: llvm/test/Transforms/InstCombine/statepoint-iter.ll =================================================================== --- llvm/test/Transforms/InstCombine/statepoint-iter.ll +++ llvm/test/Transforms/InstCombine/statepoint-iter.ll @@ -3,7 +3,8 @@ ; These tests check the optimizations specific to ; pointers being relocated at a statepoint. - +declare void @func_call(i1) +declare void @func_invoke() declare void @func() define i1 @test_null(i1 %cond) gc "statepoint-example" { @@ -69,5 +70,104 @@ ret i32* %pnew2 } +define i8 addrspace(1)* @test_call(i8 addrspace(1)* %x, i8 addrspace(1)* %y, i1 %c1) gc "statepoint-example" personality i32* ()* @fake_personality_function { +; CHECK-LABEL: @test_call( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[C1:%.*]], label [[HERE:%.*]], label [[THERE:%.*]] +; CHECK: here: +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: there: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: [[MERGED_VALUE:%.*]] = phi i8 addrspace(1)* [ [[X:%.*]], [[HERE]] ], [ [[Y:%.*]], [[THERE]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void (i1)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi1f(i64 2882400000, i32 0, void (i1)* nonnull @func_call, i32 1, i32 0, i1 true, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* [[MERGED_VALUE]]), "gc-live"(i8 addrspace(1)* [[MERGED_VALUE]]) ] +; CHECK-NEXT: [[MERGED_VALUE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) +; CHECK-NEXT: [[STATEPOINT_TOKEN1:%.*]] = call token (i64, i32, void (i1)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi1f(i64 2882400000, i32 0, void (i1)* nonnull @func_call, i32 1, i32 0, i1 true, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* [[MERGED_VALUE_RELOCATED]]), "gc-live"(i8 addrspace(1)* [[MERGED_VALUE_RELOCATED]]) ] +; CHECK-NEXT: [[MERGED_VALUE_RELOCATED2:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN1]], i32 0, i32 0) +; CHECK-NEXT: ret i8 addrspace(1)* [[MERGED_VALUE_RELOCATED2]] +; +entry: + br i1 %c1, label %here, label %there + +here: ; preds = %entry + br label %merge + +there: ; preds = %entry + br label %merge + +merge: ; preds = %there, %here + %merged_value.base = phi i8 addrspace(1)* [ %x, %here ], [ %y, %there ] + %merged_value = phi i8 addrspace(1)* [ %x, %here ], [ %y, %there ] + %statepoint_token = call token (i64, i32, void (i1)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi1f(i64 2882400000, i32 0, void (i1)* @func_call, i32 1, i32 0, i1 true, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* %merged_value), "gc-live"(i8 addrspace(1)* %merged_value, i8 addrspace(1)* %merged_value.base) ] + %merged_value.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 1, i32 0) ; (%merged_value.base, %merged_value) + %merged_value.base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 1, i32 1) ; (%merged_value.base, %merged_value.base) + %statepoint_token1 = call token (i64, i32, void (i1)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi1f(i64 2882400000, i32 0, void (i1)* @func_call, i32 1, i32 0, i1 true, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* %merged_value.relocated), "gc-live"(i8 addrspace(1)* %merged_value.relocated, i8 addrspace(1)* %merged_value.base.relocated) ] + %merged_value.relocated2 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token1, i32 1, i32 0) ; (%merged_value.base.relocated, %merged_value.relocated) + %merged_value.base.relocated3 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token1, i32 1, i32 1) ; (%merged_value.base.relocated, %merged_value.base.relocated) + ret i8 addrspace(1)* %merged_value.relocated2 +} + +define i8 addrspace(1)* @test_invoke(i8 addrspace(1)* %x, i8 addrspace(1)* %y, i1 %c1) gc "statepoint-example" personality i32* ()* @fake_personality_function { +; CHECK-LABEL: @test_invoke( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 [[C1:%.*]], label [[HERE:%.*]], label [[THERE:%.*]] +; CHECK: here: +; CHECK-NEXT: br label [[MERGE:%.*]] +; CHECK: there: +; CHECK-NEXT: br label [[MERGE]] +; CHECK: merge: +; CHECK-NEXT: [[MERGED_VALUE:%.*]] = phi i8 addrspace(1)* [ [[X:%.*]], [[HERE]] ], [ [[Y:%.*]], [[THERE]] ] +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* nonnull @func_invoke, i32 0, i32 0, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* [[MERGED_VALUE]]), "gc-live"(i8 addrspace(1)* [[MERGED_VALUE]]) ] +; CHECK-NEXT: to label [[NORMAL_DEST:%.*]] unwind label [[UNWIND_DEST:%.*]] +; CHECK: unwind_dest: +; CHECK-NEXT: [[LPAD:%.*]] = landingpad token +; CHECK-NEXT: cleanup +; CHECK-NEXT: [[MERGED_VALUE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[LPAD]], i32 0, i32 0) +; CHECK-NEXT: [[STATEPOINT_TOKEN3:%.*]] = call token (i64, i32, void (i1)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi1f(i64 2882400000, i32 0, void (i1)* nonnull @func_call, i32 1, i32 0, i1 false, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* [[MERGED_VALUE_RELOCATED]]), "gc-live"(i8 addrspace(1)* [[MERGED_VALUE_RELOCATED]]) ] +; CHECK-NEXT: [[MERGED_VALUE_RELOCATED4:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN3]], i32 0, i32 0) +; CHECK-NEXT: ret i8 addrspace(1)* [[MERGED_VALUE_RELOCATED4]] +; CHECK: normal_dest: +; CHECK-NEXT: [[MERGED_VALUE_RELOCATED1:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) +; CHECK-NEXT: [[STATEPOINT_TOKEN6:%.*]] = call token (i64, i32, void (i1)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi1f(i64 2882400000, i32 0, void (i1)* nonnull @func_call, i32 1, i32 0, i1 true, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* [[MERGED_VALUE_RELOCATED1]]), "gc-live"(i8 addrspace(1)* [[MERGED_VALUE_RELOCATED1]]) ] +; CHECK-NEXT: [[MERGED_VALUE_RELOCATED7:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN6]], i32 0, i32 0) +; CHECK-NEXT: ret i8 addrspace(1)* [[MERGED_VALUE_RELOCATED7]] +; +entry: + br i1 %c1, label %here, label %there + +here: ; preds = %entry + br label %merge + +there: ; preds = %entry + br label %merge + +merge: ; preds = %there, %here + %merged_value.base = phi i8 addrspace(1)* [ %x, %here ], [ %y, %there ] + %merged_value = phi i8 addrspace(1)* [ %x, %here ], [ %y, %there ] + %statepoint_token = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @func_invoke, i32 0, i32 0, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* %merged_value), "gc-live"(i8 addrspace(1)* %merged_value, i8 addrspace(1)* %merged_value.base) ] + to label %normal_dest unwind label %unwind_dest + +unwind_dest: ; preds = %merge + %lpad = landingpad token + cleanup + %merged_value.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %lpad, i32 1, i32 0) ; (%merged_value.base, %merged_value) + %merged_value.base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %lpad, i32 1, i32 1) ; (%merged_value.base, %merged_value.base) + %statepoint_token3 = call token (i64, i32, void (i1)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi1f(i64 2882400000, i32 0, void (i1)* @func_call, i32 1, i32 0, i1 false, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* %merged_value.relocated), "gc-live"(i8 addrspace(1)* %merged_value.relocated, i8 addrspace(1)* %merged_value.base.relocated) ] + %merged_value.relocated4 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token3, i32 1, i32 0) ; (%merged_value.base.relocated, %merged_value.relocated) + %merged_value.base.relocated5 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token3, i32 1, i32 1) ; (%merged_value.base.relocated, %merged_value.base.relocated) + ret i8 addrspace(1)* %merged_value.relocated4 + +normal_dest: ; preds = %merge + %merged_value.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 1, i32 0) ; (%merged_value.base, %merged_value) + %merged_value.base.relocated2 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 1, i32 1) ; (%merged_value.base, %merged_value.base) + %statepoint_token6 = call token (i64, i32, void (i1)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi1f(i64 2882400000, i32 0, void (i1)* @func_call, i32 1, i32 0, i1 true, i32 0, i32 0) [ "deopt"(i8 addrspace(1)* %merged_value.relocated1), "gc-live"(i8 addrspace(1)* %merged_value.relocated1, i8 addrspace(1)* %merged_value.base.relocated2) ] + %merged_value.relocated7 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token6, i32 1, i32 0) ; (%merged_value.base.relocated2, %merged_value.relocated1) + %merged_value.base.relocated8 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token6, i32 1, i32 1) ; (%merged_value.base.relocated2, %merged_value.base.relocated2) + ret i8 addrspace(1)* %merged_value.relocated7 +} + +declare token @llvm.experimental.gc.statepoint.p0f_isVoidi1f(i64, i32, void (i1)*, i32, i32, ...) +declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) declare i32* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) +declare i32* @fake_personality_function()