[win][x64] Re-use fixed object if multiple catchpads use the same alloca for their catch objects#147849
Merged
dpaoliello merged 1 commit intollvm:mainfrom Jul 14, 2025
Merged
Conversation
…oca for their catch objects
Member
|
@llvm/pr-subscribers-platform-windows @llvm/pr-subscribers-backend-x86 Author: Daniel Paoliello (dpaoliello) ChangesAddresses <#147421 (comment)> for x86 If more than one As a follow up, Clang could be updated to re-use the same Full diff: https://github.com/llvm/llvm-project/pull/147849.diff 2 Files Affected:
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp
index c96d3c15a8823..80b51cc5ab89b 100644
--- a/llvm/lib/Target/X86/X86FrameLowering.cpp
+++ b/llvm/lib/Target/X86/X86FrameLowering.cpp
@@ -4241,7 +4241,7 @@ void X86FrameLowering::adjustFrameForMsvcCxxEh(MachineFunction &MF) const {
for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) {
for (WinEHHandlerType &H : TBME.HandlerArray) {
int FrameIndex = H.CatchObj.FrameIndex;
- if (FrameIndex != INT_MAX) {
+ if ((FrameIndex != INT_MAX) && MFI.getObjectOffset(FrameIndex) == 0) {
// Ensure alignment.
unsigned Align = MFI.getObjectAlign(FrameIndex).value();
MinFixedObjOffset -= std::abs(MinFixedObjOffset) % Align;
diff --git a/llvm/test/CodeGen/WinEH/wineh-reuse-catch-alloca.ll b/llvm/test/CodeGen/WinEH/wineh-reuse-catch-alloca.ll
new file mode 100644
index 0000000000000..2bd004ed7dec5
--- /dev/null
+++ b/llvm/test/CodeGen/WinEH/wineh-reuse-catch-alloca.ll
@@ -0,0 +1,100 @@
+; RUN: llc %s --mtriple=x86_64-pc-windows-msvc -o - | FileCheck %s
+
+; Tests the fixed object layouts when two catchpads re-use the same stack
+; allocation for this catch objects.
+
+; Generated from this C++ code, with modifications to the IR (see comments in
+; IR):
+; https://godbolt.org/z/9qv5Yn68j
+; > clang --target=x86_64-pc-windows-msvc test.cpp
+; ```
+; extern "C" void boom();
+; extern "C" int calls_boom();
+; {
+; try { boom(); }
+; catch (int& i) { return i; }
+; catch (long& l) { return l; }
+; return 0;
+; }
+; ```
+
+; Minimum stack alloc is 64 bytes, so no change there.
+; CHECK-LABEL: calls_boom:
+; CHECK: subq $64, %rsp
+; CHECK: .seh_stackalloc 64
+
+; Both the catch blocks load from the same address.
+; CHECK-LABEL: "?catch$3@?0?calls_boom@4HA":
+; CHECK: movq -8(%rbp), %rax
+; CHECK-LABEL: "?catch$4@?0?calls_boom@4HA":
+; CHECK: movq -8(%rbp), %rax
+
+; There's enough space for the UnwindHelp to be at 48 instead of 40
+; CHECK-LABEL: $cppxdata$calls_boom:
+; CHECK: .long 48 # UnwindHelp
+
+; Both catches have the same object offset.
+; CHECK-LABEL: $handlerMap$0$calls_boom:
+; CHECK: .long 56 # CatchObjOffset
+; CHECK-NEXT: .long "?catch$3@?0?calls_boom@4HA"@IMGREL # Handler
+; CHECK: .long 56 # CatchObjOffset
+; CHECK-NEXT: .long "?catch$4@?0?calls_boom@4HA"@IMGREL # Handler
+
+%rtti.TypeDescriptor2 = type { ptr, ptr, [3 x i8] }
+
+$"??_R0H@8" = comdat any
+
+$"??_R0J@8" = comdat any
+
+@"??_7type_info@@6B@" = external constant ptr
+@"??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { ptr @"??_7type_info@@6B@", ptr null, [3 x i8] c".H\00" }, comdat
+@"??_R0J@8" = linkonce_odr global %rtti.TypeDescriptor2 { ptr @"??_7type_info@@6B@", ptr null, [3 x i8] c".J\00" }, comdat
+
+define dso_local i32 @calls_boom() personality ptr @__CxxFrameHandler3 {
+entry:
+ %retval = alloca i32, align 4
+; MODIFICATION: Remove unusued alloca
+; %l = alloca ptr, align 8
+ %i = alloca ptr, align 8
+ invoke void @boom()
+ to label %invoke.cont unwind label %catch.dispatch
+
+catch.dispatch:
+ %0 = catchswitch within none [label %catch1, label %catch] unwind to caller
+
+catch1:
+ %1 = catchpad within %0 [ptr @"??_R0H@8", i32 8, ptr %i]
+ %2 = load ptr, ptr %i, align 8
+ %3 = load i32, ptr %2, align 4
+ store i32 %3, ptr %retval, align 4
+ catchret from %1 to label %catchret.dest2
+
+catch:
+; MODIFICATION: Use %i instead of %l
+ %4 = catchpad within %0 [ptr @"??_R0J@8", i32 8, ptr %i]
+ %5 = load ptr, ptr %i, align 8
+ %6 = load i32, ptr %5, align 4
+ store i32 %6, ptr %retval, align 4
+ catchret from %4 to label %catchret.dest
+
+invoke.cont:
+ br label %try.cont
+
+catchret.dest:
+ br label %return
+
+catchret.dest2:
+ br label %return
+
+try.cont:
+ store i32 0, ptr %retval, align 4
+ br label %return
+
+return:
+ %7 = load i32, ptr %retval, align 4
+ ret i32 %7
+}
+
+declare dso_local void @boom() #1
+
+declare dso_local i32 @__CxxFrameHandler3(...)
|
Contributor
Author
|
FYI, my plan is to unify the duplicated tests with (or after) #147860 |
dpaoliello
added a commit
that referenced
this pull request
Jul 21, 2025
mahesh-attarde
pushed a commit
to mahesh-attarde/llvm-project
that referenced
this pull request
Jul 28, 2025
…vm#149178) Cleans up debt from llvm#147849 and llvm#147860 I had originally duplicated this test since the WinEH directory wasn't enabled for AArch64, but now that we can run AArch64 tests in that directory, I've unified the tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses #147421 (comment) for x86
If more than one
catchpaduses the sameallocafor their catch objects, then we will allocate more than one object in the fixed area resulting in wasted stack space.As a follow up, Clang could be updated to re-use the same
allocafor all by-reference and by-pointer catch objects.