[llvm] 1353f7c - [Inliner] Fix dangling pointer in OriginallyIndirectCalls. (#191242)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 9 11:06:53 PDT 2026
Author: Florian Hahn
Date: 2026-04-09T19:06:48+01:00
New Revision: 1353f7cd548d3534c1e1fd4265bc030209bb4dd2
URL: https://github.com/llvm/llvm-project/commit/1353f7cd548d3534c1e1fd4265bc030209bb4dd2
DIFF: https://github.com/llvm/llvm-project/commit/1353f7cd548d3534c1e1fd4265bc030209bb4dd2.diff
LOG: [Inliner] Fix dangling pointer in OriginallyIndirectCalls. (#191242)
changeToInvokeAndSplitBasicBlock replaces an exising call instruction
with an invoke instruction. This leaves a dangling pointer in
OriginallyIndirectCalls. This means we miss !inline_history metadata on
the invokes replacing the direct calls.
It also cause non-determinism, where the inliner adds !inline_history
entries to unrelated call instructions, if we happen to re-allocate a
new call at the same address as a dangling pointer in the set.
PR: https://github.com/llvm/llvm-project/pull/191242
Added:
llvm/test/Transforms/Inline/inline-history-invoke.ll
Modified:
llvm/lib/Transforms/Utils/InlineFunction.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index 7eef188bbc57a..c398a6ae4f0f9 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -560,6 +560,7 @@ static Value *getUnwindDestToken(Instruction *EHPad,
/// nodes in that block with the values specified in InvokeDestPHIValues.
static BasicBlock *HandleCallsInBlockInlinedThroughInvoke(
BasicBlock *BB, BasicBlock *UnwindEdge,
+ SmallSetVector<const Value *, 4> &OriginallyIndirectCalls,
UnwindDestMemoTy *FuncletUnwindMap = nullptr) {
for (Instruction &I : llvm::make_early_inc_range(*BB)) {
// We only need to check for function calls: inlined invoke
@@ -605,7 +606,10 @@ static BasicBlock *HandleCallsInBlockInlinedThroughInvoke(
#endif // NDEBUG
}
+ bool WasIndirect = OriginallyIndirectCalls.remove(CI);
changeToInvokeAndSplitBasicBlock(CI, UnwindEdge);
+ if (WasIndirect)
+ OriginallyIndirectCalls.insert(BB->getTerminator());
return BB;
}
return nullptr;
@@ -651,7 +655,8 @@ static void HandleInlinedLandingPad(InvokeInst *II, BasicBlock *FirstNewBlock,
BB != E; ++BB) {
if (InlinedCodeInfo.ContainsCalls)
if (BasicBlock *NewBB = HandleCallsInBlockInlinedThroughInvoke(
- &*BB, Invoke.getOuterResumeDest()))
+ &*BB, Invoke.getOuterResumeDest(),
+ InlinedCodeInfo.OriginallyIndirectCalls))
// Update any PHI nodes in the exceptional block to indicate that there
// is now a new entry in them.
Invoke.addIncomingPHIValuesFor(NewBB);
@@ -785,7 +790,8 @@ static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
E = Caller->end();
BB != E; ++BB)
if (BasicBlock *NewBB = HandleCallsInBlockInlinedThroughInvoke(
- &*BB, UnwindDest, &FuncletUnwindMap))
+ &*BB, UnwindDest, InlinedCodeInfo.OriginallyIndirectCalls,
+ &FuncletUnwindMap))
// Update any PHI nodes in the exceptional block to indicate that there
// is now a new entry in them.
UpdatePHINodes(NewBB);
diff --git a/llvm/test/Transforms/Inline/inline-history-invoke.ll b/llvm/test/Transforms/Inline/inline-history-invoke.ll
new file mode 100644
index 0000000000000..1ab0b3f365b53
--- /dev/null
+++ b/llvm/test/Transforms/Inline/inline-history-invoke.ll
@@ -0,0 +1,74 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes='cgscc(inline)' -S %s | FileCheck %s
+;
+declare i32 @__gxx_personality_v0(...)
+declare void @may_throw()
+
+define internal void @callee_with_indirect(ptr %fn) {
+ call void %fn()
+ call void @may_throw()
+ ret void
+}
+
+define void @caller(ptr %fn) personality ptr @__gxx_personality_v0 {
+; CHECK-LABEL: define void @caller(
+; CHECK-SAME: ptr [[FN:%.*]]) personality ptr @__gxx_personality_v0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: invoke void [[FN]]()
+; CHECK-NEXT: to [[DOTNOEXC:label %.*]] unwind label %[[LPAD:.*]], !inline_history [[META0:![0-9]+]]
+; CHECK: [[_NOEXC:.*:]]
+; CHECK-NEXT: invoke void @may_throw()
+; CHECK-NEXT: to label %[[CALLEE_WITH_INDIRECT_EXIT:.*]] unwind label %[[LPAD]]
+; CHECK: [[CALLEE_WITH_INDIRECT_EXIT]]:
+; CHECK-NEXT: br label %[[CONT:.*]]
+; CHECK: [[CONT]]:
+; CHECK-NEXT: ret void
+; CHECK: [[LPAD]]:
+; CHECK-NEXT: [[EX:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: resume { ptr, i32 } [[EX]]
+;
+entry:
+ invoke void @callee_with_indirect(ptr %fn)
+ to label %cont unwind label %lpad
+
+cont:
+ ret void
+
+lpad:
+ %ex = landingpad { ptr, i32 } cleanup
+ resume { ptr, i32 } %ex
+}
+
+define void @caller_ehpad(ptr %fn) personality ptr @__gxx_personality_v0 {
+; CHECK-LABEL: define void @caller_ehpad(
+; CHECK-SAME: ptr [[FN:%.*]]) personality ptr @__gxx_personality_v0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: invoke void [[FN]]()
+; CHECK-NEXT: to [[DOTNOEXC:label %.*]] unwind label %[[CLEANUPBB:.*]], !inline_history [[META0]]
+; CHECK: [[_NOEXC:.*:]]
+; CHECK-NEXT: invoke void @may_throw()
+; CHECK-NEXT: to label %[[CALLEE_WITH_INDIRECT_EXIT:.*]] unwind label %[[CLEANUPBB]]
+; CHECK: [[CALLEE_WITH_INDIRECT_EXIT]]:
+; CHECK-NEXT: br label %[[CONT:.*]]
+; CHECK: [[CONT]]:
+; CHECK-NEXT: ret void
+; CHECK: [[CLEANUPBB]]:
+; CHECK-NEXT: [[PAD:%.*]] = cleanuppad within none []
+; CHECK-NEXT: cleanupret from [[PAD]] unwind to caller
+;
+entry:
+ invoke void @callee_with_indirect(ptr %fn)
+ to label %cont unwind label %cleanupbb
+
+cont:
+ ret void
+
+cleanupbb:
+ %pad = cleanuppad within none []
+ cleanupret from %pad unwind to caller
+}
+
+;.
+; CHECK: [[META0]] = distinct !{null}
+;.
More information about the llvm-commits
mailing list