Index: llvm/trunk/lib/Target/Mips/MipsInstructionSelector.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsInstructionSelector.cpp +++ llvm/trunk/lib/Target/Mips/MipsInstructionSelector.cpp @@ -320,6 +320,41 @@ I.eraseFromParent(); return true; } + case G_FCONSTANT: { + const APFloat &FPimm = I.getOperand(1).getFPImm()->getValueAPF(); + APInt APImm = FPimm.bitcastToAPInt(); + unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits(); + + if (Size == 32) { + unsigned GPRReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); + MachineIRBuilder B(I); + if (!materialize32BitImm(GPRReg, APImm, B)) + return false; + + MachineInstrBuilder MTC1 = + B.buildInstr(Mips::MTC1, {I.getOperand(0).getReg()}, {GPRReg}); + if (!MTC1.constrainAllUses(TII, TRI, RBI)) + return false; + } + if (Size == 64) { + unsigned GPRRegHigh = MRI.createVirtualRegister(&Mips::GPR32RegClass); + unsigned GPRRegLow = MRI.createVirtualRegister(&Mips::GPR32RegClass); + MachineIRBuilder B(I); + if (!materialize32BitImm(GPRRegHigh, APImm.getHiBits(32).trunc(32), B)) + return false; + if (!materialize32BitImm(GPRRegLow, APImm.getLoBits(32).trunc(32), B)) + return false; + + MachineInstrBuilder PairF64 = B.buildInstr( + STI.isFP64bit() ? Mips::BuildPairF64_64 : Mips::BuildPairF64, + {I.getOperand(0).getReg()}, {GPRRegLow, GPRRegHigh}); + if (!PairF64.constrainAllUses(TII, TRI, RBI)) + return false; + } + + I.eraseFromParent(); + return true; + } case G_GLOBAL_VALUE: { if (MF.getTarget().isPositionIndependent()) return false; Index: llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp +++ llvm/trunk/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -81,6 +81,9 @@ .legalFor({s32}) .clampScalar(0, s32, s32); + getActionDefinitionsBuilder(G_FCONSTANT) + .legalFor({s32, s64}); + getActionDefinitionsBuilder(G_GEP) .legalFor({{p0, s32}}); Index: llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp =================================================================== --- llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp +++ llvm/trunk/lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -24,22 +24,40 @@ namespace Mips { enum PartialMappingIdx { PMI_GPR, + PMI_SPR, + PMI_DPR, PMI_Min = PMI_GPR, }; RegisterBankInfo::PartialMapping PartMappings[]{ - {0, 32, GPRBRegBank} + {0, 32, GPRBRegBank}, + {0, 32, FPRBRegBank}, + {0, 64, FPRBRegBank} }; -enum ValueMappingIdx { InvalidIdx = 0, GPRIdx = 1 }; +enum ValueMappingIdx { + InvalidIdx = 0, + GPRIdx = 1, + SPRIdx = 4, + DPRIdx = 7 +}; RegisterBankInfo::ValueMapping ValueMappings[] = { // invalid {nullptr, 0}, - // 3 operands in GPRs + // up to 3 operands in GPRs + {&PartMappings[PMI_GPR - PMI_Min], 1}, {&PartMappings[PMI_GPR - PMI_Min], 1}, {&PartMappings[PMI_GPR - PMI_Min], 1}, - {&PartMappings[PMI_GPR - PMI_Min], 1}}; + // up to 3 ops operands FPRs - single precission + {&PartMappings[PMI_SPR - PMI_Min], 1}, + {&PartMappings[PMI_SPR - PMI_Min], 1}, + {&PartMappings[PMI_SPR - PMI_Min], 1}, + // up to 3 ops operands FPRs - double precission + {&PartMappings[PMI_DPR - PMI_Min], 1}, + {&PartMappings[PMI_DPR - PMI_Min], 1}, + {&PartMappings[PMI_DPR - PMI_Min], 1} +}; } // end namespace Mips } // end namespace llvm @@ -76,6 +94,8 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { unsigned Opc = MI.getOpcode(); + const MachineFunction &MF = *MI.getParent()->getParent(); + const MachineRegisterInfo &MRI = MF.getRegInfo(); const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI); if (Mapping.isValid()) @@ -109,6 +129,15 @@ case G_UREM: OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; break; + case G_FCONSTANT: { + LLT Ty = MRI.getType(MI.getOperand(0).getReg()); + unsigned Size = Ty.getSizeInBits(); + const RegisterBankInfo::ValueMapping *FPRValueMapping = + Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] + : &Mips::ValueMappings[Mips::DPRIdx]; + OperandsMapping = getOperandsMapping({FPRValueMapping, nullptr}); + break; + } case G_CONSTANT: case G_FRAME_INDEX: case G_GLOBAL_VALUE: Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/instruction-select/float_constants.mir =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/instruction-select/float_constants.mir +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/instruction-select/float_constants.mir @@ -0,0 +1,64 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP32 +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP64 +--- | + + define void @e_single_precision() {entry: ret void} + define void @e_double_precision() {entry: ret void} + +... +--- +name: e_single_precision +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + ; FP32-LABEL: name: e_single_precision + ; FP32: [[LUi:%[0-9]+]]:gpr32 = LUi 16429 + ; FP32: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 63572 + ; FP32: [[MTC1_:%[0-9]+]]:fgr32 = MTC1 [[ORi]] + ; FP32: $f0 = COPY [[MTC1_]] + ; FP32: RetRA implicit $f0 + ; FP64-LABEL: name: e_single_precision + ; FP64: [[LUi:%[0-9]+]]:gpr32 = LUi 16429 + ; FP64: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 63572 + ; FP64: [[MTC1_:%[0-9]+]]:fgr32 = MTC1 [[ORi]] + ; FP64: $f0 = COPY [[MTC1_]] + ; FP64: RetRA implicit $f0 + %0:fprb(s32) = G_FCONSTANT float 0x4005BF0A80000000 + $f0 = COPY %0(s32) + RetRA implicit $f0 + +... +--- +name: e_double_precision +alignment: 2 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + ; FP32-LABEL: name: e_double_precision + ; FP32: [[LUi:%[0-9]+]]:gpr32 = LUi 16389 + ; FP32: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 48906 + ; FP32: [[LUi1:%[0-9]+]]:gpr32 = LUi 35604 + ; FP32: [[ORi1:%[0-9]+]]:gpr32 = ORi [[LUi1]], 22377 + ; FP32: [[BuildPairF64_:%[0-9]+]]:afgr64 = BuildPairF64 [[ORi1]], [[ORi]] + ; FP32: $d0 = COPY [[BuildPairF64_]] + ; FP32: RetRA implicit $d0 + ; FP64-LABEL: name: e_double_precision + ; FP64: [[LUi:%[0-9]+]]:gpr32 = LUi 16389 + ; FP64: [[ORi:%[0-9]+]]:gpr32 = ORi [[LUi]], 48906 + ; FP64: [[LUi1:%[0-9]+]]:gpr32 = LUi 35604 + ; FP64: [[ORi1:%[0-9]+]]:gpr32 = ORi [[LUi1]], 22377 + ; FP64: [[BuildPairF64_64_:%[0-9]+]]:fgr64 = BuildPairF64_64 [[ORi1]], [[ORi]] + ; FP64: $d0 = COPY [[BuildPairF64_64_]] + ; FP64: RetRA implicit $d0 + %0:fprb(s64) = G_FCONSTANT double 0x4005BF0A8B145769 + $d0 = COPY %0(s64) + RetRA implicit $d0 + +... + Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/float_constants.mir =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/float_constants.mir +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/legalizer/float_constants.mir @@ -0,0 +1,49 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP32 +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP64 + +--- | + + define void @e_single_precision() {entry: ret void} + define void @e_double_precision() {entry: ret void} + +... +--- +name: e_single_precision +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + ; FP32-LABEL: name: e_single_precision + ; FP32: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x4005BF0A80000000 + ; FP32: $f0 = COPY [[C]](s32) + ; FP32: RetRA implicit $f0 + ; FP64-LABEL: name: e_single_precision + ; FP64: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x4005BF0A80000000 + ; FP64: $f0 = COPY [[C]](s32) + ; FP64: RetRA implicit $f0 + %0:_(s32) = G_FCONSTANT float 0x4005BF0A80000000 + $f0 = COPY %0(s32) + RetRA implicit $f0 + +... +--- +name: e_double_precision +alignment: 2 +tracksRegLiveness: true +body: | + bb.1.entry: + ; FP32-LABEL: name: e_double_precision + ; FP32: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x4005BF0A8B145769 + ; FP32: $d0 = COPY [[C]](s64) + ; FP32: RetRA implicit $d0 + ; FP64-LABEL: name: e_double_precision + ; FP64: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 0x4005BF0A8B145769 + ; FP64: $d0 = COPY [[C]](s64) + ; FP64: RetRA implicit $d0 + %0:_(s64) = G_FCONSTANT double 0x4005BF0A8B145769 + $d0 = COPY %0(s64) + RetRA implicit $d0 + +... + Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/float_constants.ll =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/float_constants.ll +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/llvm-ir/float_constants.ll @@ -0,0 +1,41 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32,FP32 +; RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -global-isel -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=MIPS32,FP64 + +define float @e_single_precision() { +; MIPS32-LABEL: e_single_precision: +; MIPS32: # %bb.0: # %entry +; MIPS32-NEXT: lui $1, 16429 +; MIPS32-NEXT: ori $1, $1, 63572 +; MIPS32-NEXT: mtc1 $1, $f0 +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +entry: + ret float 0x4005BF0A80000000 +} + +define double @e_double_precision() { +; FP32-LABEL: e_double_precision: +; FP32: # %bb.0: # %entry +; FP32-NEXT: lui $1, 16389 +; FP32-NEXT: ori $1, $1, 48906 +; FP32-NEXT: lui $2, 35604 +; FP32-NEXT: ori $2, $2, 22377 +; FP32-NEXT: mtc1 $2, $f0 +; FP32-NEXT: mtc1 $1, $f1 +; FP32-NEXT: jr $ra +; FP32-NEXT: nop +; +; FP64-LABEL: e_double_precision: +; FP64: # %bb.0: # %entry +; FP64-NEXT: lui $1, 16389 +; FP64-NEXT: ori $1, $1, 48906 +; FP64-NEXT: lui $2, 35604 +; FP64-NEXT: ori $2, $2, 22377 +; FP64-NEXT: mtc1 $2, $f0 +; FP64-NEXT: mthc1 $1, $f0 +; FP64-NEXT: jr $ra +; FP64-NEXT: nop +entry: + ret double 0x4005BF0A8B145769 +} Index: llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/float_constants.mir =================================================================== --- llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/float_constants.mir +++ llvm/trunk/test/CodeGen/Mips/GlobalISel/regbankselect/float_constants.mir @@ -0,0 +1,50 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP32 +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mattr=+fp64,+mips32r2 -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=FP64 + +--- | + + define void @e_single_precision() {entry: ret void} + define void @e_double_precision() {entry: ret void} + +... +--- +name: e_single_precision +alignment: 2 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + ; FP32-LABEL: name: e_single_precision + ; FP32: [[C:%[0-9]+]]:fprb(s32) = G_FCONSTANT float 0x4005BF0A80000000 + ; FP32: $f0 = COPY [[C]](s32) + ; FP32: RetRA implicit $f0 + ; FP64-LABEL: name: e_single_precision + ; FP64: [[C:%[0-9]+]]:fprb(s32) = G_FCONSTANT float 0x4005BF0A80000000 + ; FP64: $f0 = COPY [[C]](s32) + ; FP64: RetRA implicit $f0 + %0:_(s32) = G_FCONSTANT float 0x4005BF0A80000000 + $f0 = COPY %0(s32) + RetRA implicit $f0 + +... +--- +name: e_double_precision +alignment: 2 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + ; FP32-LABEL: name: e_double_precision + ; FP32: [[C:%[0-9]+]]:fprb(s64) = G_FCONSTANT double 0x4005BF0A8B145769 + ; FP32: $d0 = COPY [[C]](s64) + ; FP32: RetRA implicit $d0 + ; FP64-LABEL: name: e_double_precision + ; FP64: [[C:%[0-9]+]]:fprb(s64) = G_FCONSTANT double 0x4005BF0A8B145769 + ; FP64: $d0 = COPY [[C]](s64) + ; FP64: RetRA implicit $d0 + %0:_(s64) = G_FCONSTANT double 0x4005BF0A8B145769 + $d0 = COPY %0(s64) + RetRA implicit $d0 + +...