diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index 51f2ced321bb7..0971a0e33f98b 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -99,7 +99,7 @@ bool X86FrameLowering::hasFP(const MachineFunction &MF) const { MF.getInfo()->hasPreallocatedCall() || MF.callsUnwindInit() || MF.hasEHFunclets() || MF.callsEHReturn() || MFI.hasStackMap() || MFI.hasPatchPoint() || - MFI.hasCopyImplyingStackAdjustment()); + (isWin64Prologue(MF) && MFI.hasCopyImplyingStackAdjustment())); } static unsigned getSUBriOpcode(bool IsLP64, int64_t Imm) { @@ -1289,6 +1289,9 @@ bool X86FrameLowering::has128ByteRedZone(const MachineFunction& MF) const { return Is64Bit && !IsWin64CC && !Fn.hasFnAttribute(Attribute::NoRedZone); } +/// Return true if we need to use the restricted Windows x64 prologue and +/// epilogue code patterns that can be described with WinCFI (.seh_* +/// directives). bool X86FrameLowering::isWin64Prologue(const MachineFunction &MF) const { return MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); } diff --git a/llvm/test/CodeGen/X86/x86-64-flags-intrinsics.ll b/llvm/test/CodeGen/X86/x86-64-flags-intrinsics.ll index 2cc64685552df..5460f36fca670 100644 --- a/llvm/test/CodeGen/X86/x86-64-flags-intrinsics.ll +++ b/llvm/test/CodeGen/X86/x86-64-flags-intrinsics.ll @@ -1,37 +1,54 @@ -; RUN: llc -verify-machineinstrs < %s | FileCheck %s -target triple = "x86_64-pc-win32" +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple x86_64-linux < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -mtriple x86_64-windows < %s | FileCheck %s --check-prefix=WIN64 declare i64 @llvm.x86.flags.read.u64() declare void @llvm.x86.flags.write.u64(i64) define i64 @read_flags() { +; CHECK-LABEL: read_flags: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushfq +; CHECK-NEXT: popq %rax +; CHECK-NEXT: retq +; +; WIN64-LABEL: read_flags: +; WIN64: # %bb.0: # %entry +; WIN64-NEXT: pushq %rbp +; WIN64-NEXT: .seh_pushreg %rbp +; WIN64-NEXT: movq %rsp, %rbp +; WIN64-NEXT: .seh_setframe %rbp, 0 +; WIN64-NEXT: .seh_endprologue +; WIN64-NEXT: pushfq +; WIN64-NEXT: popq %rax +; WIN64-NEXT: popq %rbp +; WIN64-NEXT: retq +; WIN64-NEXT: .seh_endproc entry: %flags = call i64 @llvm.x86.flags.read.u64() ret i64 %flags } -; CHECK-LABEL: read_flags: -; CHECK: pushq %rbp -; CHECK: .seh_pushreg %rbp -; CHECK: movq %rsp, %rbp -; CHECK: .seh_setframe %rbp, 0 -; CHECK: .seh_endprologue -; CHECK-NEXT: pushfq -; CHECK-NEXT: popq %rax -; CHECK-NEXT: popq %rbp - define void @write_flags(i64 %arg) { +; CHECK-LABEL: write_flags: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushq %rdi +; CHECK-NEXT: popfq +; CHECK-NEXT: retq +; +; WIN64-LABEL: write_flags: +; WIN64: # %bb.0: # %entry +; WIN64-NEXT: pushq %rbp +; WIN64-NEXT: .seh_pushreg %rbp +; WIN64-NEXT: movq %rsp, %rbp +; WIN64-NEXT: .seh_setframe %rbp, 0 +; WIN64-NEXT: .seh_endprologue +; WIN64-NEXT: pushq %rcx +; WIN64-NEXT: popfq +; WIN64-NEXT: popq %rbp +; WIN64-NEXT: retq +; WIN64-NEXT: .seh_endproc entry: call void @llvm.x86.flags.write.u64(i64 %arg) ret void } - -; CHECK-LABEL: write_flags: -; CHECK: pushq %rbp -; CHECK: .seh_pushreg %rbp -; CHECK: movq %rsp, %rbp -; CHECK: .seh_setframe %rbp, 0 -; CHECK: .seh_endprologue -; CHECK-NEXT: pushq %rcx -; CHECK-NEXT: popfq -; CHECK-NEXT: popq %rbp diff --git a/llvm/test/CodeGen/X86/x86-flags-intrinsics.ll b/llvm/test/CodeGen/X86/x86-flags-intrinsics.ll index e2233aec22c7c..67cf0ef6e8b8f 100644 --- a/llvm/test/CodeGen/X86/x86-flags-intrinsics.ll +++ b/llvm/test/CodeGen/X86/x86-flags-intrinsics.ll @@ -1,6 +1,10 @@ ; RUN: llc -verify-machineinstrs < %s | FileCheck %s target triple = "i686-pc-win32" +; Check that pushf/popf intrinsics on win32 don't need a frame pointer. +; FIXME: These can't be autogenerated due to the fastcall function name label, +; it seems. + declare i32 @llvm.x86.flags.read.u32() declare void @llvm.x86.flags.write.u32(i32) @@ -11,11 +15,9 @@ entry: } ; CHECK-LABEL: _read_flags: -; CHECK: pushl %ebp -; CHECK-NEXT: movl %esp, %ebp -; CHECK-NEXT: pushfl +; CHECK: pushfl ; CHECK-NEXT: popl %eax -; CHECK-NEXT: popl %ebp +; CHECK-NEXT: retl define x86_fastcallcc void @write_flags(i32 inreg %arg) { entry: @@ -24,8 +26,6 @@ entry: } ; CHECK-LABEL: @write_flags@4: -; CHECK: pushl %ebp -; CHECK-NEXT: movl %esp, %ebp -; CHECK-NEXT: pushl %ecx +; CHECK: pushl %ecx ; CHECK-NEXT: popfl -; CHECK-NEXT: popl %ebp +; CHECK-NEXT: retl