Index: lib/Transforms/Scalar/PlaceSafepoints.cpp =================================================================== --- lib/Transforms/Scalar/PlaceSafepoints.cpp +++ lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -431,6 +431,13 @@ if (II->getIntrinsicID() == Intrinsic::assume) { continue; } + // llvm.frameescape() intrinsic is not a real call. The intrinsic can + // exist only in the entry block. + // Inserting a statepoint before llvm.frameescape() may split the + // entry block, and push the intrinsic out of the entry block. + if (II->getIntrinsicID() == Intrinsic::frameescape) { + continue; + } } break; } Index: test/CodeGen/X86/statepoint-frameescape.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/statepoint-frameescape.ll @@ -0,0 +1,28 @@ +; RUN: opt %s -S -place-safepoints | FileCheck %s + +declare void @llvm.frameescape(...) + +; Do we insert the entry safepoint after the frameescape intrinsic? +define void @parent() gc "statepoint-example" { +; CHECK-LABEL: @parent +entry: +; CHECK-LABEL: entry + %ptr = alloca i32 +; CHECK-NOT: statepoint + call void (...)* @llvm.frameescape(i32* %ptr) +; CHECK: statepoint + ret void +} + +; This function is inlined when inserting a poll. To avoid recursive +; issues, make sure we don't place safepoints in it. +declare void @do_safepoint() +define void @gc.safepoint_poll() { +; CHECK-LABEL: gc.safepoint_poll +; CHECK-LABEL: entry +; CHECK-NEXT: do_safepoint +; CHECK-NEXT: ret void +entry: + call void @do_safepoint() + ret void +}