Skip to content

Commit 597718a

Browse files
committed
Re-land "Avoid emitting unreachable SP adjustments after throw"
This reverts commit 4e0fe03. Re-lands 65b2128. After landing 5ff5ddd to add int3 into trailing unreachable blocks, we can now remove these extra stack adjustments without confusing the Win64 unwinder. See https://llvm.org/45064#c4 or X86AvoidTrailingCall.cpp for a full explanation. Fixes PR45064.
1 parent 8f64b02 commit 597718a

File tree

3 files changed

+67
-13
lines changed

3 files changed

+67
-13
lines changed

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2989,6 +2989,12 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
29892989
I = MBB.erase(I);
29902990
auto InsertPos = skipDebugInstructionsForward(I, MBB.end());
29912991

2992+
// Try to avoid emitting dead SP adjustments if the block end is unreachable,
2993+
// typically because the function is marked noreturn (abort, throw,
2994+
// assert_fail, etc).
2995+
if (isDestroy && blockEndIsUnreachable(MBB, I))
2996+
return I;
2997+
29922998
if (!reserveCallFrame) {
29932999
// If the stack pointer can be changed after prologue, turn the
29943000
// adjcallstackup instruction into a 'sub ESP, <amt>' and the
@@ -3070,13 +3076,7 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
30703076
return I;
30713077
}
30723078

3073-
if (isDestroy && InternalAmt && !blockEndIsUnreachable(MBB, I)) {
3074-
// If we are performing frame pointer elimination and if the callee pops
3075-
// something off the stack pointer, add it back. We do this until we have
3076-
// more advanced stack pointer tracking ability.
3077-
// We are not tracking the stack pointer adjustment by the callee, so make
3078-
// sure we restore the stack pointer immediately after the call, there may
3079-
// be spill code inserted between the CALL and ADJCALLSTACKUP instructions.
3079+
if (InternalAmt) {
30803080
MachineBasicBlock::iterator CI = I;
30813081
MachineBasicBlock::iterator B = MBB.begin();
30823082
while (CI != B && !std::prev(CI)->isCall())

llvm/lib/Target/X86/X86ISelLowering.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4366,12 +4366,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
43664366
else
43674367
NumBytesForCalleeToPop = 0; // Callee pops nothing.
43684368

4369-
if (CLI.DoesNotReturn && !getTargetMachine().Options.TrapUnreachable) {
4370-
// No need to reset the stack after the call if the call doesn't return. To
4371-
// make the MI verify, we'll pretend the callee does it for us.
4372-
NumBytesForCalleeToPop = NumBytes;
4373-
}
4374-
43754369
// Returns a flag for retval copy to use.
43764370
if (!IsSibcall) {
43774371
Chain = DAG.getCALLSEQ_END(Chain,

llvm/test/CodeGen/X86/noreturn-call-win64.ll

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s
22

3+
%struct.MakeCleanup = type { i8 }
4+
%eh.ThrowInfo = type { i32, i32, i32, i32 }
5+
36
; Function Attrs: noinline nounwind optnone uwtable
47
define dso_local i32 @foo() {
58
entry:
@@ -51,3 +54,60 @@ declare dso_local i32 @cond()
5154
declare dso_local void @abort1() noreturn
5255
declare dso_local void @abort2() noreturn
5356
declare dso_local void @abort3() noreturn
57+
58+
define dso_local void @throw_exception() uwtable personality i32 (...)* @__CxxFrameHandler3 {
59+
entry:
60+
%o = alloca %struct.MakeCleanup, align 1
61+
%call = invoke i32 @cond()
62+
to label %invoke.cont unwind label %ehcleanup
63+
64+
invoke.cont: ; preds = %entry
65+
%cmp1 = icmp eq i32 0, %call
66+
br i1 %cmp1, label %if.then, label %if.end
67+
68+
if.then: ; preds = %invoke.cont
69+
invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null)
70+
to label %unreachable unwind label %ehcleanup
71+
72+
if.end: ; preds = %invoke.cont
73+
%call2 = invoke i32 @cond()
74+
to label %invoke.cont1 unwind label %ehcleanup
75+
76+
invoke.cont1: ; preds = %if.end
77+
%cmp2 = icmp eq i32 0, %call2
78+
br i1 %cmp2, label %if.then3, label %if.end4
79+
80+
if.then3: ; preds = %invoke.cont1
81+
invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null)
82+
to label %unreachable unwind label %ehcleanup
83+
84+
if.end4: ; preds = %invoke.cont1
85+
call void @"??1MakeCleanup@@QEAA@XZ"(%struct.MakeCleanup* nonnull %o)
86+
ret void
87+
88+
ehcleanup: ; preds = %if.then3, %if.end, %if.then, %entry
89+
%cp = cleanuppad within none []
90+
call void @"??1MakeCleanup@@QEAA@XZ"(%struct.MakeCleanup* nonnull %o) [ "funclet"(token %cp) ]
91+
cleanupret from %cp unwind to caller
92+
93+
unreachable: ; preds = %if.then3, %if.then
94+
unreachable
95+
}
96+
97+
declare dso_local i32 @__CxxFrameHandler3(...)
98+
declare dso_local void @_CxxThrowException(i8*, %eh.ThrowInfo*)
99+
declare dso_local void @"??1MakeCleanup@@QEAA@XZ"(%struct.MakeCleanup*)
100+
101+
; CHECK-LABEL: throw_exception:
102+
; CHECK: callq cond
103+
; CHECK: je
104+
; CHECK: callq cond
105+
; CHECK: je
106+
; CHECK: retq
107+
; CHECK: callq _CxxThrowException
108+
; CHECK-NOT: {{(addq|subq) .*, %rsp}}
109+
; CHECK: callq _CxxThrowException
110+
; CHECK-NOT: {{(addq|subq) .*, %rsp}}
111+
; CHECK: # %unreachable
112+
; CHECK: int3
113+
; CHECK: .seh_handlerdata

0 commit comments

Comments
 (0)