diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -2734,6 +2734,10 @@ // the RET instruction and handled by the FP Stackifier. if (VA.getLocReg() == X86::FP0 || VA.getLocReg() == X86::FP1) { + // When returning a value via an X87 register, report an error if X87 is + // disabled. + if (!Subtarget.hasX87()) + report_fatal_error("x87 register return with x87 disabled"); // If this is a copy from an xmm register to ST(0), use an FPExtend to // change the value to the FP stack register class. if (isScalarFPTypeInSSEReg(VA.getValVT())) @@ -3070,7 +3074,7 @@ if ((VA.getLocReg() == X86::FP0 || VA.getLocReg() == X86::FP1) && isScalarFPTypeInSSEReg(VA.getValVT())) { if (!Subtarget.hasX87()) - report_fatal_error("X87 register return with X87 disabled"); + report_fatal_error("x87 register return with x87 disabled"); CopyVT = MVT::f80; RoundAfterCopy = (CopyVT != VA.getLocVT()); } @@ -3241,6 +3245,9 @@ else ValVT = VA.getValVT(); + if (ValVT == MVT::f80 && !Subtarget.hasX87()) + report_fatal_error("x87 register return with x87 disabled"); + // FIXME: For now, all byval parameter objects are marked mutable. This can be // changed with more analysis. // In case of tail call optimization mark all arguments mutable. Since they diff --git a/llvm/lib/Target/X86/X86InstrFormats.td b/llvm/lib/Target/X86/X86InstrFormats.td --- a/llvm/lib/Target/X86/X86InstrFormats.td +++ b/llvm/lib/Target/X86/X86InstrFormats.td @@ -458,6 +458,7 @@ class FPI o, Format F, dag outs, dag ins, string asm> : I { let Defs = [FPSW]; + let Predicates = [HasX87]; } // FpI_ - Floating Point Pseudo Instruction template. Not Predicated. @@ -465,6 +466,7 @@ : PseudoI { let FPForm = fp; let Defs = [FPSW]; + let Predicates = [HasX87]; } // Templates for instructions that use a 16- or 32-bit segmented address as diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -923,6 +923,7 @@ def HasVAES : Predicate<"Subtarget->hasVAES()">; def NoVLX_Or_NoVAES : Predicate<"!Subtarget->hasVLX() || !Subtarget->hasVAES()">; def HasFXSR : Predicate<"Subtarget->hasFXSR()">; +def HasX87 : Predicate<"Subtarget->hasX87()">; def HasXSAVE : Predicate<"Subtarget->hasXSAVE()">; def HasXSAVEOPT : Predicate<"Subtarget->hasXSAVEOPT()">; def HasXSAVEC : Predicate<"Subtarget->hasXSAVEC()">; diff --git a/llvm/test/CodeGen/X86/nox87-error.ll b/llvm/test/CodeGen/X86/nox87-error.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/nox87-error.ll @@ -0,0 +1,20 @@ +; RUN: not --crash llc < %s -mattr=-x87 -o /dev/null 2>&1 | FileCheck %s --check-prefix NOX87 +; RUN: llc < %s | FileCheck %s + +; NOX87: LLVM ERROR: x87 register return with x87 disabled + +; CHECK-LABEL: f1: +; CHECK: fldt 8(%rsp) +; CHECK-NEXT: fstpt -24(%rsp) +; CHECK-NEXT: retq + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define dso_local void @f1(x86_fp80 %a) #0 { +entry: + %a.addr = alloca x86_fp80, align 16 + store x86_fp80 %a, x86_fp80* %a.addr, align 16 + ret void +} +