summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2017-02-16 18:25:37 +0000
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2017-02-16 18:25:37 +0000
commit42f7712e2340e64173d53900cf5b84f956af8cf3 (patch)
tree94ae495f9fcce020ae96e26757fa3349c7d8a15e
parent8e55b685c2969a01a5bd887369d3610d779aa4c8 (diff)
downloadbcm5719-llvm-42f7712e2340e64173d53900cf5b84f956af8cf3.tar.gz
bcm5719-llvm-42f7712e2340e64173d53900cf5b84f956af8cf3.zip
x86 interrupt calling convention: only save xmm registers if the target supports SSE
The existing code always saves the xmm registers for 64-bit targets even if the target doesn't support SSE (which is common for kernels). Thus, the compiler inserts movaps instructions which lead to CPU exceptions when an interrupt handler is invoked. This commit fixes this bug by returning a register set without xmm registers from getCalleeSavedRegs and getCallPreservedMask for such targets. Patch by Philipp Oppermann. Differential Revision: https://reviews.llvm.org/D29959 llvm-svn: 295347
-rw-r--r--llvm/lib/Target/X86/X86CallingConv.td2
-rw-r--r--llvm/lib/Target/X86/X86RegisterInfo.cpp8
-rw-r--r--llvm/test/CodeGen/X86/x86-64-intrcc-nosse.ll19
3 files changed, 27 insertions, 2 deletions
diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td
index cf7bc981b8a..6781d761a1c 100644
--- a/llvm/lib/Target/X86/X86CallingConv.td
+++ b/llvm/lib/Target/X86/X86CallingConv.td
@@ -1074,6 +1074,8 @@ def CSR_32_AllRegs_AVX512 : CalleeSavedRegs<(add CSR_32_AllRegs,
(sequence "K%u", 0, 7))>;
def CSR_64_AllRegs : CalleeSavedRegs<(add CSR_64_MostRegs, RAX)>;
+def CSR_64_AllRegs_NoSSE : CalleeSavedRegs<(add RAX, RBX, RCX, RDX, RSI, RDI, R8, R9,
+ R10, R11, R12, R13, R14, R15, RBP)>;
def CSR_64_AllRegs_AVX : CalleeSavedRegs<(sub (add CSR_64_MostRegs, RAX,
(sequence "YMM%u", 0, 15)),
(sequence "XMM%u", 0, 15))>;
diff --git a/llvm/lib/Target/X86/X86RegisterInfo.cpp b/llvm/lib/Target/X86/X86RegisterInfo.cpp
index 65f438f94b0..9e886e13ac5 100644
--- a/llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ b/llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -337,7 +337,9 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
return CSR_64_AllRegs_AVX512_SaveList;
if (HasAVX)
return CSR_64_AllRegs_AVX_SaveList;
- return CSR_64_AllRegs_SaveList;
+ if (HasSSE)
+ return CSR_64_AllRegs_SaveList;
+ return CSR_64_AllRegs_NoSSE_SaveList;
} else {
if (HasAVX512)
return CSR_32_AllRegs_AVX512_SaveList;
@@ -447,7 +449,9 @@ X86RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
return CSR_64_AllRegs_AVX512_RegMask;
if (HasAVX)
return CSR_64_AllRegs_AVX_RegMask;
- return CSR_64_AllRegs_RegMask;
+ if (HasSSE)
+ return CSR_64_AllRegs_RegMask;
+ return CSR_64_AllRegs_NoSSE_RegMask;
} else {
if (HasAVX512)
return CSR_32_AllRegs_AVX512_RegMask;
diff --git a/llvm/test/CodeGen/X86/x86-64-intrcc-nosse.ll b/llvm/test/CodeGen/X86/x86-64-intrcc-nosse.ll
new file mode 100644
index 00000000000..0bb4e47adf0
--- /dev/null
+++ b/llvm/test/CodeGen/X86/x86-64-intrcc-nosse.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=-sse < %s | FileCheck %s
+
+%struct.interrupt_frame = type { i64, i64, i64, i64, i64 }
+
+@llvm.used = appending global [1 x i8*] [i8* bitcast (void (%struct.interrupt_frame*, i64)* @test_isr_sse_clobbers to i8*)], section "llvm.metadata"
+
+; Clobbered SSE must not be saved when the target doesn't support SSE
+define x86_intrcc void @test_isr_sse_clobbers(%struct.interrupt_frame* %frame, i64 %ecode) {
+ ; CHECK-LABEL: test_isr_sse_clobbers:
+ ; CHECK: # BB#0:
+ ; CHECK-NEXT: cld
+ ; CHECK-NEXT: #APP
+ ; CHECK-NEXT: #NO_APP
+ ; CHECK-NEXT: addq $8, %rsp
+ ; CHECK-NEXT: iretq
+ call void asm sideeffect "", "~{xmm0},~{xmm6}"()
+ ret void
+}
OpenPOWER on IntegriCloud