diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp index 1428a09040a34..591be6be092c6 100644 --- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp +++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp @@ -747,6 +747,7 @@ void MergeFunctions::writeThunk(Function *F, Function *G) { NewG = Function::Create(G->getFunctionType(), G->getLinkage(), G->getAddressSpace(), "", G->getParent()); NewG->setComdat(G->getComdat()); + NewG->IsNewDbgInfoFormat = G->IsNewDbgInfoFormat; BB = BasicBlock::Create(F->getContext(), "", NewG); } @@ -874,6 +875,7 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) { F->getAddressSpace(), "", F->getParent()); NewF->copyAttributesFrom(F); NewF->takeName(F); + NewF->IsNewDbgInfoFormat = F->IsNewDbgInfoFormat; // Ensure CFI type metadata is propagated to the new function. copyMetadataIfPresent(F, NewF, "type"); copyMetadataIfPresent(F, NewF, "kcfi_type"); diff --git a/llvm/test/Transforms/MergeFunc/debuginfo-iterators.ll b/llvm/test/Transforms/MergeFunc/debuginfo-iterators.ll new file mode 100644 index 0000000000000..7f259159ce9d3 --- /dev/null +++ b/llvm/test/Transforms/MergeFunc/debuginfo-iterators.ll @@ -0,0 +1,54 @@ +;; Ensure that the MergeFunctions pass creates thunks with the appropriate debug +;; info format set (which would otherwise assert when inlining those thunks). +; RUN: opt -S -passes=mergefunc,inline --try-experimental-debuginfo-iterators < %s | FileCheck %s + +declare void @f1() +declare void @f2() + +define void @f3() { + call void @f1() + call void @f2() + ret void +} + +;; MergeFunctions will replace f4 with a thunk that calls f3. Inlining will +;; inline f3 into that thunk, which would assert if the thunk had the incorrect +;; debug info format. +define void @f4() { + call void @f1() + call void @f2() + ret void +} + +; CHECK-LABEL: define void @f4() { +; CHECK-NEXT: call void @f1() +; CHECK-NEXT: call void @f2() +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +;; Both of these are interposable, so MergeFunctions will create a common thunk +;; that both will call. Inlining will inline that thunk back, which would assert +;; if the thunk had the incorrect debug info format. +define weak void @f5() { + call void @f2() + call void @f1() + ret void +} + +define weak void @f6() { + call void @f2() + call void @f1() + ret void +} + +; CHECK-LABEL: define weak void @f6() { +; CHECK-NEXT: call void @f2() +; CHECK-NEXT: call void @f1() +; CHECK-NEXT: ret void +; CHECK-NEXT: } + +; CHECK-LABEL: define weak void @f5() { +; CHECK-NEXT: call void @f2() +; CHECK-NEXT: call void @f1() +; CHECK-NEXT: ret void +; CHECK-NEXT: }