diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h index 0df3df5b8e9c8..fd72a3898562e 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerInfo.h @@ -935,6 +935,16 @@ class LegalizeRuleSet { Types2); } + /// The instruction is custom when the predicate is true and type indexes 0 + /// and 1 are all in their respective lists. + LegalizeRuleSet & + customForCartesianProduct(bool Pred, std::initializer_list Types0, + std::initializer_list Types1) { + if (!Pred) + return *this; + return actionForCartesianProduct(LegalizeAction::Custom, Types0, Types1); + } + /// Unconditionally custom lower. LegalizeRuleSet &custom() { return customIf(always); diff --git a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp index ea08f71b8af4a..3090ad313b90d 100644 --- a/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp +++ b/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp @@ -364,7 +364,7 @@ bool X86InstructionSelector::select(MachineInstr &I) { MachineRegisterInfo &MRI = MF.getRegInfo(); unsigned Opcode = I.getOpcode(); - if (!isPreISelGenericOpcode(Opcode)) { + if (!isPreISelGenericOpcode(Opcode) && !I.isPreISelOpcode()) { // Certain non-generic instructions also need some special handling. if (Opcode == TargetOpcode::LOAD_STACK_GUARD) diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp index f008cb1bea839..11dd05c584983 100644 --- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp +++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.cpp @@ -490,31 +490,25 @@ X86LegalizerInfo::X86LegalizerInfo(const X86Subtarget &STI, }); getActionDefinitionsBuilder(G_SITOFP) - .legalIf([=](const LegalityQuery &Query) { - return (HasSSE1 && - (typePairInSet(0, 1, {{s32, s32}})(Query) || - (Is64Bit && typePairInSet(0, 1, {{s32, s64}})(Query)))) || - (HasSSE2 && - (typePairInSet(0, 1, {{s64, s32}})(Query) || - (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)))); - }) - .clampScalar(1, s32, sMaxScalar) + .legalFor(HasSSE1, {{s32, s32}}) + .legalFor(HasSSE1 && Is64Bit, {{s32, s64}}) + .legalFor(HasSSE2, {{s64, s32}}) + .legalFor(HasSSE2 && Is64Bit, {{s64, s64}}) + .clampScalar(1, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar) .widenScalarToNextPow2(1) + .customForCartesianProduct(UseX87, {s32, s64, s80}, {s16, s32, s64}) .clampScalar(0, s32, HasSSE2 ? s64 : s32) .widenScalarToNextPow2(0); getActionDefinitionsBuilder(G_FPTOSI) - .legalIf([=](const LegalityQuery &Query) { - return (HasSSE1 && - (typePairInSet(0, 1, {{s32, s32}})(Query) || - (Is64Bit && typePairInSet(0, 1, {{s64, s32}})(Query)))) || - (HasSSE2 && - (typePairInSet(0, 1, {{s32, s64}})(Query) || - (Is64Bit && typePairInSet(0, 1, {{s64, s64}})(Query)))); - }) - .clampScalar(1, s32, HasSSE2 ? s64 : s32) + .legalFor(HasSSE1, {{s32, s32}}) + .legalFor(HasSSE1 && Is64Bit, {{s64, s32}}) + .legalFor(HasSSE2, {{s32, s64}}) + .legalFor(HasSSE2 && Is64Bit, {{s64, s64}}) + .clampScalar(0, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar) .widenScalarToNextPow2(0) - .clampScalar(0, s32, sMaxScalar) + .customForCartesianProduct(UseX87, {s16, s32, s64}, {s32, s64, s80}) + .clampScalar(1, s32, HasSSE2 ? s64 : s32) .widenScalarToNextPow2(1); // For G_UITOFP and G_FPTOUI without AVX512, we have to custom legalize types @@ -671,10 +665,70 @@ bool X86LegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, return legalizeUITOFP(MI, MRI, Helper); case TargetOpcode::G_STORE: return legalizeNarrowingStore(MI, MRI, Helper); + case TargetOpcode::G_SITOFP: + return legalizeSITOFP(MI, MRI, Helper); + case TargetOpcode::G_FPTOSI: + return legalizeFPTOSI(MI, MRI, Helper); } llvm_unreachable("expected switch to return"); } +bool X86LegalizerInfo::legalizeSITOFP(MachineInstr &MI, + MachineRegisterInfo &MRI, + LegalizerHelper &Helper) const { + MachineIRBuilder &MIRBuilder = Helper.MIRBuilder; + MachineFunction &MF = *MI.getMF(); + auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs(); + + assert((SrcTy.getSizeInBits() == 16 || SrcTy.getSizeInBits() == 32 || + SrcTy.getSizeInBits() == 64) && + "Unexpected source type for SITOFP in X87 mode."); + + TypeSize MemSize = SrcTy.getSizeInBytes(); + MachinePointerInfo PtrInfo; + Align Alignmt = Helper.getStackTemporaryAlignment(SrcTy); + auto SlotPointer = Helper.createStackTemporary(MemSize, Alignmt, PtrInfo); + MachineMemOperand *StoreMMO = MF.getMachineMemOperand( + PtrInfo, MachineMemOperand::MOStore, MemSize, Align(MemSize)); + + // Store the integer value on the FPU stack. + MIRBuilder.buildStore(Src, SlotPointer, *StoreMMO); + + MachineMemOperand *LoadMMO = MF.getMachineMemOperand( + PtrInfo, MachineMemOperand::MOLoad, MemSize, Align(MemSize)); + MIRBuilder.buildInstr(X86::G_FILD) + .addDef(Dst) + .addUse(SlotPointer.getReg(0)) + .addMemOperand(LoadMMO); + + MI.eraseFromParent(); + return true; +} + +bool X86LegalizerInfo::legalizeFPTOSI(MachineInstr &MI, + MachineRegisterInfo &MRI, + LegalizerHelper &Helper) const { + MachineFunction &MF = *MI.getMF(); + MachineIRBuilder &MIRBuilder = Helper.MIRBuilder; + auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs(); + + TypeSize MemSize = DstTy.getSizeInBytes(); + MachinePointerInfo PtrInfo; + Align Alignmt = Helper.getStackTemporaryAlignment(DstTy); + auto SlotPointer = Helper.createStackTemporary(MemSize, Alignmt, PtrInfo); + MachineMemOperand *StoreMMO = MF.getMachineMemOperand( + PtrInfo, MachineMemOperand::MOStore, MemSize, Align(MemSize)); + + MIRBuilder.buildInstr(X86::G_FIST) + .addUse(Src) + .addUse(SlotPointer.getReg(0)) + .addMemOperand(StoreMMO); + + MIRBuilder.buildLoad(Dst, SlotPointer, PtrInfo, Align(MemSize)); + MI.eraseFromParent(); + return true; +} + bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI, MachineRegisterInfo &MRI, LegalizerHelper &Helper) const { diff --git a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h index 54f776456397b..1ba82674ed4c6 100644 --- a/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h +++ b/llvm/lib/Target/X86/GISel/X86LegalizerInfo.h @@ -48,6 +48,12 @@ class X86LegalizerInfo : public LegalizerInfo { bool legalizeNarrowingStore(MachineInstr &MI, MachineRegisterInfo &MRI, LegalizerHelper &Helper) const; + + bool legalizeSITOFP(MachineInstr &MI, MachineRegisterInfo &MRI, + LegalizerHelper &Helper) const; + + bool legalizeFPTOSI(MachineInstr &MI, MachineRegisterInfo &MRI, + LegalizerHelper &Helper) const; }; } // namespace llvm #endif diff --git a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp index 0baca81494694..74fe5fcaab6cc 100644 --- a/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp +++ b/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp @@ -111,6 +111,7 @@ bool X86RegisterBankInfo::onlyUsesFP(const MachineInstr &MI, case TargetOpcode::G_FPTOSI: case TargetOpcode::G_FPTOUI: case TargetOpcode::G_FCMP: + case X86::G_FIST: case TargetOpcode::G_LROUND: case TargetOpcode::G_LLROUND: case TargetOpcode::G_INTRINSIC_TRUNC: @@ -129,6 +130,7 @@ bool X86RegisterBankInfo::onlyDefinesFP(const MachineInstr &MI, switch (MI.getOpcode()) { case TargetOpcode::G_SITOFP: case TargetOpcode::G_UITOFP: + case X86::G_FILD: return true; default: break; @@ -296,6 +298,16 @@ X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { // VECRReg) getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx); break; + case X86::G_FIST: + case X86::G_FILD: { + auto &Op0 = MI.getOperand(0); + auto &Op1 = MI.getOperand(1); + const LLT Ty0 = MRI.getType(Op0.getReg()); + const LLT Ty1 = MRI.getType(Op1.getReg()); + OpRegBankIdx[0] = getPartialMappingIdx(MI, Ty0, /* isFP= */ true); + OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ false); + break; + } case TargetOpcode::G_SITOFP: case TargetOpcode::G_FPTOSI: case TargetOpcode::G_UITOFP: diff --git a/llvm/lib/Target/X86/X86InstrFragments.td b/llvm/lib/Target/X86/X86InstrFragments.td index fe95b8c20a8ff..712492e474619 100644 --- a/llvm/lib/Target/X86/X86InstrFragments.td +++ b/llvm/lib/Target/X86/X86InstrFragments.td @@ -844,13 +844,24 @@ def X86fldf80 : PatFrag<(ops node:$ptr), (X86fld node:$ptr), [{ def X86fild16 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i16; -}]>; +}]> { + let IsLoad = true; + let MemoryVT = i16; +} + def X86fild32 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i32; -}]>; +}]> { + let IsLoad = true; + let MemoryVT = i32; +} + def X86fild64 : PatFrag<(ops node:$ptr), (X86fild node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i64; -}]>; +}]> { + let IsLoad = true; + let MemoryVT = i64; +} def X86fist32 : PatFrag<(ops node:$val, node:$ptr), (X86fist node:$val, node:$ptr), [{ @@ -865,15 +876,26 @@ def X86fist64 : PatFrag<(ops node:$val, node:$ptr), def X86fp_to_i16mem : PatFrag<(ops node:$val, node:$ptr), (X86fp_to_mem node:$val, node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i16; -}]>; +}]> { + let IsStore = true; + let MemoryVT = i16; +} + def X86fp_to_i32mem : PatFrag<(ops node:$val, node:$ptr), (X86fp_to_mem node:$val, node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i32; -}]>; +}]> { + let IsStore = true; + let MemoryVT = i32; +} + def X86fp_to_i64mem : PatFrag<(ops node:$val, node:$ptr), (X86fp_to_mem node:$val, node:$ptr), [{ return cast(N)->getMemoryVT() == MVT::i64; -}]>; +}]> { + let IsStore = true; + let MemoryVT = i64; +} //===----------------------------------------------------------------------===// // FPStack pattern fragments diff --git a/llvm/lib/Target/X86/X86InstrGISel.td b/llvm/lib/Target/X86/X86InstrGISel.td new file mode 100644 index 0000000000000..f4fa33807cd9a --- /dev/null +++ b/llvm/lib/Target/X86/X86InstrGISel.td @@ -0,0 +1,31 @@ +//===- X86InstrGISel.td - X86 GISel target specific opcodes -*- tablegen -*===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// X86 GlobalISel target pseudo instruction definitions. This is kept +// separately from the other tablegen files for organizational purposes, but +// share the same infrastructure. +// +//===----------------------------------------------------------------------===// + +class X86GenericInstruction : GenericInstruction { let Namespace = "X86"; } + +def G_FILD : X86GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins ptype1:$src); + let hasSideEffects = false; + let mayLoad = true; +} +def G_FIST : X86GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins type0:$src1, ptype1:$src2); + let hasSideEffects = false; + let mayStore = true; +} + +def : GINodeEquiv; +def : GINodeEquiv; diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index e75d6743f9273..7f6c5614847e3 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -37,6 +37,11 @@ include "X86InstrFormats.td" // include "X86InstrUtils.td" +//===----------------------------------------------------------------------===// +// Global ISel +// +include "X86InstrGISel.td" + //===----------------------------------------------------------------------===// // Subsystems. //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/X86/GlobalISel/isel-fp64-to-sint-x86.mir b/llvm/test/CodeGen/X86/GlobalISel/isel-fp64-to-sint-x86.mir new file mode 100644 index 0000000000000..3e1af9d836aec --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/isel-fp64-to-sint-x86.mir @@ -0,0 +1,136 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# NOTE: This MIR test is required because the support for 64 bit memory ops is missing in X86 mode, Due to distinction between float/int types, support is expected in near future and there is this RFC in place https://discourse.llvm.org/t/rfc-globalisel-adding-fp-type-information-to-llt/83349. Once this support is introduced this test must be dropped and integrated into the LLVM IR tests. +# RUN: llc -O2 -mtriple=i686-linux-gnu -mattr=+x87,-sse,-sse2 -run-pass=regbankselect,instruction-select -disable-gisel-legality-check -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes GISEL-X86 + +--- +name: test_double_to_int16 +alignment: 16 +exposesReturnsTwice: false +legalized: true +tracksRegLiveness: 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: 2, alignment: 2, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + +body: | + bb.1.entry: + ; GISEL-X86-LABEL: name: test_double_to_int16 + ; GISEL-X86: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF + ; GISEL-X86-NEXT: FP64_TO_INT16_IN_MEM %stack.0, 1, $noreg, 0, $noreg, [[DEF]], implicit-def dead $eflags :: (store (s16) into %stack.0) + ; GISEL-X86-NEXT: [[MOV16rm:%[0-9]+]]:gr16 = MOV16rm %stack.0, 1, $noreg, 0, $noreg :: (load (s16) from %stack.0) + ; GISEL-X86-NEXT: $ax = COPY [[MOV16rm]] + ; GISEL-X86-NEXT: RET 0, implicit $ax + %0:_(s64) = IMPLICIT_DEF + %3:_(p0) = G_FRAME_INDEX %stack.0 + G_FIST %0(s64), %3(p0) :: (store (s16) into %stack.0) + %2:_(s16) = G_LOAD %3(p0) :: (load (s16) from %stack.0) + $ax = COPY %2(s16) + RET 0, implicit $ax +... +--- +name: test_double_to_int32 +alignment: 16 +exposesReturnsTwice: false +legalized: true +tracksRegLiveness: 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: 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.entry: + ; GISEL-X86-LABEL: name: test_double_to_int32 + ; GISEL-X86: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF + ; GISEL-X86-NEXT: FP64_TO_INT32_IN_MEM %stack.0, 1, $noreg, 0, $noreg, [[DEF]], implicit-def dead $eflags :: (store (s32) into %stack.0) + ; GISEL-X86-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.0, 1, $noreg, 0, $noreg :: (load (s32) from %stack.0) + ; GISEL-X86-NEXT: $eax = COPY [[MOV32rm]] + ; GISEL-X86-NEXT: RET 0, implicit $eax + %0:_(s64) = IMPLICIT_DEF + %3:_(p0) = G_FRAME_INDEX %stack.0 + G_FIST %0(s64), %3(p0) :: (store (s32) into %stack.0) + %2:_(s32) = G_LOAD %3(p0) :: (load (s32) from %stack.0) + $eax = COPY %2(s32) + RET 0, implicit $eax +... +--- +name: test_double_to_int64 +alignment: 16 +exposesReturnsTwice: false +legalized: true +tracksRegLiveness: 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: '' } +body: | + bb.1.entry: + ; GISEL-X86-LABEL: name: test_double_to_int64 + ; GISEL-X86: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF + ; GISEL-X86-NEXT: [[LEA32r:%[0-9]+]]:gr32 = LEA32r %stack.0, 1, $noreg, 0, $noreg + ; GISEL-X86-NEXT: FP64_TO_INT64_IN_MEM %stack.0, 1, $noreg, 0, $noreg, [[DEF]], implicit-def dead $eflags :: (store (s64) into %stack.0) + ; GISEL-X86-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.0, 1, $noreg, 0, $noreg :: (load (s32) from %stack.0, align 8) + ; GISEL-X86-NEXT: [[MOV32rm1:%[0-9]+]]:gr32 = MOV32rm [[LEA32r]], 1, $noreg, 4, $noreg :: (load (s32) from %stack.0 + 4, basealign 8) + ; GISEL-X86-NEXT: $eax = COPY [[MOV32rm]] + ; GISEL-X86-NEXT: $edx = COPY [[MOV32rm1]] + ; GISEL-X86-NEXT: RET 0, implicit $eax, implicit $edx + %1:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %10:_(s32) = G_LOAD %1(p0) :: (invariant load (s32) from %fixed-stack.0, align 16) + %8:_(s32) = G_CONSTANT i32 4 + %11:_(p0) = G_PTR_ADD %1, %8(s32) + %12:_(s32) = G_LOAD %11(p0) :: (invariant load (s32) from %fixed-stack.0 + 4, basealign 16) + %0:_(s64) = IMPLICIT_DEF + %5:_(p0) = G_FRAME_INDEX %stack.0 + G_FIST %0(s64), %5(p0) :: (store (s64) into %stack.0) + %6:_(s32) = G_LOAD %5(p0) :: (load (s32) from %stack.0, align 8) + %7:_(p0) = G_PTR_ADD %5, %8(s32) + %9:_(s32) = G_LOAD %7(p0) :: (load (s32) from %stack.0 + 4, basealign 8) + $eax = COPY %6(s32) + $edx = COPY %9(s32) + RET 0, implicit $eax, implicit $edx +... +--- +name: test_double_to_int8 +alignment: 16 +exposesReturnsTwice: false +legalized: true +tracksRegLiveness: 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: 2, alignment: 2, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + +body: | + bb.1.entry: + ; GISEL-X86-LABEL: name: test_double_to_int8 + ; GISEL-X86: [[DEF:%[0-9]+]]:rfp64 = IMPLICIT_DEF + ; GISEL-X86-NEXT: FP64_TO_INT16_IN_MEM %stack.0, 1, $noreg, 0, $noreg, [[DEF]], implicit-def dead $eflags :: (store (s16) into %stack.0) + ; GISEL-X86-NEXT: [[MOV16rm:%[0-9]+]]:gr16 = MOV16rm %stack.0, 1, $noreg, 0, $noreg :: (load (s16) from %stack.0) + ; GISEL-X86-NEXT: [[COPY:%[0-9]+]]:gr16_abcd = COPY [[MOV16rm]] + ; GISEL-X86-NEXT: [[COPY1:%[0-9]+]]:gr8_abcd_l = COPY [[COPY]].sub_8bit + ; GISEL-X86-NEXT: $al = COPY [[COPY1]] + ; GISEL-X86-NEXT: RET 0, implicit $al + %0:_(s64) = IMPLICIT_DEF + %4:_(p0) = G_FRAME_INDEX %stack.0 + G_FIST %0(s64), %4(p0) :: (store (s16) into %stack.0) + %3:_(s16) = G_LOAD %4(p0) :: (load (s16) from %stack.0) + %2:_(s8) = G_TRUNC %3(s16) + $al = COPY %2(s8) + RET 0, implicit $al diff --git a/llvm/test/CodeGen/X86/GlobalISel/isel-sint-to-fp64-x86.mir b/llvm/test/CodeGen/X86/GlobalISel/isel-sint-to-fp64-x86.mir new file mode 100644 index 0000000000000..b6b2bd610fa3b --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/isel-sint-to-fp64-x86.mir @@ -0,0 +1,152 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5 +# NOTE: This MIR test is required because the support for 64 bit memory ops is missing in X86 mode, Due to distinction between float/int types, support is expected in near future and there is this RFC in place https://discourse.llvm.org/t/rfc-globalisel-adding-fp-type-information-to-llt/83349. Once this support is introduced this test must be dropped and integrated into the LLVM IR tests. +# RUN: llc -O2 -mtriple=i686-linux-gnu -mattr=+x87,-sse,-sse2 -run-pass=regbankselect,instruction-select -disable-gisel-legality-check -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes GISEL-X86 + +--- +name: test_si8tofp64 +alignment: 16 +exposesReturnsTwice: false +legalized: true +tracksRegLiveness: true +fixedStack: + - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, type: default, offset: 0, size: 1, alignment: 4, 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: 2, alignment: 2, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +body: | + bb.1.entry: + ; GISEL-X86-LABEL: name: test_si8tofp64 + ; GISEL-X86: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %fixed-stack.1, 1, $noreg, 0, $noreg :: (invariant load (p0) from %fixed-stack.1) + ; GISEL-X86-NEXT: [[DEF:%[0-9]+]]:gr16 = IMPLICIT_DEF + ; GISEL-X86-NEXT: MOV16mr %stack.0, 1, $noreg, 0, $noreg, [[DEF]] :: (store (s16) into %stack.0) + ; GISEL-X86-NEXT: [[ILD_Fp16m64_:%[0-9]+]]:rfp64 = ILD_Fp16m64 %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s16) from %stack.0) + ; GISEL-X86-NEXT: nofpexcept ST_Fp64m [[MOV32rm]], 1, $noreg, 0, $noreg, [[ILD_Fp16m64_]], implicit-def dead $fpsw, implicit $fpcw :: (store (s64)) + ; GISEL-X86-NEXT: RET 0 + %4:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %1:_(p0) = G_LOAD %4(p0) :: (invariant load (p0) from %fixed-stack.0) + %6:_(s16) = IMPLICIT_DEF + %7:_(p0) = G_FRAME_INDEX %stack.0 + G_STORE %6(s16), %7(p0) :: (store (s16) into %stack.0) + %5:_(s64) = G_FILD %7(p0) :: (load (s16) from %stack.0) + G_STORE %5(s64), %1(p0) :: (store (s64)) + RET 0 +... +--- +name: test_si16tofp64 +alignment: 16 +legalized: true +tracksRegLiveness: true +fixedStack: + - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, type: default, offset: 0, size: 2, alignment: 4, 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: 2, alignment: 2, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +body: | + bb.1.entry: + ; GISEL-X86-LABEL: name: test_si16tofp64 + ; GISEL-X86: [[DEF:%[0-9]+]]:gr16 = IMPLICIT_DEF + ; GISEL-X86-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %fixed-stack.1, 1, $noreg, 0, $noreg :: (invariant load (p0) from %fixed-stack.1) + ; GISEL-X86-NEXT: MOV16mr %stack.0, 1, $noreg, 0, $noreg, [[DEF]] :: (store (s16) into %stack.0) + ; GISEL-X86-NEXT: [[ILD_Fp16m64_:%[0-9]+]]:rfp64 = ILD_Fp16m64 %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s16) from %stack.0) + ; GISEL-X86-NEXT: nofpexcept ST_Fp64m [[MOV32rm]], 1, $noreg, 0, $noreg, [[ILD_Fp16m64_]], implicit-def dead $fpsw, implicit $fpcw :: (store (s64)) + ; GISEL-X86-NEXT: RET 0 + %0:_(s16) = IMPLICIT_DEF + %4:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %1:_(p0) = G_LOAD %4(p0) :: (invariant load (p0) from %fixed-stack.0) + %6:_(p0) = G_FRAME_INDEX %stack.0 + G_STORE %0(s16), %6(p0) :: (store (s16) into %stack.0) + %5:_(s64) = G_FILD %6(p0):: (load (s16) from %stack.0) + G_STORE %5(s64), %1(p0) :: (store (s64)) + RET 0 +... +--- +name: test_si32tofp64 +alignment: 4 +exposesReturnsTwice: false +legalized: true +tracksRegLiveness: true +fixedStack: + - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: default, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, type: default, offset: 0, size: 4, alignment: 4, 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: '' } +body: | + bb.1.entry: + ; GISEL-X86-LABEL: name: test_si32tofp64 + ; GISEL-X86: [[DEF:%[0-9]+]]:gr32 = IMPLICIT_DEF + ; GISEL-X86-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %fixed-stack.1, 1, $noreg, 0, $noreg :: (invariant load (p0) from %fixed-stack.1) + ; GISEL-X86-NEXT: MOV32mr %stack.0, 1, $noreg, 0, $noreg, [[DEF]] :: (store (s32) into %stack.0) + ; GISEL-X86-NEXT: [[ILD_Fp32m64_:%[0-9]+]]:rfp64 = ILD_Fp32m64 %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s32) from %stack.0) + ; GISEL-X86-NEXT: nofpexcept ST_Fp64m [[MOV32rm]], 1, $noreg, 0, $noreg, [[ILD_Fp32m64_]], implicit-def dead $fpsw, implicit $fpcw :: (store (s64)) + ; GISEL-X86-NEXT: RET 0 + %0:_(s32) = IMPLICIT_DEF + %3:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %1:_(p0) = G_LOAD %3(p0) :: (invariant load (p0) from %fixed-stack.0) + %5:_(p0) = G_FRAME_INDEX %stack.0 + G_STORE %0(s32), %5(p0) :: (store (s32) into %stack.0) + %4:_(s64) = G_FILD %5(p0) :: (load (s32) from %stack.0) + G_STORE %4(s64), %1(p0) :: (store (s64)) + RET 0 +... +--- +name: test_si64tofp64 +alignment: 16 +exposesReturnsTwice: false +legalized: true +tracksRegLiveness: true +fixedStack: + - { id: 0, type: default, offset: 8, size: 4, alignment: 8, stack-id: default, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, type: default, offset: 4, size: 4, alignment: 4, stack-id: default, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 2, 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: 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.entry: + ; GISEL-X86-LABEL: name: test_si64tofp64 + ; GISEL-X86: [[DEF:%[0-9]+]]:gr32 = IMPLICIT_DEF + ; GISEL-X86-NEXT: [[DEF1:%[0-9]+]]:gr32 = IMPLICIT_DEF + ; GISEL-X86-NEXT: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %fixed-stack.2, 1, $noreg, 0, $noreg :: (invariant load (p0) from %fixed-stack.2, align 8) + ; GISEL-X86-NEXT: [[LEA32r:%[0-9]+]]:gr32 = LEA32r %stack.0, 1, $noreg, 0, $noreg + ; GISEL-X86-NEXT: MOV32mr %stack.0, 1, $noreg, 0, $noreg, [[DEF]] :: (store (s32) into %stack.0, align 8) + ; GISEL-X86-NEXT: MOV32mr [[LEA32r]], 1, $noreg, 4, $noreg, [[DEF1]] :: (store (s32) into %stack.0 + 4, basealign 8) + ; GISEL-X86-NEXT: [[ILD_Fp64m64_:%[0-9]+]]:rfp64 = ILD_Fp64m64 %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s64) from %stack.0) + ; GISEL-X86-NEXT: nofpexcept ST_Fp64m [[MOV32rm]], 1, $noreg, 0, $noreg, [[ILD_Fp64m64_]], implicit-def dead $fpsw, implicit $fpcw :: (store (s64)) + ; GISEL-X86-NEXT: RET 0 + %2:_(s32) = IMPLICIT_DEF + %3:_(s32) = IMPLICIT_DEF + %6:_(p0) = G_FRAME_INDEX %fixed-stack.0 + %1:_(p0) = G_LOAD %6(p0) :: (invariant load (p0) from %fixed-stack.0, align 8) + %8:_(p0) = G_FRAME_INDEX %stack.0 + G_STORE %2(s32), %8(p0) :: (store (s32) into %stack.0, align 8) + %12:_(s32) = G_CONSTANT i32 4 + %11:_(p0) = G_PTR_ADD %8, %12(s32) + G_STORE %3(s32), %11(p0) :: (store (s32) into %stack.0 + 4, basealign 8) + %7:_(s64) = G_FILD %8(p0) :: (load (s64) from %stack.0) + G_STORE %7(s64), %1(p0) :: (store (s64)) + RET 0 diff --git a/llvm/test/CodeGen/X86/isel-fp-to-sint-x87.ll b/llvm/test/CodeGen/X86/isel-fp-to-sint-x87.ll index b0400dff1d3d4..49e33141701fb 100644 --- a/llvm/test/CodeGen/X86/isel-fp-to-sint-x87.ll +++ b/llvm/test/CodeGen/X86/isel-fp-to-sint-x87.ll @@ -2,71 +2,133 @@ ; NOTE: Fast Isel is not added because it does not support x87 stores. ; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel=0 | FileCheck %s --check-prefixes X64,SDAG-X64 -; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel -global-isel-abort=2 | FileCheck %s --check-prefixes X64,GISEL-X64 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel -global-isel-abort=1 | FileCheck %s --check-prefixes X64,GISEL-X64 ; RUN: llc < %s -mtriple=i686-- -mattr=+x87,-sse,-sse2 -global-isel=0 | FileCheck %s --check-prefixes X86,SDAG-X86 +; TODO: The last RUN line fails GISEL for f64/double cases and will fallback to DAG due to lack of support for +; loads/stores in X86 mode, support is expected soon enough, for this reason the isel-fp64-to-sint-x86.mir test is added. ; RUN: llc < %s -mtriple=i686-- -mattr=+x87,-sse,-sse2 -global-isel -global-isel-abort=2 | FileCheck %s --check-prefixes X86,GISEL-X86 define i8 @test_float_to_int8(float %input) nounwind { -; X64-LABEL: test_float_to_int8: -; X64: # %bb.0: # %entry -; X64-NEXT: flds {{[0-9]+}}(%rsp) -; X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) -; X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax -; X64-NEXT: orl $3072, %eax # imm = 0xC00 -; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-NEXT: fistps -{{[0-9]+}}(%rsp) -; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax -; X64-NEXT: retq +; SDAG-X64-LABEL: test_float_to_int8: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: flds {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistps -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: retq ; -; X86-LABEL: test_float_to_int8: -; X86: # %bb.0: # %entry -; X86-NEXT: subl $8, %esp -; X86-NEXT: flds {{[0-9]+}}(%esp) -; X86-NEXT: fnstcw {{[0-9]+}}(%esp) -; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; X86-NEXT: orl $3072, %eax # imm = 0xC00 -; X86-NEXT: movw %ax, {{[0-9]+}}(%esp) -; X86-NEXT: fldcw {{[0-9]+}}(%esp) -; X86-NEXT: fistps {{[0-9]+}}(%esp) -; X86-NEXT: fldcw {{[0-9]+}}(%esp) -; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax -; X86-NEXT: addl $8, %esp -; X86-NEXT: retl +; GISEL-X64-LABEL: test_float_to_int8: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: flds {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistps -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: # kill: def $al killed $al killed $ax +; GISEL-X64-NEXT: retq +; +; SDAG-X86-LABEL: test_float_to_int8: +; SDAG-X86: # %bb.0: # %entry +; SDAG-X86-NEXT: subl $8, %esp +; SDAG-X86-NEXT: flds {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fnstcw {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; SDAG-X86-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fldcw {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fistps {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fldcw {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; SDAG-X86-NEXT: addl $8, %esp +; SDAG-X86-NEXT: retl +; +; GISEL-X86-LABEL: test_float_to_int8: +; GISEL-X86: # %bb.0: # %entry +; GISEL-X86-NEXT: subl $8, %esp +; GISEL-X86-NEXT: flds {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fnstcw {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fldcw {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fistps {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fldcw {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: # kill: def $al killed $al killed $ax +; GISEL-X86-NEXT: addl $8, %esp +; GISEL-X86-NEXT: retl entry: %conv = fptosi float %input to i8 ret i8 %conv } define i8 @test_longdouble_to_int8(x86_fp80 %input) nounwind { -; X64-LABEL: test_longdouble_to_int8: -; X64: # %bb.0: # %entry -; X64-NEXT: fldt {{[0-9]+}}(%rsp) -; X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) -; X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax -; X64-NEXT: orl $3072, %eax # imm = 0xC00 -; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-NEXT: fistps -{{[0-9]+}}(%rsp) -; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax -; X64-NEXT: retq +; SDAG-X64-LABEL: test_longdouble_to_int8: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistps -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: retq ; -; X86-LABEL: test_longdouble_to_int8: -; X86: # %bb.0: # %entry -; X86-NEXT: subl $8, %esp -; X86-NEXT: fldt {{[0-9]+}}(%esp) -; X86-NEXT: fnstcw {{[0-9]+}}(%esp) -; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; X86-NEXT: orl $3072, %eax # imm = 0xC00 -; X86-NEXT: movw %ax, {{[0-9]+}}(%esp) -; X86-NEXT: fldcw {{[0-9]+}}(%esp) -; X86-NEXT: fistps {{[0-9]+}}(%esp) -; X86-NEXT: fldcw {{[0-9]+}}(%esp) -; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax -; X86-NEXT: addl $8, %esp -; X86-NEXT: retl +; GISEL-X64-LABEL: test_longdouble_to_int8: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: fldt {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistps -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: # kill: def $al killed $al killed $ax +; GISEL-X64-NEXT: retq +; +; SDAG-X86-LABEL: test_longdouble_to_int8: +; SDAG-X86: # %bb.0: # %entry +; SDAG-X86-NEXT: subl $8, %esp +; SDAG-X86-NEXT: fldt {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fnstcw {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; SDAG-X86-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fldcw {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fistps {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fldcw {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; SDAG-X86-NEXT: addl $8, %esp +; SDAG-X86-NEXT: retl +; +; GISEL-X86-LABEL: test_longdouble_to_int8: +; GISEL-X86: # %bb.0: # %entry +; GISEL-X86-NEXT: subl $8, %esp +; GISEL-X86-NEXT: fldt {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fnstcw {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fldcw {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fistps {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fldcw {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: # kill: def $al killed $al killed $ax +; GISEL-X86-NEXT: addl $8, %esp +; GISEL-X86-NEXT: retl entry: %conv = fptosi x86_fp80 %input to i8 ret i8 %conv @@ -281,18 +343,32 @@ entry: } define i8 @test_double_to_int8(double %input) nounwind { -; X64-LABEL: test_double_to_int8: -; X64: # %bb.0: # %entry -; X64-NEXT: fldl {{[0-9]+}}(%rsp) -; X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) -; X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax -; X64-NEXT: orl $3072, %eax # imm = 0xC00 -; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-NEXT: fistps -{{[0-9]+}}(%rsp) -; X64-NEXT: fldcw -{{[0-9]+}}(%rsp) -; X64-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax -; X64-NEXT: retq +; SDAG-X64-LABEL: test_double_to_int8: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: fldl {{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fistps -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: movzbl -{{[0-9]+}}(%rsp), %eax +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_double_to_int8: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: fldl {{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fnstcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: orl $3072, %eax # imm = 0xC00 +; GISEL-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fistps -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fldcw -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: movzwl -{{[0-9]+}}(%rsp), %eax +; GISEL-X64-NEXT: # kill: def $al killed $al killed $ax +; GISEL-X64-NEXT: retq ; ; X86-LABEL: test_double_to_int8: ; X86: # %bb.0: # %entry @@ -416,8 +492,4 @@ entry: %conv = fptosi double %input to i64 ret i64 %conv } -;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: -; GISEL-X86: {{.*}} -; GISEL-X64: {{.*}} -; SDAG-X86: {{.*}} -; SDAG-X64: {{.*}} + diff --git a/llvm/test/CodeGen/X86/isel-sint-to-fp-x87.ll b/llvm/test/CodeGen/X86/isel-sint-to-fp-x87.ll index 6e8461598d5e8..98fa3c9541faa 100644 --- a/llvm/test/CodeGen/X86/isel-sint-to-fp-x87.ll +++ b/llvm/test/CodeGen/X86/isel-sint-to-fp-x87.ll @@ -2,29 +2,53 @@ ; NOTE: Fast Isel is not added because it does not support x87 stores. ; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel=0 | FileCheck %s --check-prefixes X64,SDAG-X64 -; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel -global-isel-abort=2 | FileCheck %s --check-prefixes X64,GISEL-X64 +; RUN: llc < %s -mtriple=x86_64-- -mattr=+x87,-sse,-sse2 -global-isel -global-isel-abort=1 | FileCheck %s --check-prefixes X64,GISEL-X64 ; RUN: llc < %s -mtriple=i686-- -mattr=+x87,-sse,-sse2 -global-isel=0 | FileCheck %s --check-prefixes X86,SDAG-X86 +; TODO: The last RUN line fails GISEL for f64/double cases and will fallback to DAG due to lack of support for +; loads/stores in X86 mode, support is expected soon enough, for this reason the isel-sint-to-fp64-x86.mir test is added. ; RUN: llc < %s -mtriple=i686-- -mattr=+x87,-sse,-sse2 -global-isel -global-isel-abort=2 | FileCheck %s --check-prefixes X86,GISEL-X86 define void @test_int8_to_float(i8 %x, ptr %p) nounwind { -; X64-LABEL: test_int8_to_float: -; X64: # %bb.0: # %entry -; X64-NEXT: movsbl %dil, %eax -; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-NEXT: filds -{{[0-9]+}}(%rsp) -; X64-NEXT: fstps (%rsi) -; X64-NEXT: retq +; SDAG-X64-LABEL: test_int8_to_float: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: movsbl %dil, %eax +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: filds -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fstps (%rsi) +; SDAG-X64-NEXT: retq ; -; X86-LABEL: test_int8_to_float: -; X86: # %bb.0: # %entry -; X86-NEXT: pushl %eax -; X86-NEXT: movsbl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movw %ax, {{[0-9]+}}(%esp) -; X86-NEXT: filds {{[0-9]+}}(%esp) -; X86-NEXT: fstps (%ecx) -; X86-NEXT: popl %eax -; X86-NEXT: retl +; GISEL-X64-LABEL: test_int8_to_float: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: shlw $8, %di +; GISEL-X64-NEXT: sarw $8, %di +; GISEL-X64-NEXT: movw %di, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: filds -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fstps (%rsi) +; GISEL-X64-NEXT: retq +; +; SDAG-X86-LABEL: test_int8_to_float: +; SDAG-X86: # %bb.0: # %entry +; SDAG-X86-NEXT: pushl %eax +; SDAG-X86-NEXT: movsbl {{[0-9]+}}(%esp), %eax +; SDAG-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; SDAG-X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: filds {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fstps (%ecx) +; SDAG-X86-NEXT: popl %eax +; SDAG-X86-NEXT: retl +; +; GISEL-X86-LABEL: test_int8_to_float: +; GISEL-X86: # %bb.0: # %entry +; GISEL-X86-NEXT: pushl %eax +; GISEL-X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; GISEL-X86-NEXT: shlw $8, %ax +; GISEL-X86-NEXT: sarw $8, %ax +; GISEL-X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: filds {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fstps (%ecx) +; GISEL-X86-NEXT: popl %eax +; GISEL-X86-NEXT: retl entry: %conv = sitofp i8 %x to float store float %conv, ptr %p, align 4 @@ -39,16 +63,27 @@ define void @test_int16_to_float(i16 %x, ptr %p) nounwind { ; X64-NEXT: fstps (%rsi) ; X64-NEXT: retq ; -; X86-LABEL: test_int16_to_float: -; X86: # %bb.0: # %entry -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movzwl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movw %cx, {{[0-9]+}}(%esp) -; X86-NEXT: filds {{[0-9]+}}(%esp) -; X86-NEXT: fstps (%eax) -; X86-NEXT: popl %eax -; X86-NEXT: retl +; SDAG-X86-LABEL: test_int16_to_float: +; SDAG-X86: # %bb.0: # %entry +; SDAG-X86-NEXT: pushl %eax +; SDAG-X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; SDAG-X86-NEXT: movzwl {{[0-9]+}}(%esp), %ecx +; SDAG-X86-NEXT: movw %cx, {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: filds {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: fstps (%eax) +; SDAG-X86-NEXT: popl %eax +; SDAG-X86-NEXT: retl +; +; GISEL-X86-LABEL: test_int16_to_float: +; GISEL-X86: # %bb.0: # %entry +; GISEL-X86-NEXT: pushl %eax +; GISEL-X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; GISEL-X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: filds {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: fstps (%ecx) +; GISEL-X86-NEXT: popl %eax +; GISEL-X86-NEXT: retl entry: %conv = sitofp i16 %x to float store float %conv, ptr %p, align 4 @@ -63,16 +98,27 @@ define void @test_int32_to_float(i32 %x, ptr %p) nounwind { ; X64-NEXT: fstps (%rsi) ; X64-NEXT: retq ; -; X86-LABEL: test_int32_to_float: -; X86: # %bb.0: # %entry -; X86-NEXT: pushl %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx -; X86-NEXT: movl %ecx, (%esp) -; X86-NEXT: fildl (%esp) -; X86-NEXT: fstps (%eax) -; X86-NEXT: popl %eax -; X86-NEXT: retl +; SDAG-X86-LABEL: test_int32_to_float: +; SDAG-X86: # %bb.0: # %entry +; SDAG-X86-NEXT: pushl %eax +; SDAG-X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; SDAG-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; SDAG-X86-NEXT: movl %ecx, (%esp) +; SDAG-X86-NEXT: fildl (%esp) +; SDAG-X86-NEXT: fstps (%eax) +; SDAG-X86-NEXT: popl %eax +; SDAG-X86-NEXT: retl +; +; GISEL-X86-LABEL: test_int32_to_float: +; GISEL-X86: # %bb.0: # %entry +; GISEL-X86-NEXT: pushl %eax +; GISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; GISEL-X86-NEXT: movl %eax, (%esp) +; GISEL-X86-NEXT: fildl (%esp) +; GISEL-X86-NEXT: fstps (%ecx) +; GISEL-X86-NEXT: popl %eax +; GISEL-X86-NEXT: retl entry: %conv = sitofp i32 %x to float store float %conv, ptr %p, align 4 @@ -100,21 +146,40 @@ entry: } define x86_fp80 @test_int8to_longdouble(i8 %a) nounwind { -; X64-LABEL: test_int8to_longdouble: -; X64: # %bb.0: -; X64-NEXT: movsbl %dil, %eax -; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-NEXT: filds -{{[0-9]+}}(%rsp) -; X64-NEXT: retq +; SDAG-X64-LABEL: test_int8to_longdouble: +; SDAG-X64: # %bb.0: +; SDAG-X64-NEXT: movsbl %dil, %eax +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: filds -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: retq ; -; X86-LABEL: test_int8to_longdouble: -; X86: # %bb.0: -; X86-NEXT: pushl %eax -; X86-NEXT: movsbl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movw %ax, {{[0-9]+}}(%esp) -; X86-NEXT: filds {{[0-9]+}}(%esp) -; X86-NEXT: popl %eax -; X86-NEXT: retl +; GISEL-X64-LABEL: test_int8to_longdouble: +; GISEL-X64: # %bb.0: +; GISEL-X64-NEXT: shlw $8, %di +; GISEL-X64-NEXT: sarw $8, %di +; GISEL-X64-NEXT: movw %di, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: filds -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: retq +; +; SDAG-X86-LABEL: test_int8to_longdouble: +; SDAG-X86: # %bb.0: +; SDAG-X86-NEXT: pushl %eax +; SDAG-X86-NEXT: movsbl {{[0-9]+}}(%esp), %eax +; SDAG-X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: filds {{[0-9]+}}(%esp) +; SDAG-X86-NEXT: popl %eax +; SDAG-X86-NEXT: retl +; +; GISEL-X86-LABEL: test_int8to_longdouble: +; GISEL-X86: # %bb.0: +; GISEL-X86-NEXT: pushl %eax +; GISEL-X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax +; GISEL-X86-NEXT: shlw $8, %ax +; GISEL-X86-NEXT: sarw $8, %ax +; GISEL-X86-NEXT: movw %ax, {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: filds {{[0-9]+}}(%esp) +; GISEL-X86-NEXT: popl %eax +; GISEL-X86-NEXT: retl %conv = sitofp i8 %a to x86_fp80 ret x86_fp80 %conv } @@ -174,13 +239,22 @@ define x86_fp80 @test_int64_to_longdouble(i64 %a, ptr %p) nounwind { define void @test_int8to_double(i8 %x, ptr %p) nounwind { -; X64-LABEL: test_int8to_double: -; X64: # %bb.0: # %entry -; X64-NEXT: movsbl %dil, %eax -; X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) -; X64-NEXT: filds -{{[0-9]+}}(%rsp) -; X64-NEXT: fstpl (%rsi) -; X64-NEXT: retq +; SDAG-X64-LABEL: test_int8to_double: +; SDAG-X64: # %bb.0: # %entry +; SDAG-X64-NEXT: movsbl %dil, %eax +; SDAG-X64-NEXT: movw %ax, -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: filds -{{[0-9]+}}(%rsp) +; SDAG-X64-NEXT: fstpl (%rsi) +; SDAG-X64-NEXT: retq +; +; GISEL-X64-LABEL: test_int8to_double: +; GISEL-X64: # %bb.0: # %entry +; GISEL-X64-NEXT: shlw $8, %di +; GISEL-X64-NEXT: sarw $8, %di +; GISEL-X64-NEXT: movw %di, -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: filds -{{[0-9]+}}(%rsp) +; GISEL-X64-NEXT: fstpl (%rsi) +; GISEL-X64-NEXT: retq ; ; X86-LABEL: test_int8to_double: ; X86: # %bb.0: # %entry @@ -265,8 +339,3 @@ entry: store double %conv, ptr %p, align 4 ret void } -;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: -; GISEL-X86: {{.*}} -; GISEL-X64: {{.*}} -; SDAG-X86: {{.*}} -; SDAG-X64: {{.*}}