diff --git a/lib/Transforms/Utils/CodeExtractor.cpp b/lib/Transforms/Utils/CodeExtractor.cpp index 4e48910b03c..419e1db08bf 100644 --- a/lib/Transforms/Utils/CodeExtractor.cpp +++ b/lib/Transforms/Utils/CodeExtractor.cpp @@ -168,14 +168,22 @@ static bool isBlockValidForExtraction(const BasicBlock &BB, continue; } - if (const CallInst *CI = dyn_cast(I)) - if (const Function *F = CI->getCalledFunction()) - if (F->getIntrinsicID() == Intrinsic::vastart) { + if (const CallInst *CI = dyn_cast(I)) { + if (const Function *F = CI->getCalledFunction()) { + auto IID = F->getIntrinsicID(); + if (IID == Intrinsic::vastart) { if (AllowVarArgs) continue; else return false; } + + // Currently, we miscompile outlined copies of eh_typid_for. There are + // proposals for fixing this in llvm.org/PR39545. + if (IID == Intrinsic::eh_typeid_for) + return false; + } + } } return true; diff --git a/test/Transforms/HotColdSplit/eh-typeid-for.ll b/test/Transforms/HotColdSplit/eh-typeid-for.ll new file mode 100644 index 00000000000..75f9e672332 --- /dev/null +++ b/test/Transforms/HotColdSplit/eh-typeid-for.ll @@ -0,0 +1,26 @@ +; RUN: opt -hotcoldsplit -S < %s | FileCheck %s + +; Do not outline calls to @llvm.eh.typeid.for. See llvm.org/PR39545. + +@_ZTIi = external constant i8* + +; CHECK-LABEL: @fun +; CHECK-NOT: call {{.*}}@fun.cold.1 +define void @fun() { +entry: + br i1 undef, label %if.then, label %if.else + +if.then: + ret void + +if.else: + %t = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) + call void @sink() + call void @sink() + call void @sink() + ret void +} + +declare void @sink() cold + +declare i32 @llvm.eh.typeid.for(i8*)