diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -999,7 +999,7 @@ /// register, this contains one step in the expansion to get to the smaller /// register. For illegal floating point types, this returns the integer type /// to transform to. - EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const { + virtual EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const { return getTypeConversion(Context, VT).second; } diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -722,9 +722,13 @@ } void DAGTypeLegalizer::SetSoftenedFloat(SDValue Op, SDValue Result) { - assert(Result.getValueType() == - TLI.getTypeToTransformTo(*DAG.getContext(), Op.getValueType()) && +#ifndef NDEBUG + EVT VT = Result.getValueType(); + LLVMContext &Ctx = *DAG.getContext(); + assert((VT == EVT::getIntegerVT(Ctx, 80) || + VT == TLI.getTypeToTransformTo(Ctx, Op.getValueType())) && "Invalid type for softened float"); +#endif AnalyzeNewValue(Result); auto &OpIdEntry = SoftenedFloats[getTableId(Op)]; diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp --- a/llvm/lib/CodeGen/TargetLoweringBase.cpp +++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp @@ -1349,6 +1349,15 @@ ValueTypeActions.setTypeAction(MVT::f128, TypeSoftenFloat); } + // Decide how to handle f80. If the target does not have native f80 support, + // expand it to i96 and we will be generating soft float library calls. + if (!isTypeLegal(MVT::f80)) { + NumRegistersForVT[MVT::f80] = 3*NumRegistersForVT[MVT::i32]; + RegisterTypeForVT[MVT::f80] = RegisterTypeForVT[MVT::i32]; + TransformToType[MVT::f80] = MVT::i32; + ValueTypeActions.setTypeAction(MVT::f80, TypeSoftenFloat); + } + // Decide how to handle f64. If the target does not have native f64 support, // expand it to i64 and we will be generating soft float library calls. if (!isTypeLegal(MVT::f64)) { diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -1514,6 +1514,12 @@ Align getPrefLoopAlignment(MachineLoop *ML) const override; + EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const override { + if (VT == MVT::f80) + return EVT::getIntegerVT(Context, 96); + return TargetLoweringBase::getTypeToTransformTo(Context, VT); + } + protected: std::pair findRepresentativeClass(const TargetRegisterInfo *TRI, 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 @@ -21322,7 +21322,7 @@ return DAG.getNode(ISD::SINT_TO_FP, dl, VT, Ext); } - if (VT == MVT::f128) + if (VT == MVT::f128 || !Subtarget.hasX87()) return SDValue(); SDValue ValueToStore = Src; 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 @@ -473,13 +473,15 @@ 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. +// FpI_ - Floating Point Pseudo Instruction template. class FpI_ pattern> : 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 @@ -931,6 +931,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/no-ret-in-x87-reg.ll b/llvm/test/CodeGen/X86/no-ret-in-x87-reg.ll --- a/llvm/test/CodeGen/X86/no-ret-in-x87-reg.ll +++ b/llvm/test/CodeGen/X86/no-ret-in-x87-reg.ll @@ -117,7 +117,6 @@ ret double %0 } -; FIXME: We should not generate x87 instructions when x87 is disabled. define x86_fp80 @f6(x86_fp80 %a, x86_fp80 %b) nounwind { ; X87-LABEL: f6: ; X87: # %bb.0: # %entry @@ -128,31 +127,17 @@ ; ; NOX87-LABEL: f6: ; NOX87: # %bb.0: # %entry -; NOX87-NEXT: pushl %ebp -; NOX87-NEXT: movl %esp, %ebp -; NOX87-NEXT: andl $-8, %esp -; NOX87-NEXT: subl $48, %esp -; NOX87-NEXT: movl 20(%ebp), %eax -; NOX87-NEXT: movl 24(%ebp), %ecx -; NOX87-NEXT: movl %ecx, {{[0-9]+}}(%esp) -; NOX87-NEXT: movl %eax, {{[0-9]+}}(%esp) -; NOX87-NEXT: movl 28(%ebp), %eax -; NOX87-NEXT: movw %ax, {{[0-9]+}}(%esp) -; NOX87-NEXT: movl 8(%ebp), %eax -; NOX87-NEXT: movl 12(%ebp), %ecx -; NOX87-NEXT: movl %ecx, {{[0-9]+}}(%esp) -; NOX87-NEXT: movl %eax, {{[0-9]+}}(%esp) -; NOX87-NEXT: movl 16(%ebp), %eax -; NOX87-NEXT: movw %ax, {{[0-9]+}}(%esp) -; NOX87-NEXT: fldt {{[0-9]+}}(%esp) -; NOX87-NEXT: fldt {{[0-9]+}}(%esp) -; NOX87-NEXT: faddp %st, %st(1) -; NOX87-NEXT: fstpt (%esp) -; NOX87-NEXT: movl (%esp), %eax -; NOX87-NEXT: movl {{[0-9]+}}(%esp), %edx +; NOX87-NEXT: movzwl {{[0-9]+}}(%esp), %eax ; NOX87-NEXT: movzwl {{[0-9]+}}(%esp), %ecx -; NOX87-NEXT: movl %ebp, %esp -; NOX87-NEXT: popl %ebp +; NOX87-NEXT: pushl %ecx +; NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOX87-NEXT: pushl %eax +; NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOX87-NEXT: calll __addxf3 +; NOX87-NEXT: addl $24, %esp +; NOX87-NEXT: movzwl %cx, %ecx ; NOX87-NEXT: retl entry: %0 = fadd x86_fp80 %a, %b @@ -191,3 +176,52 @@ %2 = insertvalue {float, float, float} %1, float %b, 2 ret {float, float, float} %2 } + +define x86_fp80 @f8(i64 %a) nounwind { +; X87-LABEL: f8: +; X87: # %bb.0: # %entry +; X87-NEXT: fildll {{[0-9]+}}(%esp) +; X87-NEXT: retl +; +; NOX87-LABEL: f8: +; NOX87: # %bb.0: # %entry +; NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOX87-NEXT: calll __floatdixf +; NOX87-NEXT: addl $8, %esp +; NOX87-NEXT: movzwl %cx, %ecx +; NOX87-NEXT: retl +entry: + %0 = sitofp i64 %a to x86_fp80 + ret x86_fp80 %0 +} + +define i32 @f9(x86_fp80 %a) nounwind { +; X87-LABEL: f9: +; X87: # %bb.0: # %entry +; X87-NEXT: subl $8, %esp +; X87-NEXT: fldt {{[0-9]+}}(%esp) +; X87-NEXT: fnstcw (%esp) +; X87-NEXT: movzwl (%esp), %eax +; X87-NEXT: orl $3072, %eax # imm = 0xC00 +; X87-NEXT: movw %ax, {{[0-9]+}}(%esp) +; X87-NEXT: fldcw {{[0-9]+}}(%esp) +; X87-NEXT: fistpl {{[0-9]+}}(%esp) +; X87-NEXT: fldcw (%esp) +; X87-NEXT: movl {{[0-9]+}}(%esp), %eax +; X87-NEXT: addl $8, %esp +; X87-NEXT: retl +; +; NOX87-LABEL: f9: +; NOX87: # %bb.0: # %entry +; NOX87-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; NOX87-NEXT: pushl %eax +; NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOX87-NEXT: calll __fixxfsi +; NOX87-NEXT: addl $12, %esp +; NOX87-NEXT: retl +entry: + %0 = fptosi x86_fp80 %a to i32 + ret i32 %0 +}