diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 4106be4c81ce..ea0873f41ebb 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -295,6 +295,11 @@ private: getNeutralElementForVecReduce(unsigned Opcode, MachineIRBuilder &MIRBuilder, LLT Ty); + LegalizeResult emitSincosLibcall(MachineInstr &MI, + MachineIRBuilder &MIRBuilder, unsigned Size, + Type *OpType, + LostDebugLocObserver &LocObserver); + public: /// Return the alignment to use for a stack temporary object with the given /// type. diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 5f5af5cad778..461fc35337ea 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -469,6 +469,8 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) { RTLIBCASE(COSH_F); case TargetOpcode::G_FTANH: RTLIBCASE(TANH_F); + case TargetOpcode::G_FSINCOS: + RTLIBCASE(SINCOS_F); case TargetOpcode::G_FLOG10: RTLIBCASE(LOG10_F); case TargetOpcode::G_FLOG: @@ -648,6 +650,54 @@ simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, LocObserver, &MI); } +LegalizerHelper::LegalizeResult LegalizerHelper::emitSincosLibcall( + MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType, + LostDebugLocObserver &LocObserver) { + MachineFunction &MF = *MI.getMF(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + + Register DstSin = MI.getOperand(0).getReg(); + Register DstCos = MI.getOperand(1).getReg(); + Register Src = MI.getOperand(2).getReg(); + LLT DstTy = MRI.getType(DstSin); + + int MemSize = DstTy.getSizeInBytes(); + Align Alignment = getStackTemporaryAlignment(DstTy); + const DataLayout &DL = MIRBuilder.getDataLayout(); + unsigned AddrSpace = DL.getAllocaAddrSpace(); + MachinePointerInfo PtrInfo; + + Register StackPtrSin = + createStackTemporary(TypeSize::getFixed(MemSize), Alignment, PtrInfo) + .getReg(0); + Register StackPtrCos = + createStackTemporary(TypeSize::getFixed(MemSize), Alignment, PtrInfo) + .getReg(0); + + auto &Ctx = MF.getFunction().getContext(); + auto LibcallResult = + createLibcall(MIRBuilder, getRTLibDesc(MI.getOpcode(), Size), + {{0}, Type::getVoidTy(Ctx), 0}, + {{Src, OpType, 0}, + {StackPtrSin, PointerType::get(Ctx, AddrSpace), 1}, + {StackPtrCos, PointerType::get(Ctx, AddrSpace), 2}}, + LocObserver, &MI); + + if (LibcallResult != LegalizeResult::Legalized) + return LegalizerHelper::UnableToLegalize; + + MachineMemOperand *LoadMMOSin = MF.getMachineMemOperand( + PtrInfo, MachineMemOperand::MOLoad, MemSize, Alignment); + MachineMemOperand *LoadMMOCos = MF.getMachineMemOperand( + PtrInfo, MachineMemOperand::MOLoad, MemSize, Alignment); + + MIRBuilder.buildLoad(DstSin, StackPtrSin, *LoadMMOSin); + MIRBuilder.buildLoad(DstCos, StackPtrCos, *LoadMMOCos); + MI.eraseFromParent(); + + return LegalizerHelper::Legalized; +} + LegalizerHelper::LegalizeResult llvm::createMemLibcall(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, MachineInstr &MI, LostDebugLocObserver &LocObserver) { @@ -1275,6 +1325,16 @@ LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) { return Status; break; } + case TargetOpcode::G_FSINCOS: { + LLT LLTy = MRI.getType(MI.getOperand(0).getReg()); + unsigned Size = LLTy.getSizeInBits(); + Type *HLTy = getFloatTypeForLLT(Ctx, LLTy); + if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) { + LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n"); + return UnableToLegalize; + } + return emitSincosLibcall(MI, MIRBuilder, Size, HLTy, LocObserver); + } case TargetOpcode::G_LROUND: case TargetOpcode::G_LLROUND: case TargetOpcode::G_INTRINSIC_LRINT: diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp index f21a7c81459f..7a3650f0c589 100644 --- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp @@ -97,10 +97,10 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, .widenScalarToNextPow2(0, /*Min=*/8) .clampScalar(0, s8, sMaxScalar); - getActionDefinitionsBuilder({G_LROUND, G_LLROUND, G_FCOS, G_FCOSH, G_FACOS, - G_FSIN, G_FSINH, G_FASIN, G_FTAN, G_FTANH, - G_FATAN, G_FATAN2, G_FPOW, G_FEXP, G_FEXP2, - G_FEXP10, G_FLOG, G_FLOG2, G_FLOG10, G_FPOWI}) + getActionDefinitionsBuilder( + {G_LROUND, G_LLROUND, G_FCOS, G_FCOSH, G_FACOS, G_FSIN, G_FSINH, + G_FASIN, G_FTAN, G_FTANH, G_FATAN, G_FATAN2, G_FPOW, G_FEXP, + G_FEXP2, G_FEXP10, G_FLOG, G_FLOG2, G_FLOG10, G_FPOWI, G_FSINCOS}) .libcall(); getActionDefinitionsBuilder(G_FSQRT) diff --git a/llvm/test/CodeGen/X86/GlobalISel/llvm.sincos.mir b/llvm/test/CodeGen/X86/GlobalISel/llvm.sincos.mir new file mode 100644 index 000000000000..f8ce9ea8be65 --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/llvm.sincos.mir @@ -0,0 +1,189 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# RUN: llc -mtriple=i686-linux-gnu -run-pass=regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes GISEL-I686 + +--- +name: test_sincos_f32 +alignment: 16 +legalized: true +fixedStack: + - { id: 0, type: default, offset: 0, size: 4, alignment: 16, stack-id: default, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +stack: + - { id: 0, name: '', type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: '', type: default, offset: 0, size: 4, alignment: 4, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +body: | + bb.1: + ; GISEL-I686-LABEL: name: test_sincos_f32 + ; GISEL-I686: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %fixed-stack.0, 1, $noreg, 0, $noreg :: (invariant load (s32) from %fixed-stack.0, align 16) + ; GISEL-I686-NEXT: [[LEA32r:%[0-9]+]]:gr32 = LEA32r %stack.0, 1, $noreg, 0, $noreg + ; GISEL-I686-NEXT: [[LEA32r1:%[0-9]+]]:gr32 = LEA32r %stack.1, 1, $noreg, 0, $noreg + ; GISEL-I686-NEXT: ADJCALLSTACKDOWN32 12, 0, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + ; GISEL-I686-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $esp + ; GISEL-I686-NEXT: MOV32mr [[COPY]], 1, $noreg, 0, $noreg, [[MOV32rm]] :: (store (s32) into stack, align 1) + ; GISEL-I686-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $esp + ; GISEL-I686-NEXT: MOV32mr [[COPY1]], 1, $noreg, 4, $noreg, [[LEA32r]] :: (store (s32) into stack + 4, align 1) + ; GISEL-I686-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY $esp + ; GISEL-I686-NEXT: MOV32mr [[COPY2]], 1, $noreg, 8, $noreg, [[LEA32r1]] :: (store (s32) into stack + 8, align 1) + ; GISEL-I686-NEXT: CALLpcrel32 &sincosf, csr_32, implicit $esp, implicit $ssp + ; GISEL-I686-NEXT: ADJCALLSTACKUP32 12, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + ; GISEL-I686-NEXT: [[LD_Fp32m:%[0-9]+]]:rfp32 = nofpexcept LD_Fp32m %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s32) from %stack.0) + ; GISEL-I686-NEXT: [[LD_Fp32m1:%[0-9]+]]:rfp32 = nofpexcept LD_Fp32m %stack.1, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s32) from %stack.1) + ; GISEL-I686-NEXT: $fp0 = COPY [[LD_Fp32m]] + ; GISEL-I686-NEXT: $fp1 = COPY [[LD_Fp32m1]] + ; GISEL-I686-NEXT: RET 0, implicit $fp0, implicit $fp1 + %1:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %0:_(s32) = G_LOAD %1(p0) :: (invariant load (s32) from %fixed-stack.0, align 16) + %4:_(p0) = G_FRAME_INDEX %stack.0 + %5:_(p0) = G_FRAME_INDEX %stack.1 + ADJCALLSTACKDOWN32 12, 0, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + %6:_(p0) = COPY $esp + %7:_(s32) = G_CONSTANT i32 0 + %8:_(p0) = G_PTR_ADD %6, %7(s32) + G_STORE %0(s32), %8(p0) :: (store (s32) into stack, align 1) + %9:_(p0) = COPY $esp + %10:_(s32) = G_CONSTANT i32 4 + %11:_(p0) = G_PTR_ADD %9, %10(s32) + G_STORE %4(p0), %11(p0) :: (store (s32) into stack + 4, align 1) + %12:_(p0) = COPY $esp + %13:_(s32) = G_CONSTANT i32 8 + %14:_(p0) = G_PTR_ADD %12, %13(s32) + G_STORE %5(p0), %14(p0) :: (store (s32) into stack + 8, align 1) + CALLpcrel32 &sincosf, csr_32, implicit $esp, implicit $ssp + ADJCALLSTACKUP32 12, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + %2:_(s32) = G_LOAD %4(p0) :: (load (s32) from %stack.0) + %3:_(s32) = G_LOAD %5(p0) :: (load (s32) from %stack.1) + $fp0 = COPY %2(s32) + $fp1 = COPY %3(s32) + RET 0, implicit $fp0, implicit $fp1 +... +--- +name: test_sincos_f64 +alignment: 16 +legalized: true +fixedStack: + - { id: 0, type: default, offset: 0, size: 8, alignment: 16, stack-id: default, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +stack: + - { id: 0, name: '', type: default, offset: 0, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: '', type: default, offset: 0, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +body: | + bb.1: + ; GISEL-I686-LABEL: name: test_sincos_f64 + ; GISEL-I686: [[LEA32r:%[0-9]+]]:gr32 = LEA32r %fixed-stack.0, 1, $noreg, 0, $noreg + ; GISEL-I686-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %fixed-stack.0, 1, $noreg, 0, $noreg :: (invariant load (s32) from %fixed-stack.0, align 16) + ; GISEL-I686-NEXT: [[MOV32rm1:%[0-9]+]]:gr32 = MOV32rm [[LEA32r]], 1, $noreg, 4, $noreg :: (invariant load (s32) from %fixed-stack.0 + 4, basealign 16) + ; GISEL-I686-NEXT: [[LEA32r1:%[0-9]+]]:gr32 = LEA32r %stack.0, 1, $noreg, 0, $noreg + ; GISEL-I686-NEXT: [[LEA32r2:%[0-9]+]]:gr32 = LEA32r %stack.1, 1, $noreg, 0, $noreg + ; GISEL-I686-NEXT: ADJCALLSTACKDOWN32 16, 0, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + ; GISEL-I686-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $esp + ; GISEL-I686-NEXT: [[MOV32r0_:%[0-9]+]]:gr32_nosp = MOV32r0 implicit-def dead $eflags + ; GISEL-I686-NEXT: [[LEA32r3:%[0-9]+]]:gr32 = LEA32r [[COPY]], 1, [[MOV32r0_]], 0, $noreg + ; GISEL-I686-NEXT: MOV32mr [[COPY]], 1, $noreg, 0, $noreg, [[MOV32rm]] :: (store (s32) into stack, align 1) + ; GISEL-I686-NEXT: MOV32mr [[LEA32r3]], 1, $noreg, 4, $noreg, [[MOV32rm1]] :: (store (s32) into stack + 4, align 1) + ; GISEL-I686-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $esp + ; GISEL-I686-NEXT: MOV32mr [[COPY1]], 1, $noreg, 8, $noreg, [[LEA32r1]] :: (store (s32) into stack + 8, align 1) + ; GISEL-I686-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY $esp + ; GISEL-I686-NEXT: MOV32mr [[COPY2]], 1, $noreg, 12, $noreg, [[LEA32r2]] :: (store (s32) into stack + 12, align 1) + ; GISEL-I686-NEXT: CALLpcrel32 &sincos, csr_32, implicit $esp, implicit $ssp + ; GISEL-I686-NEXT: ADJCALLSTACKUP32 16, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + ; GISEL-I686-NEXT: $fp0 = IMPLICIT_DEF + ; GISEL-I686-NEXT: $fp1 = IMPLICIT_DEF + ; GISEL-I686-NEXT: RET 0, implicit $fp0, implicit $fp1 + %1:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %25:_(s32) = G_LOAD %1(p0) :: (invariant load (s32) from %fixed-stack.0, align 16) + %17:_(s32) = G_CONSTANT i32 4 + %26:_(p0) = G_PTR_ADD %1, %17(s32) + %27:_(s32) = G_LOAD %26(p0) :: (invariant load (s32) from %fixed-stack.0 + 4, basealign 16) + %4:_(p0) = G_FRAME_INDEX %stack.0 + %5:_(p0) = G_FRAME_INDEX %stack.1 + ADJCALLSTACKDOWN32 16, 0, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + %6:_(p0) = COPY $esp + %7:_(s32) = G_CONSTANT i32 0 + %8:_(p0) = G_PTR_ADD %6, %7(s32) + G_STORE %25(s32), %8(p0) :: (store (s32) into stack, align 1) + %24:_(p0) = G_PTR_ADD %8, %17(s32) + G_STORE %27(s32), %24(p0) :: (store (s32) into stack + 4, align 1) + %9:_(p0) = COPY $esp + %10:_(s32) = G_CONSTANT i32 8 + %11:_(p0) = G_PTR_ADD %9, %10(s32) + G_STORE %4(p0), %11(p0) :: (store (s32) into stack + 8, align 1) + %12:_(p0) = COPY $esp + %13:_(s32) = G_CONSTANT i32 12 + %14:_(p0) = G_PTR_ADD %12, %13(s32) + G_STORE %5(p0), %14(p0) :: (store (s32) into stack + 12, align 1) + CALLpcrel32 &sincos, csr_32, implicit $esp, implicit $ssp + ADJCALLSTACKUP32 16, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + $fp0 = IMPLICIT_DEF + $fp1 = IMPLICIT_DEF + RET 0, implicit $fp0, implicit $fp1 +... +--- +name: test_sincos_f80 +alignment: 16 +legalized: true +fixedStack: + - { id: 0, type: default, offset: 0, size: 10, alignment: 16, stack-id: default, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +stack: + - { id: 0, name: '', type: default, offset: 0, size: 10, alignment: 16, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: '', type: default, offset: 0, size: 10, alignment: 16, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +body: | + bb.1: + ; GISEL-I686-LABEL: name: test_sincos_f80 + ; GISEL-I686: [[LD_Fp80m:%[0-9]+]]:rfp80 = nofpexcept LD_Fp80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (invariant load (s80) from %fixed-stack.0, align 16) + ; GISEL-I686-NEXT: [[LEA32r:%[0-9]+]]:gr32 = LEA32r %stack.0, 1, $noreg, 0, $noreg + ; GISEL-I686-NEXT: [[LEA32r1:%[0-9]+]]:gr32 = LEA32r %stack.1, 1, $noreg, 0, $noreg + ; GISEL-I686-NEXT: ADJCALLSTACKDOWN32 20, 0, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + ; GISEL-I686-NEXT: [[COPY:%[0-9]+]]:gr32 = COPY $esp + ; GISEL-I686-NEXT: nofpexcept ST_FpP80m [[COPY]], 1, $noreg, 0, $noreg, [[LD_Fp80m]], implicit-def dead $fpsw, implicit $fpcw :: (store (s80) into stack, align 1) + ; GISEL-I686-NEXT: [[COPY1:%[0-9]+]]:gr32 = COPY $esp + ; GISEL-I686-NEXT: MOV32mr [[COPY1]], 1, $noreg, 12, $noreg, [[LEA32r]] :: (store (s32) into stack + 12, align 1) + ; GISEL-I686-NEXT: [[COPY2:%[0-9]+]]:gr32 = COPY $esp + ; GISEL-I686-NEXT: MOV32mr [[COPY2]], 1, $noreg, 16, $noreg, [[LEA32r1]] :: (store (s32) into stack + 16, align 1) + ; GISEL-I686-NEXT: CALLpcrel32 &sincosl, csr_32, implicit $esp, implicit $ssp + ; GISEL-I686-NEXT: ADJCALLSTACKUP32 20, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + ; GISEL-I686-NEXT: [[LD_Fp80m1:%[0-9]+]]:rfp80 = nofpexcept LD_Fp80m %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s80) from %stack.0, align 16) + ; GISEL-I686-NEXT: [[LD_Fp80m2:%[0-9]+]]:rfp80 = nofpexcept LD_Fp80m %stack.1, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s80) from %stack.1, align 16) + ; GISEL-I686-NEXT: $fp0 = COPY [[LD_Fp80m1]] + ; GISEL-I686-NEXT: $fp1 = COPY [[LD_Fp80m2]] + ; GISEL-I686-NEXT: RET 0, implicit $fp0, implicit $fp1 + %1:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %0:_(s80) = G_LOAD %1(p0) :: (invariant load (s80) from %fixed-stack.0, align 16) + %4:_(p0) = G_FRAME_INDEX %stack.0 + %5:_(p0) = G_FRAME_INDEX %stack.1 + ADJCALLSTACKDOWN32 20, 0, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + %6:_(p0) = COPY $esp + %7:_(s32) = G_CONSTANT i32 0 + %8:_(p0) = G_PTR_ADD %6, %7(s32) + G_STORE %0(s80), %8(p0) :: (store (s80) into stack, align 1) + %9:_(p0) = COPY $esp + %10:_(s32) = G_CONSTANT i32 12 + %11:_(p0) = G_PTR_ADD %9, %10(s32) + G_STORE %4(p0), %11(p0) :: (store (s32) into stack + 12, align 1) + %12:_(p0) = COPY $esp + %13:_(s32) = G_CONSTANT i32 16 + %14:_(p0) = G_PTR_ADD %12, %13(s32) + G_STORE %5(p0), %14(p0) :: (store (s32) into stack + 16, align 1) + CALLpcrel32 &sincosl, csr_32, implicit $esp, implicit $ssp + ADJCALLSTACKUP32 20, 0, implicit-def $esp, implicit-def $eflags, implicit-def $ssp, implicit $esp, implicit $ssp + %2:_(s80) = G_LOAD %4(p0) :: (load (s80) from %stack.0, align 16) + %3:_(s80) = G_LOAD %5(p0) :: (load (s80) from %stack.1, align 16) + $fp0 = COPY %2(s80) + $fp1 = COPY %3(s80) + RET 0, implicit $fp0, implicit $fp1 +... diff --git a/llvm/test/CodeGen/X86/llvm.sincos.ll b/llvm/test/CodeGen/X86/llvm.sincos.ll index 5734729a2c50..065710f91457 100644 --- a/llvm/test/CodeGen/X86/llvm.sincos.ll +++ b/llvm/test/CodeGen/X86/llvm.sincos.ll @@ -3,8 +3,9 @@ ; RUN: llc < %s -mtriple=x86_64-linux-gnu -fast-isel | FileCheck %s --check-prefixes=X64,FASTISEL-X64 ; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=0 -fast-isel=0 | FileCheck %s --check-prefixes=X86,SDAG-X86 ; RUN: llc < %s -mtriple=x86_64-linux-gnu -global-isel=0 -fast-isel=0 | FileCheck %s --check-prefixes=X64,SDAG-X64 -; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes=X86,GISEL-X86 -; RUN: llc < %s -mtriple=x86_64-linux-gnu -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes=X64,GISEL-X64 +; TODO: The below RUN line will fails GISEL selection and will fallback to DAG selection due to lack of support for loads/stores in i686 mode, support is expected soon enough, for this reason the llvm/test/CodeGen/X86/GlobalISel/llvm.sincos.mir test is added for now because of the lack of support for i686 in GlobalISel. +; RUN: llc < %s -mtriple=i686-linux-gnu -global-isel=1 -global-isel-abort=2 | FileCheck %s --check-prefixes=GISEL-X86 +; RUN: llc < %s -mtriple=x86_64-linux-gnu -global-isel=1 -global-isel-abort=1 | FileCheck %s --check-prefixes=GISEL-X64 define { float, float } @test_sincos_f32(float %Val) nounwind { ; X86-LABEL: test_sincos_f32: @@ -32,6 +33,35 @@ define { float, float } @test_sincos_f32(float %Val) nounwind { ; X64-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero ; X64-NEXT: popq %rax ; X64-NEXT: retq +; +; GISEL-X86-LABEL: test_sincos_f32: +; GISEL-X86: # %bb.0: +; GISEL-X86-NEXT: subl $28, %esp +; GISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; GISEL-X86-NEXT: leal {{[0-9]+}}(%esp), %edx +; GISEL-X86-NEXT: movl %eax, (%esp) +; GISEL-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: movl %edx, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: calll sincosf +; GISEL-X86-NEXT: flds {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: flds {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fxch %st(1) +; GISEL-X86-NEXT: addl $28, %esp +; GISEL-X86-NEXT: retl +; +; GISEL-X64-LABEL: test_sincos_f32: +; GISEL-X64: # %bb.0: +; GISEL-X64-NEXT: pushq %rax +; GISEL-X64-NEXT: leaq {{[0-9]+}}(%rsp), %rdi +; GISEL-X64-NEXT: movq %rsp, %rsi +; GISEL-X64-NEXT: callq sincosf +; GISEL-X64-NEXT: movl {{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: movl (%rsp), %ecx +; GISEL-X64-NEXT: movd %eax, %xmm0 +; GISEL-X64-NEXT: movd %ecx, %xmm1 +; GISEL-X64-NEXT: popq %rax +; GISEL-X64-NEXT: retq %res = call { float, float } @llvm.sincos.f32(float %Val) ret { float, float } %res } @@ -62,6 +92,34 @@ define { double, double } @test_sincos_f64(double %Val) nounwind { ; X64-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero ; X64-NEXT: addq $24, %rsp ; X64-NEXT: retq +; +; GISEL-X86-LABEL: test_sincos_f64: +; GISEL-X86: # %bb.0: +; GISEL-X86-NEXT: subl $44, %esp +; GISEL-X86-NEXT: fldl {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fstpl (%esp) +; GISEL-X86-NEXT: calll sincos +; GISEL-X86-NEXT: fldl {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fldl {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: addl $44, %esp +; GISEL-X86-NEXT: retl +; +; GISEL-X64-LABEL: test_sincos_f64: +; GISEL-X64: # %bb.0: +; GISEL-X64-NEXT: subq $24, %rsp +; GISEL-X64-NEXT: leaq {{[0-9]+}}(%rsp), %rdi +; GISEL-X64-NEXT: leaq {{[0-9]+}}(%rsp), %rsi +; GISEL-X64-NEXT: callq sincos +; GISEL-X64-NEXT: movq {{[0-9]+}}(%rsp), %rax +; GISEL-X64-NEXT: movq {{[0-9]+}}(%rsp), %rcx +; GISEL-X64-NEXT: movq %rax, %xmm0 +; GISEL-X64-NEXT: movq %rcx, %xmm1 +; GISEL-X64-NEXT: addq $24, %rsp +; GISEL-X64-NEXT: retq %res = call { double, double } @llvm.sincos.f64(double %Val) ret { double, double } %res } @@ -94,6 +152,36 @@ define { x86_fp80, x86_fp80 } @test_sincos_f80(x86_fp80 %Val) nounwind { ; X64-NEXT: fldt {{[0-9]+}}(%rsp) ; X64-NEXT: addq $56, %rsp ; X64-NEXT: retq +; +; GISEL-X86-LABEL: test_sincos_f80: +; GISEL-X86: # %bb.0: +; GISEL-X86-NEXT: subl $60, %esp +; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: leal {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: leal {{[0-9]+}}(%esp), %ecx +; GISEL-X86-NEXT: fstpt (%esp) +; GISEL-X86-NEXT: movl %eax, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: movl %ecx, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: calll sincosl +; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fxch %st(1) +; GISEL-X86-NEXT: addl $60, %esp +; GISEL-X86-NEXT: retl +; +; GISEL-X64-LABEL: test_sincos_f80: +; GISEL-X64: # %bb.0: +; GISEL-X64-NEXT: subq $56, %rsp +; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: leaq {{[0-9]+}}(%rsp), %rdi +; GISEL-X64-NEXT: leaq {{[0-9]+}}(%rsp), %rsi +; GISEL-X64-NEXT: fstpt (%rsp) +; GISEL-X64-NEXT: callq sincosl +; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fxch %st(1) +; GISEL-X64-NEXT: addq $56, %rsp +; GISEL-X64-NEXT: retq %res = call { x86_fp80, x86_fp80 } @llvm.sincos.f80(x86_fp80 %Val) ret { x86_fp80, x86_fp80 } %res }