Skip to content

Commit f3481f4

Browse files
committed
[X86] Only force FP usage in the presence of pushf/popf on Win64
This ensures that the Windows unwinder will work at every instruction boundary, and allows other targets to read and write flags without setting up a frame pointer. Fixes GH-46875 Differential Revision: https://reviews.llvm.org/D119391
1 parent 0148b58 commit f3481f4

File tree

3 files changed

+51
-31
lines changed

3 files changed

+51
-31
lines changed

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ bool X86FrameLowering::hasFP(const MachineFunction &MF) const {
100100
MF.getInfo<X86MachineFunctionInfo>()->hasPreallocatedCall() ||
101101
MF.callsUnwindInit() || MF.hasEHFunclets() || MF.callsEHReturn() ||
102102
MFI.hasStackMap() || MFI.hasPatchPoint() ||
103-
MFI.hasCopyImplyingStackAdjustment());
103+
(isWin64Prologue(MF) && MFI.hasCopyImplyingStackAdjustment()));
104104
}
105105

106106
static unsigned getSUBriOpcode(bool IsLP64, int64_t Imm) {
@@ -1385,6 +1385,9 @@ bool X86FrameLowering::has128ByteRedZone(const MachineFunction& MF) const {
13851385
return Is64Bit && !IsWin64CC && !Fn.hasFnAttribute(Attribute::NoRedZone);
13861386
}
13871387

1388+
/// Return true if we need to use the restricted Windows x64 prologue and
1389+
/// epilogue code patterns that can be described with WinCFI (.seh_*
1390+
/// directives).
13881391
bool X86FrameLowering::isWin64Prologue(const MachineFunction &MF) const {
13891392
return MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
13901393
}

llvm/test/CodeGen/X86/x86-64-flags-intrinsics.ll

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,54 @@
1-
; RUN: llc -verify-machineinstrs < %s | FileCheck %s
2-
target triple = "x86_64-pc-win32"
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -verify-machineinstrs -mtriple x86_64-linux < %s | FileCheck %s
3+
; RUN: llc -verify-machineinstrs -mtriple x86_64-windows < %s | FileCheck %s --check-prefix=WIN64
34

45
declare i64 @llvm.x86.flags.read.u64()
56
declare void @llvm.x86.flags.write.u64(i64)
67

78
define i64 @read_flags() {
9+
; CHECK-LABEL: read_flags:
10+
; CHECK: # %bb.0: # %entry
11+
; CHECK-NEXT: pushfq
12+
; CHECK-NEXT: popq %rax
13+
; CHECK-NEXT: retq
14+
;
15+
; WIN64-LABEL: read_flags:
16+
; WIN64: # %bb.0: # %entry
17+
; WIN64-NEXT: pushq %rbp
18+
; WIN64-NEXT: .seh_pushreg %rbp
19+
; WIN64-NEXT: movq %rsp, %rbp
20+
; WIN64-NEXT: .seh_setframe %rbp, 0
21+
; WIN64-NEXT: .seh_endprologue
22+
; WIN64-NEXT: pushfq
23+
; WIN64-NEXT: popq %rax
24+
; WIN64-NEXT: popq %rbp
25+
; WIN64-NEXT: retq
26+
; WIN64-NEXT: .seh_endproc
827
entry:
928
%flags = call i64 @llvm.x86.flags.read.u64()
1029
ret i64 %flags
1130
}
1231

13-
; CHECK-LABEL: read_flags:
14-
; CHECK: pushq %rbp
15-
; CHECK: .seh_pushreg %rbp
16-
; CHECK: movq %rsp, %rbp
17-
; CHECK: .seh_setframe %rbp, 0
18-
; CHECK: .seh_endprologue
19-
; CHECK-NEXT: pushfq
20-
; CHECK-NEXT: popq %rax
21-
; CHECK-NEXT: popq %rbp
22-
2332
define void @write_flags(i64 %arg) {
33+
; CHECK-LABEL: write_flags:
34+
; CHECK: # %bb.0: # %entry
35+
; CHECK-NEXT: pushq %rdi
36+
; CHECK-NEXT: popfq
37+
; CHECK-NEXT: retq
38+
;
39+
; WIN64-LABEL: write_flags:
40+
; WIN64: # %bb.0: # %entry
41+
; WIN64-NEXT: pushq %rbp
42+
; WIN64-NEXT: .seh_pushreg %rbp
43+
; WIN64-NEXT: movq %rsp, %rbp
44+
; WIN64-NEXT: .seh_setframe %rbp, 0
45+
; WIN64-NEXT: .seh_endprologue
46+
; WIN64-NEXT: pushq %rcx
47+
; WIN64-NEXT: popfq
48+
; WIN64-NEXT: popq %rbp
49+
; WIN64-NEXT: retq
50+
; WIN64-NEXT: .seh_endproc
2451
entry:
2552
call void @llvm.x86.flags.write.u64(i64 %arg)
2653
ret void
2754
}
28-
29-
; CHECK-LABEL: write_flags:
30-
; CHECK: pushq %rbp
31-
; CHECK: .seh_pushreg %rbp
32-
; CHECK: movq %rsp, %rbp
33-
; CHECK: .seh_setframe %rbp, 0
34-
; CHECK: .seh_endprologue
35-
; CHECK-NEXT: pushq %rcx
36-
; CHECK-NEXT: popfq
37-
; CHECK-NEXT: popq %rbp
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
; RUN: llc -verify-machineinstrs < %s | FileCheck %s
22
target triple = "i686-pc-win32"
33

4+
; Check that pushf/popf intrinsics on win32 don't need a frame pointer.
5+
; FIXME: These can't be autogenerated due to the fastcall function name label,
6+
; it seems.
7+
48
declare i32 @llvm.x86.flags.read.u32()
59
declare void @llvm.x86.flags.write.u32(i32)
610

@@ -11,11 +15,9 @@ entry:
1115
}
1216

1317
; CHECK-LABEL: _read_flags:
14-
; CHECK: pushl %ebp
15-
; CHECK-NEXT: movl %esp, %ebp
16-
; CHECK-NEXT: pushfl
18+
; CHECK: pushfl
1719
; CHECK-NEXT: popl %eax
18-
; CHECK-NEXT: popl %ebp
20+
; CHECK-NEXT: retl
1921

2022
define x86_fastcallcc void @write_flags(i32 inreg %arg) {
2123
entry:
@@ -24,8 +26,6 @@ entry:
2426
}
2527

2628
; CHECK-LABEL: @write_flags@4:
27-
; CHECK: pushl %ebp
28-
; CHECK-NEXT: movl %esp, %ebp
29-
; CHECK-NEXT: pushl %ecx
29+
; CHECK: pushl %ecx
3030
; CHECK-NEXT: popfl
31-
; CHECK-NEXT: popl %ebp
31+
; CHECK-NEXT: retl

0 commit comments

Comments
 (0)