diff options
| -rw-r--r-- | llvm/lib/Target/X86/X86VZeroUpper.cpp | 11 | ||||
| -rw-r--r-- | llvm/test/CodeGen/X86/x86-interrupt_vzeroupper.ll | 19 |
2 files changed, 27 insertions, 3 deletions
diff --git a/llvm/lib/Target/X86/X86VZeroUpper.cpp b/llvm/lib/Target/X86/X86VZeroUpper.cpp index cd822b08361..172f8665fad 100644 --- a/llvm/lib/Target/X86/X86VZeroUpper.cpp +++ b/llvm/lib/Target/X86/X86VZeroUpper.cpp @@ -80,6 +80,7 @@ namespace { BlockStateMap BlockStates; DirtySuccessorsWorkList DirtySuccessors; bool EverMadeChange; + bool IsX86INTR; const TargetInstrInfo *TII; static char ID; @@ -181,10 +182,13 @@ void VZeroUpperInserter::processBasicBlock(MachineBasicBlock &MBB) { for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) { MachineInstr *MI = I; - bool isControlFlow = MI->isCall() || MI->isReturn(); + // No need for vzeroupper before iret in interrupt handler function, + // epilogue will restore YMM registers if needed. + bool IsReturnFromX86INTR = IsX86INTR && MI->isReturn(); + bool IsControlFlow = MI->isCall() || MI->isReturn(); // Shortcut: don't need to check regular instructions in dirty state. - if (!isControlFlow && CurState == EXITS_DIRTY) + if ((!IsControlFlow || IsReturnFromX86INTR) && CurState == EXITS_DIRTY) continue; if (hasYmmReg(MI)) { @@ -196,7 +200,7 @@ void VZeroUpperInserter::processBasicBlock(MachineBasicBlock &MBB) { // Check for control-flow out of the current function (which might // indirectly execute SSE instructions). - if (!isControlFlow) + if (!IsControlFlow || IsReturnFromX86INTR) continue; // If the call won't clobber any YMM register, skip it as well. It usually @@ -253,6 +257,7 @@ bool VZeroUpperInserter::runOnMachineFunction(MachineFunction &MF) { TII = ST.getInstrInfo(); MachineRegisterInfo &MRI = MF.getRegInfo(); EverMadeChange = false; + IsX86INTR = MF.getFunction()->getCallingConv() == CallingConv::X86_INTR; bool FnHasLiveInYmm = checkFnHasLiveInYmm(MRI); diff --git a/llvm/test/CodeGen/X86/x86-interrupt_vzeroupper.ll b/llvm/test/CodeGen/X86/x86-interrupt_vzeroupper.ll new file mode 100644 index 00000000000..ab9f168d972 --- /dev/null +++ b/llvm/test/CodeGen/X86/x86-interrupt_vzeroupper.ll @@ -0,0 +1,19 @@ +; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+avx < %s | FileCheck %s + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Checks that interrupt handler code does not call "vzeroupper" instruction +;; before iret. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +; CHECK: vzeroupper +; CHECK-NEXT: call +; CHECK-NOT: vzeroupper +; CHECK: iret + +define x86_intrcc void @foo(i8* %frame) { + call void @bar() + ret void +} + +declare void @bar() + |

