From 2228d07bc0f14cbd0150ca2c78430f765954a6db Mon Sep 17 00:00:00 2001 From: Andrey Turetskiy Date: Wed, 23 Mar 2016 11:13:54 +0000 Subject: [PATCH] [X86] Introduction of FeatureX87. Add FeatureX87 in X86 backend to be able to define CPUs which doesn't have x87. Differential Revision: http://reviews.llvm.org/D13979 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@264148 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86.td | 155 +++++++++++++++++------------ lib/Target/X86/X86ISelLowering.cpp | 9 +- lib/Target/X86/X86Subtarget.cpp | 1 + lib/Target/X86/X86Subtarget.h | 4 + test/CodeGen/X86/x87.ll | 55 ++++++++++ 5 files changed, 155 insertions(+), 69 deletions(-) create mode 100644 test/CodeGen/X86/x87.ll diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 3d7644d6ec1..962a3dd1441 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -31,6 +31,9 @@ def Mode16Bit : SubtargetFeature<"16bit-mode", "In16BitMode", "true", // X86 Subtarget features //===----------------------------------------------------------------------===// +def FeatureX87 : SubtargetFeature<"x87","HasX87", "true", + "Enable X87 float instructions">; + def FeatureCMOV : SubtargetFeature<"cmov","HasCMov", "true", "Enable conditional move instructions">; @@ -259,37 +262,38 @@ def ProcIntelSLM : SubtargetFeature<"slm", "X86ProcFamily", "IntelSLM", class Proc Features> : ProcessorModel; -def : Proc<"generic", [FeatureSlowUAMem16]>; -def : Proc<"i386", [FeatureSlowUAMem16]>; -def : Proc<"i486", [FeatureSlowUAMem16]>; -def : Proc<"i586", [FeatureSlowUAMem16]>; -def : Proc<"pentium", [FeatureSlowUAMem16]>; -def : Proc<"pentium-mmx", [FeatureSlowUAMem16, FeatureMMX]>; -def : Proc<"i686", [FeatureSlowUAMem16]>; -def : Proc<"pentiumpro", [FeatureSlowUAMem16, FeatureCMOV]>; -def : Proc<"pentium2", [FeatureSlowUAMem16, FeatureMMX, FeatureCMOV, - FeatureFXSR]>; -def : Proc<"pentium3", [FeatureSlowUAMem16, FeatureMMX, FeatureSSE1, - FeatureFXSR]>; -def : Proc<"pentium3m", [FeatureSlowUAMem16, FeatureMMX, FeatureSSE1, - FeatureFXSR, FeatureSlowBTMem]>; -def : Proc<"pentium-m", [FeatureSlowUAMem16, FeatureMMX, FeatureSSE2, - FeatureFXSR, FeatureSlowBTMem]>; -def : Proc<"pentium4", [FeatureSlowUAMem16, FeatureMMX, FeatureSSE2, - FeatureFXSR]>; -def : Proc<"pentium4m", [FeatureSlowUAMem16, FeatureMMX, FeatureSSE2, - FeatureFXSR, FeatureSlowBTMem]>; +def : Proc<"generic", [FeatureX87, FeatureSlowUAMem16]>; +def : Proc<"i386", [FeatureX87, FeatureSlowUAMem16]>; +def : Proc<"i486", [FeatureX87, FeatureSlowUAMem16]>; +def : Proc<"i586", [FeatureX87, FeatureSlowUAMem16]>; +def : Proc<"pentium", [FeatureX87, FeatureSlowUAMem16]>; +def : Proc<"pentium-mmx", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; +def : Proc<"i686", [FeatureX87, FeatureSlowUAMem16]>; +def : Proc<"pentiumpro", [FeatureX87, FeatureSlowUAMem16, FeatureCMOV]>; +def : Proc<"pentium2", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, + FeatureCMOV, FeatureFXSR]>; +def : Proc<"pentium3", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, + FeatureSSE1, FeatureFXSR]>; +def : Proc<"pentium3m", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, + FeatureSSE1, FeatureFXSR, FeatureSlowBTMem]>; +def : Proc<"pentium-m", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, + FeatureSSE2, FeatureFXSR, FeatureSlowBTMem]>; +def : Proc<"pentium4", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, + FeatureSSE2, FeatureFXSR]>; +def : Proc<"pentium4m", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, + FeatureSSE2, FeatureFXSR, FeatureSlowBTMem]>; // Intel Core Duo. def : ProcessorModel<"yonah", SandyBridgeModel, - [FeatureSlowUAMem16, FeatureMMX, FeatureSSE3, FeatureFXSR, - FeatureSlowBTMem]>; + [FeatureX87, FeatureSlowUAMem16, FeatureMMX, FeatureSSE3, + FeatureFXSR, FeatureSlowBTMem]>; // NetBurst. def : Proc<"prescott", - [FeatureSlowUAMem16, FeatureMMX, FeatureSSE3, FeatureFXSR, - FeatureSlowBTMem]>; + [FeatureX87, FeatureSlowUAMem16, FeatureMMX, FeatureSSE3, + FeatureFXSR, FeatureSlowBTMem]>; def : Proc<"nocona", [ + FeatureX87, FeatureSlowUAMem16, FeatureMMX, FeatureSSE3, @@ -300,6 +304,7 @@ def : Proc<"nocona", [ // Intel Core 2 Solo/Duo. def : ProcessorModel<"core2", SandyBridgeModel, [ + FeatureX87, FeatureSlowUAMem16, FeatureMMX, FeatureSSSE3, @@ -309,6 +314,7 @@ def : ProcessorModel<"core2", SandyBridgeModel, [ FeatureLAHFSAHF ]>; def : ProcessorModel<"penryn", SandyBridgeModel, [ + FeatureX87, FeatureSlowUAMem16, FeatureMMX, FeatureSSE41, @@ -321,6 +327,7 @@ def : ProcessorModel<"penryn", SandyBridgeModel, [ // Atom CPUs. class BonnellProc : ProcessorModel; // Pin the generic name to the baseline. class SilvermontProc : ProcessorModel; // Legacy alias. // "Arrandale" along with corei3 and corei5 class NehalemProc : ProcessorModel; // Westmere is a similar machine to nehalem with some additional features. // Westmere is the corei3/i5/i7 path from nehalem to sandybridge class WestmereProc : ProcessorModel; // AMD CPUs. -def : Proc<"k6", [FeatureSlowUAMem16, FeatureMMX]>; -def : Proc<"k6-2", [FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"k6-3", [FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"athlon", [FeatureSlowUAMem16, Feature3DNowA, +def : Proc<"k6", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; +def : Proc<"k6-2", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; +def : Proc<"k6-3", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; +def : Proc<"athlon", [FeatureX87, FeatureSlowUAMem16, Feature3DNowA, FeatureSlowBTMem, FeatureSlowSHLD]>; -def : Proc<"athlon-tbird", [FeatureSlowUAMem16, Feature3DNowA, +def : Proc<"athlon-tbird", [FeatureX87, FeatureSlowUAMem16, Feature3DNowA, FeatureSlowBTMem, FeatureSlowSHLD]>; -def : Proc<"athlon-4", [FeatureSlowUAMem16, FeatureSSE1, Feature3DNowA, - FeatureFXSR, FeatureSlowBTMem, FeatureSlowSHLD]>; -def : Proc<"athlon-xp", [FeatureSlowUAMem16, FeatureSSE1, Feature3DNowA, - FeatureFXSR, FeatureSlowBTMem, FeatureSlowSHLD]>; -def : Proc<"athlon-mp", [FeatureSlowUAMem16, FeatureSSE1, Feature3DNowA, - FeatureFXSR, FeatureSlowBTMem, FeatureSlowSHLD]>; -def : Proc<"k8", [FeatureSlowUAMem16, FeatureSSE2, Feature3DNowA, - FeatureFXSR, Feature64Bit, FeatureSlowBTMem, +def : Proc<"athlon-4", [FeatureX87, FeatureSlowUAMem16, FeatureSSE1, + Feature3DNowA, FeatureFXSR, FeatureSlowBTMem, FeatureSlowSHLD]>; -def : Proc<"opteron", [FeatureSlowUAMem16, FeatureSSE2, Feature3DNowA, - FeatureFXSR, Feature64Bit, FeatureSlowBTMem, +def : Proc<"athlon-xp", [FeatureX87, FeatureSlowUAMem16, FeatureSSE1, + Feature3DNowA, FeatureFXSR, FeatureSlowBTMem, FeatureSlowSHLD]>; -def : Proc<"athlon64", [FeatureSlowUAMem16, FeatureSSE2, Feature3DNowA, - FeatureFXSR, Feature64Bit, FeatureSlowBTMem, +def : Proc<"athlon-mp", [FeatureX87, FeatureSlowUAMem16, FeatureSSE1, + Feature3DNowA, FeatureFXSR, FeatureSlowBTMem, FeatureSlowSHLD]>; -def : Proc<"athlon-fx", [FeatureSlowUAMem16, FeatureSSE2, Feature3DNowA, - FeatureFXSR, Feature64Bit, FeatureSlowBTMem, - FeatureSlowSHLD]>; -def : Proc<"k8-sse3", [FeatureSlowUAMem16, FeatureSSE3, Feature3DNowA, - FeatureFXSR, FeatureCMPXCHG16B, FeatureSlowBTMem, - FeatureSlowSHLD]>; -def : Proc<"opteron-sse3", [FeatureSlowUAMem16, FeatureSSE3, Feature3DNowA, - FeatureFXSR, FeatureCMPXCHG16B, FeatureSlowBTMem, - FeatureSlowSHLD]>; -def : Proc<"athlon64-sse3", [FeatureSlowUAMem16, FeatureSSE3, Feature3DNowA, - FeatureFXSR, FeatureCMPXCHG16B, FeatureSlowBTMem, - FeatureSlowSHLD]>; -def : Proc<"amdfam10", [FeatureSSE4A, Feature3DNowA, FeatureFXSR, - FeatureCMPXCHG16B, FeatureLZCNT, FeaturePOPCNT, - FeatureSlowBTMem, FeatureSlowSHLD, FeatureLAHFSAHF]>; -def : Proc<"barcelona", [FeatureSSE4A, Feature3DNowA, FeatureFXSR, - FeatureCMPXCHG16B, FeatureLZCNT, FeaturePOPCNT, - FeatureSlowBTMem, FeatureSlowSHLD, FeatureLAHFSAHF]>; +def : Proc<"k8", [FeatureX87, FeatureSlowUAMem16, FeatureSSE2, + Feature3DNowA, FeatureFXSR, Feature64Bit, + FeatureSlowBTMem, FeatureSlowSHLD]>; +def : Proc<"opteron", [FeatureX87, FeatureSlowUAMem16, FeatureSSE2, + Feature3DNowA, FeatureFXSR, Feature64Bit, + FeatureSlowBTMem, FeatureSlowSHLD]>; +def : Proc<"athlon64", [FeatureX87, FeatureSlowUAMem16, FeatureSSE2, + Feature3DNowA, FeatureFXSR, Feature64Bit, + FeatureSlowBTMem, FeatureSlowSHLD]>; +def : Proc<"athlon-fx", [FeatureX87, FeatureSlowUAMem16, FeatureSSE2, + Feature3DNowA, FeatureFXSR, Feature64Bit, + FeatureSlowBTMem, FeatureSlowSHLD]>; +def : Proc<"k8-sse3", [FeatureX87, FeatureSlowUAMem16, FeatureSSE3, + Feature3DNowA, FeatureFXSR, FeatureCMPXCHG16B, + FeatureSlowBTMem, FeatureSlowSHLD]>; +def : Proc<"opteron-sse3", [FeatureX87, FeatureSlowUAMem16, FeatureSSE3, + Feature3DNowA, FeatureFXSR, FeatureCMPXCHG16B, + FeatureSlowBTMem, FeatureSlowSHLD]>; +def : Proc<"athlon64-sse3", [FeatureX87, FeatureSlowUAMem16, FeatureSSE3, + Feature3DNowA, FeatureFXSR, FeatureCMPXCHG16B, + FeatureSlowBTMem, FeatureSlowSHLD]>; +def : Proc<"amdfam10", [FeatureX87, FeatureSSE4A, Feature3DNowA, + FeatureFXSR, FeatureCMPXCHG16B, FeatureLZCNT, + FeaturePOPCNT, FeatureSlowBTMem, FeatureSlowSHLD, + FeatureLAHFSAHF]>; +def : Proc<"barcelona", [FeatureX87, FeatureSSE4A, Feature3DNowA, + FeatureFXSR, FeatureCMPXCHG16B, FeatureLZCNT, + FeaturePOPCNT, FeatureSlowBTMem, FeatureSlowSHLD, + FeatureLAHFSAHF]>; // Bobcat def : Proc<"btver1", [ + FeatureX87, FeatureMMX, FeatureSSSE3, FeatureSSE4A, @@ -580,6 +597,7 @@ def : Proc<"btver1", [ // Jaguar def : ProcessorModel<"btver2", BtVer2Model, [ + FeatureX87, FeatureMMX, FeatureAVX, FeatureFXSR, @@ -602,6 +620,7 @@ def : ProcessorModel<"btver2", BtVer2Model, [ // Bulldozer def : Proc<"bdver1", [ + FeatureX87, FeatureXOP, FeatureFMA4, FeatureCMPXCHG16B, @@ -620,6 +639,7 @@ def : Proc<"bdver1", [ ]>; // Piledriver def : Proc<"bdver2", [ + FeatureX87, FeatureXOP, FeatureFMA4, FeatureCMPXCHG16B, @@ -643,6 +663,7 @@ def : Proc<"bdver2", [ // Steamroller def : Proc<"bdver3", [ + FeatureX87, FeatureXOP, FeatureFMA4, FeatureCMPXCHG16B, @@ -668,6 +689,7 @@ def : Proc<"bdver3", [ // Excavator def : Proc<"bdver4", [ + FeatureX87, FeatureMMX, FeatureAVX2, FeatureFXSR, @@ -690,12 +712,13 @@ def : Proc<"bdver4", [ FeatureLAHFSAHF ]>; -def : Proc<"geode", [FeatureSlowUAMem16, Feature3DNowA]>; +def : Proc<"geode", [FeatureX87, FeatureSlowUAMem16, Feature3DNowA]>; -def : Proc<"winchip-c6", [FeatureSlowUAMem16, FeatureMMX]>; -def : Proc<"winchip2", [FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"c3", [FeatureSlowUAMem16, Feature3DNow]>; -def : Proc<"c3-2", [FeatureSlowUAMem16, FeatureMMX, FeatureSSE1, FeatureFXSR]>; +def : Proc<"winchip-c6", [FeatureX87, FeatureSlowUAMem16, FeatureMMX]>; +def : Proc<"winchip2", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; +def : Proc<"c3", [FeatureX87, FeatureSlowUAMem16, Feature3DNow]>; +def : Proc<"c3-2", [FeatureX87, FeatureSlowUAMem16, FeatureMMX, + FeatureSSE1, FeatureFXSR]>; // We also provide a generic 64-bit specific x86 processor model which tries to // be good for modern chips without enabling instruction set encodings past the @@ -708,8 +731,8 @@ def : Proc<"c3-2", [FeatureSlowUAMem16, FeatureMMX, FeatureSSE1, FeatureFXSR]>; // knobs which need to be tuned differently for AMD chips, we might consider // forming a common base for them. def : ProcessorModel<"x86-64", SandyBridgeModel, - [FeatureMMX, FeatureSSE2, FeatureFXSR, Feature64Bit, - FeatureSlowBTMem ]>; + [FeatureX87, FeatureMMX, FeatureSSE2, FeatureFXSR, + Feature64Bit, FeatureSlowBTMem ]>; //===----------------------------------------------------------------------===// // Register File Description diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 9aaf8205b96..c06d78d2042 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -72,6 +72,7 @@ static cl::opt ExperimentalVectorWideningLegalization( X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, const X86Subtarget &STI) : TargetLowering(TM), Subtarget(STI) { + bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87(); X86ScalarSSEf64 = Subtarget.hasSSE2(); X86ScalarSSEf32 = Subtarget.hasSSE1(); MVT PtrVT = MVT::getIntegerVT(8 * TM.getPointerSize()); @@ -561,7 +562,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, // cases we handle. addLegalFPImmediate(APFloat(+0.0)); // xorpd addLegalFPImmediate(APFloat(+0.0f)); // xorps - } else if (!Subtarget.useSoftFloat() && X86ScalarSSEf32) { + } else if (UseX87 && X86ScalarSSEf32) { // Use SSE for f32, x87 for f64. // Set up the FP register classes. addRegisterClass(MVT::f32, &X86::FR32RegClass); @@ -596,7 +597,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::FCOS , MVT::f64, Expand); setOperationAction(ISD::FSINCOS, MVT::f64, Expand); } - } else if (!Subtarget.useSoftFloat()) { + } else if (UseX87) { // f32 and f64 in x87. // Set up the FP register classes. addRegisterClass(MVT::f64, &X86::RFP64RegClass); @@ -630,7 +631,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::FMA, MVT::f32, Expand); // Long double always uses X87, except f128 in MMX. - if (!Subtarget.useSoftFloat()) { + if (UseX87) { if (Subtarget.is64Bit() && Subtarget.hasMMX()) { addRegisterClass(MVT::f128, &X86::FR128RegClass); ValueTypeActions.setTypeAction(MVT::f128, TypeSoftenFloat); @@ -2433,6 +2434,8 @@ X86TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, bool RoundAfterCopy = false; if ((VA.getLocReg() == X86::FP0 || VA.getLocReg() == X86::FP1) && isScalarFPTypeInSSEReg(VA.getValVT())) { + if (!Subtarget.hasX87()) + report_fatal_error("X87 register return with X87 disabled"); CopyVT = MVT::f80; RoundAfterCopy = (CopyVT != VA.getLocVT()); } diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index 6e72a4e4a61..7f4dfe7e4b8 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -239,6 +239,7 @@ void X86Subtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) { void X86Subtarget::initializeEnvironment() { X86SSELevel = NoSSE; X863DNowLevel = NoThreeDNow; + HasX87 = false; HasCMov = false; HasX86_64 = false; HasPOPCNT = false; diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index 47977f6413a..0f40557fa26 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -70,6 +70,9 @@ protected: /// MMX, 3DNow, 3DNow Athlon, or none supported. X863DNowEnum X863DNowLevel; + /// True if the processor supports X87 instructions. + bool HasX87; + /// True if this processor has conditional move instructions /// (generally pentium pro+). bool HasCMov; @@ -370,6 +373,7 @@ public: PICStyles::Style getPICStyle() const { return PICStyle; } void setPICStyle(PICStyles::Style Style) { PICStyle = Style; } + bool hasX87() const { return HasX87; } bool hasCMov() const { return HasCMov; } bool hasSSE1() const { return X86SSELevel >= SSE1; } bool hasSSE2() const { return X86SSELevel >= SSE2; } diff --git a/test/CodeGen/X86/x87.ll b/test/CodeGen/X86/x87.ll new file mode 100644 index 00000000000..683d7b05cf8 --- /dev/null +++ b/test/CodeGen/X86/x87.ll @@ -0,0 +1,55 @@ +; RUN: llc < %s -march=x86 | FileCheck %s -check-prefix=X87 +; RUN: llc < %s -march=x86-64 -mattr=-sse | FileCheck %s -check-prefix=X87 +; RUN: llc < %s -march=x86 -mattr=-x87 | FileCheck %s -check-prefix=NOX87 --implicit-check-not "{{ }}f{{.*}}" +; RUN: llc < %s -march=x86-64 -mattr=-x87,-sse | FileCheck %s -check-prefix=NOX87 --implicit-check-not "{{ }}f{{.*}}" +; RUN: llc < %s -march=x86 -mattr=-x87,+sse | FileCheck %s -check-prefix=NOX87 --implicit-check-not "{{ }}f{{.*}}" +; RUN: llc < %s -march=x86-64 -mattr=-x87,-sse2 | FileCheck %s -check-prefix=NOX87 --implicit-check-not "{{ }}f{{.*}}" + +define void @test(i32 %i, i64 %l, float* %pf, double* %pd, fp128* %pld) nounwind readnone { +; X87-LABEL: test: +; NOX87-LABEL: test: +; X87: fild +; NOX87: __floatunsisf + %tmp = uitofp i32 %i to float + +; X87: fild +; NOX87: __floatdisf + %tmp1 = sitofp i64 %l to float + +; X87: fadd +; NOX87: __addsf3 + %tmp2 = fadd float %tmp, %tmp1 + +; X87: fstp + store float %tmp2, float* %pf + +; X87: fild +; NOX87: __floatunsidf + %tmp3 = uitofp i32 %i to double + +; X87: fild +; NOX87: __floatdidf + %tmp4 = sitofp i64 %l to double + +; X87: fadd +; NOX87: __adddf3 + %tmp5 = fadd double %tmp3, %tmp4 + +; X87: fstp + store double %tmp5, double* %pd + +; X87: __floatsitf +; NOX87: __floatsitf + %tmp6 = sitofp i32 %i to fp128 + +; X87: __floatunditf +; NOX87: __floatunditf + %tmp7 = uitofp i64 %l to fp128 + +; X87: __addtf3 +; NOX87: __addtf3 + %tmp8 = fadd fp128 %tmp6, %tmp7 + store fp128 %tmp8, fp128* %pld + + ret void +}