diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4166,6 +4166,7 @@ def mno_x87 : Flag<["-"], "mno-x87">, Group; def m80387 : Flag<["-"], "m80387">, Alias; def mno_80387 : Flag<["-"], "mno-80387">, Alias; +def mno_fp_ret_in_387 : Flag<["-"], "mno-fp-ret-in-387">, Alias; def mmmx : Flag<["-"], "mmmx">, Group; def mno_mmx : Flag<["-"], "mno-mmx">, Group; def m3dnow : Flag<["-"], "m3dnow">, Group; diff --git a/clang/test/Driver/x86-target-features.c b/clang/test/Driver/x86-target-features.c --- a/clang/test/Driver/x86-target-features.c +++ b/clang/test/Driver/x86-target-features.c @@ -2,6 +2,7 @@ // RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-x87 %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-X87 %s // RUN: %clang -target i386-unknown-linux-gnu -march=i386 -m80387 %s -### -o %t.o 2>&1 | FileCheck -check-prefix=X87 %s // RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-80387 %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-X87 %s +// RUN: %clang -target i386-unknown-linux-gnu -march=i386 -mno-fp-ret-in-387 %s -### -o %t.o 2>&1 | FileCheck -check-prefix=NO-X87 %s // X87: "-target-feature" "+x87" // NO-X87: "-target-feature" "-x87" diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td --- a/llvm/lib/Target/X86/X86CallingConv.td +++ b/llvm/lib/Target/X86/X86CallingConv.td @@ -273,7 +273,10 @@ // conv. CCIfInReg>>>, - CCIfType<[f32,f64], CCAssignToReg<[FP0, FP1]>>, + CCIfSubtarget<"hasX87()", + CCIfType<[f32, f64], CCAssignToReg<[FP0, FP1]>>>, + CCIfNotSubtarget<"hasX87()", + CCIfType<[f32], CCAssignToReg<[EAX, EDX, ECX]>>>, CCIfType<[f16], CCAssignToReg<[XMM0,XMM1,XMM2]>>, CCDelegateTo ]>; 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 @@ -2367,6 +2367,11 @@ if (VT == MVT::v3f16 && Subtarget.hasFP16()) return MVT::v8f16; + // We will use more GPRs for f64 and f80 on 32 bits when x87 is disabled. + if ((VT == MVT::f64 || VT == MVT::f80) && !Subtarget.is64Bit() && + !Subtarget.hasX87()) + return MVT::i32; + return TargetLowering::getRegisterTypeForCallingConv(Context, CC, VT); } @@ -2390,6 +2395,15 @@ if (VT == MVT::v3f16 && Subtarget.hasFP16()) return 1; + // We have to split f64 to 2 registers and f80 to 3 registers on 32 bits if + // x87 is disabled. + if (!Subtarget.is64Bit() && !Subtarget.hasX87()) { + if (VT == MVT::f64) + return 2; + if (VT == MVT::f80) + return 3; + } + return TargetLowering::getNumRegistersForCallingConv(Context, CC, VT); } diff --git a/llvm/test/CodeGen/X86/no-ret-in-x87-reg.ll b/llvm/test/CodeGen/X86/no-ret-in-x87-reg.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/no-ret-in-x87-reg.ll @@ -0,0 +1,193 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=i686-- | FileCheck %s -check-prefix=X87 +; RUN: llc < %s -mtriple=i686-- -mattr=-x87 | FileCheck %s -check-prefixes=NOX87,NOSSE-NOX87 +; RUN: llc < %s -mtriple=i686-- -mattr=-x87,-sse2 | FileCheck %s -check-prefixes=NOX87,NOSSE-NOX87 +; RUN: llc < %s -mtriple=i686-- -mattr=-x87,+sse2 | FileCheck %s -check-prefixes=NOX87,SSE-NOX87 + +define float @f1(float %a, float %b) nounwind { +; X87-LABEL: f1: +; X87: # %bb.0: # %entry +; X87-NEXT: flds {{[0-9]+}}(%esp) +; X87-NEXT: retl +; +; NOSSE-NOX87-LABEL: f1: +; NOSSE-NOX87: # %bb.0: # %entry +; NOSSE-NOX87-NEXT: movl {{[0-9]+}}(%esp), %eax +; NOSSE-NOX87-NEXT: retl +; +; SSE-NOX87-LABEL: f1: +; SSE-NOX87: # %bb.0: # %entry +; SSE-NOX87-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero +; SSE-NOX87-NEXT: movd %xmm0, %eax +; SSE-NOX87-NEXT: retl +entry: + ret float %b +} + +define double @f2(double %a, double %b) nounwind { +; X87-LABEL: f2: +; X87: # %bb.0: # %entry +; X87-NEXT: fldl {{[0-9]+}}(%esp) +; X87-NEXT: retl +; +; NOX87-LABEL: f2: +; NOX87: # %bb.0: # %entry +; NOX87-NEXT: movl {{[0-9]+}}(%esp), %eax +; NOX87-NEXT: movl {{[0-9]+}}(%esp), %edx +; NOX87-NEXT: retl +entry: + ret double %b +} + +define x86_fp80 @f3(x86_fp80 %a, x86_fp80 %b) nounwind { +; X87-LABEL: f3: +; X87: # %bb.0: # %entry +; X87-NEXT: fldt {{[0-9]+}}(%esp) +; X87-NEXT: retl +; +; NOX87-LABEL: f3: +; NOX87: # %bb.0: # %entry +; NOX87-NEXT: movl {{[0-9]+}}(%esp), %eax +; NOX87-NEXT: movl {{[0-9]+}}(%esp), %edx +; NOX87-NEXT: movl {{[0-9]+}}(%esp), %ecx +; NOX87-NEXT: retl +entry: + ret x86_fp80 %b +} + +define float @f4(float %a, float %b) nounwind { +; X87-LABEL: f4: +; X87: # %bb.0: # %entry +; X87-NEXT: flds {{[0-9]+}}(%esp) +; X87-NEXT: fadds {{[0-9]+}}(%esp) +; X87-NEXT: retl +; +; NOSSE-NOX87-LABEL: f4: +; NOSSE-NOX87: # %bb.0: # %entry +; NOSSE-NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOSSE-NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOSSE-NOX87-NEXT: calll __addsf3 +; NOSSE-NOX87-NEXT: addl $8, %esp +; NOSSE-NOX87-NEXT: retl +; +; SSE-NOX87-LABEL: f4: +; SSE-NOX87: # %bb.0: # %entry +; SSE-NOX87-NEXT: movss {{.*#+}} xmm0 = mem[0],zero,zero,zero +; SSE-NOX87-NEXT: addss {{[0-9]+}}(%esp), %xmm0 +; SSE-NOX87-NEXT: movd %xmm0, %eax +; SSE-NOX87-NEXT: retl +entry: + %0 = fadd float %a, %b + ret float %0 +} + +define double @f5(double %a, double %b) nounwind { +; X87-LABEL: f5: +; X87: # %bb.0: # %entry +; X87-NEXT: fldl {{[0-9]+}}(%esp) +; X87-NEXT: faddl {{[0-9]+}}(%esp) +; X87-NEXT: retl +; +; NOSSE-NOX87-LABEL: f5: +; NOSSE-NOX87: # %bb.0: # %entry +; NOSSE-NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOSSE-NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOSSE-NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOSSE-NOX87-NEXT: pushl {{[0-9]+}}(%esp) +; NOSSE-NOX87-NEXT: calll __adddf3 +; NOSSE-NOX87-NEXT: addl $16, %esp +; NOSSE-NOX87-NEXT: retl +; +; SSE-NOX87-LABEL: f5: +; SSE-NOX87: # %bb.0: # %entry +; SSE-NOX87-NEXT: pushl %ebp +; SSE-NOX87-NEXT: movl %esp, %ebp +; SSE-NOX87-NEXT: andl $-8, %esp +; SSE-NOX87-NEXT: subl $8, %esp +; SSE-NOX87-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero +; SSE-NOX87-NEXT: addsd 16(%ebp), %xmm0 +; SSE-NOX87-NEXT: movsd %xmm0, (%esp) +; SSE-NOX87-NEXT: movl (%esp), %eax +; SSE-NOX87-NEXT: movl {{[0-9]+}}(%esp), %edx +; SSE-NOX87-NEXT: movl %ebp, %esp +; SSE-NOX87-NEXT: popl %ebp +; SSE-NOX87-NEXT: retl +entry: + %0 = fadd double %a, %b + 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 +; X87-NEXT: fldt {{[0-9]+}}(%esp) +; X87-NEXT: fldt {{[0-9]+}}(%esp) +; X87-NEXT: faddp %st, %st(1) +; X87-NEXT: retl +; +; 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), %ecx +; NOX87-NEXT: movl %ebp, %esp +; NOX87-NEXT: popl %ebp +; NOX87-NEXT: retl +entry: + %0 = fadd x86_fp80 %a, %b + ret x86_fp80 %0 +} + +define {float, float, float} @f7(float %a, float %b) nounwind { +; X87-LABEL: f7: +; X87: # %bb.0: # %entry +; X87-NEXT: movl {{[0-9]+}}(%esp), %eax +; X87-NEXT: flds {{[0-9]+}}(%esp) +; X87-NEXT: flds {{[0-9]+}}(%esp) +; X87-NEXT: fstps 8(%eax) +; X87-NEXT: fsts 4(%eax) +; X87-NEXT: fstps (%eax) +; X87-NEXT: retl $4 +; +; NOSSE-NOX87-LABEL: f7: +; NOSSE-NOX87: # %bb.0: # %entry +; NOSSE-NOX87-NEXT: movl {{[0-9]+}}(%esp), %eax +; NOSSE-NOX87-NEXT: movl {{[0-9]+}}(%esp), %ecx +; NOSSE-NOX87-NEXT: movl %eax, %edx +; NOSSE-NOX87-NEXT: retl +; +; SSE-NOX87-LABEL: f7: +; SSE-NOX87: # %bb.0: # %entry +; SSE-NOX87-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero +; SSE-NOX87-NEXT: movd {{.*#+}} xmm1 = mem[0],zero,zero,zero +; SSE-NOX87-NEXT: movd %xmm0, %eax +; SSE-NOX87-NEXT: movd %xmm0, %edx +; SSE-NOX87-NEXT: movd %xmm1, %ecx +; SSE-NOX87-NEXT: retl +entry: + %0 = insertvalue {float, float, float} undef, float %a, 0 + %1 = insertvalue {float, float, float} %0, float %a, 1 + %2 = insertvalue {float, float, float} %1, float %b, 2 + ret {float, float, float} %2 +}