[llvm] [Inline][WinEH] Fix try scopes leaking to caller on inline (PR #164170)
Eli Friedman via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 22 15:52:40 PDT 2025
================
@@ -2210,6 +2211,147 @@ inlineRetainOrClaimRVCalls(CallBase &CB, objcarc::ARCInstKind RVCallKind,
}
}
+struct SehScope {
+ llvm::InvokeInst *Begin;
+ llvm::InvokeInst *End;
+};
+
+// Determine SEH try scope begins and ends.
+static SmallVector<SehScope, 1> GetSehTryScopes(Function *Func) {
+ SmallVector<SehScope, 1> Scopes{};
+ DenseMap<llvm::BasicBlock *, llvm::InvokeInst *> ScopeEnds{};
+
+ for (auto &BB : *Func) {
+ auto *TI = BB.getTerminator();
+ if (auto *II = dyn_cast<InvokeInst>(TI)) {
+ auto *Call = cast<CallBase>(II);
+ const auto *Fn = Call->getCalledFunction();
+ if (!Fn || !Fn->isIntrinsic())
+ continue;
+
+ if (Fn->getIntrinsicID() == Intrinsic::seh_try_end) {
+ ScopeEnds[II->getUnwindDest()] = II;
+ } else if (Fn->getIntrinsicID() == Intrinsic::seh_try_begin) {
+ Scopes.push_back({II, nullptr});
+ }
+ }
+ }
+
+ // Assign scope end to begin if the unwind destination matches.
+ for (auto &Scope : Scopes) {
+ auto ScopeEndIt = ScopeEnds.find(Scope.Begin->getUnwindDest());
+ if (ScopeEndIt != ScopeEnds.end())
+ Scope.End = ScopeEndIt->second;
+ }
+
+ return Scopes;
+}
+
+// Find, if present, the outermost unterminated try scope for the input block.
+static llvm::InvokeInst *
+GetOutermostUnterminatedTryScopeBegin(llvm::BasicBlock *ReturnBlock,
+ SmallVector<SehScope, 1> &Scopes) {
+ llvm::InvokeInst *OutermostScope{nullptr};
+ DominatorTree DT;
+ DT.recalculate(*ReturnBlock->getParent());
+
+ for (auto &Scope : Scopes) {
----------------
efriedma-quic wrote:
This is still quadratic; it's O(number of ret instructions * number of scopes)
https://github.com/llvm/llvm-project/pull/164170
More information about the llvm-commits
mailing list