Index: lib/Target/Mips/MipsSEFrameLowering.cpp =================================================================== --- lib/Target/Mips/MipsSEFrameLowering.cpp +++ lib/Target/Mips/MipsSEFrameLowering.cpp @@ -64,6 +64,8 @@ bool expandCopy(MachineBasicBlock &MBB, Iter I); bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned MFHiOpc, unsigned MFLoOpc); + bool expandBuildPairF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, bool FP64) const; MachineFunction &MF; MachineRegisterInfo &MRI; @@ -108,6 +110,14 @@ case Mips::STORE_ACC128: expandStoreACC(MBB, I, Mips::PseudoMFHI64, Mips::PseudoMFLO64, 8); break; + case Mips::BuildPairF64: + if (expandBuildPairF64(MBB, I, false)) + MBB.erase(I); + return false; + case Mips::BuildPairF64_64: + if (expandBuildPairF64(MBB, I, true)) + MBB.erase(I); + return false; case TargetOpcode::COPY: if (!expandCopy(MBB, I)) return false; @@ -258,6 +268,44 @@ return true; } +/// expandBuildPairF64 - This method expands the same instruction that +/// MipsSEInstrInfo::expandBuildPairF64 does, for the case when ABI is fpxx +/// and mthc1 is not available. It is implemented here because frame indexes +/// are eliminated before MipsSEInstrInfo::expandBuildPairF64 is called. +bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + bool FP64) const { + // For fpxx and when mthc1 is not available, use: + // spill + reload via ldc1 + // + const TargetMachine &TM = MBB.getParent()->getTarget(); + bool HasMTHC1 = TM.getSubtarget().hasMips32r2() || + TM.getSubtarget().hasMips32r6(); + + if (TM.getSubtarget().isABI_FPXX() && !HasMTHC1) { + const MipsSEInstrInfo &TII = + *static_cast(TM.getInstrInfo()); + const MipsRegisterInfo &TRI = + *static_cast(TM.getRegisterInfo()); + + unsigned DstReg = I->getOperand(0).getReg(); + unsigned LoReg = I->getOperand(1).getReg(); + unsigned HiReg = I->getOperand(2).getReg(); + const TargetRegisterClass *RC = &Mips::GPR32RegClass; + const TargetRegisterClass *RC2 = &Mips::AFGR64RegClass; + + // TODO: Reuse the stack slot. + int FI = MF.getFrameInfo()->CreateStackObject(RC2->getSize(), + RC2->getAlignment(), false); + TII.storeRegToStack(MBB, I, LoReg, true, FI, RC, &TRI, 0); + TII.storeRegToStack(MBB, I, HiReg, true, FI, RC, &TRI, 4); + TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &TRI, 0); + return true; + } + + return false; +} + MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI) : MipsFrameLowering(STI, STI.stackAlignment()) {} Index: lib/Target/Mips/MipsSubtarget.h =================================================================== --- lib/Target/Mips/MipsSubtarget.h +++ lib/Target/Mips/MipsSubtarget.h @@ -169,7 +169,7 @@ bool isABI_N64() const { return MipsABI == N64; } bool isABI_N32() const { return MipsABI == N32; } bool isABI_O32() const { return MipsABI == O32; } - bool isABI_FPXX() const { return false; } // TODO: add check for FPXX + bool isABI_FPXX() const { return isABI_O32() && IsFPXX; } unsigned getTargetABI() const { return MipsABI; } /// This constructor initializes the data members to match that Index: test/CodeGen/Mips/fpxx.ll =================================================================== --- test/CodeGen/Mips/fpxx.ll +++ test/CodeGen/Mips/fpxx.ll @@ -0,0 +1,51 @@ +; RUN: llc -march=mipsel -mcpu=mips32 < %s | FileCheck %s -check-prefix=NO-FPXX +; RUN: llc -march=mipsel -mcpu=mips32 -mattr=fpxx < %s | FileCheck %s -check-prefix=FPXX + +define double @call1(double %d, ...) { + ret double %d + +; NO-FPXX: mtc1 $4, $f0 +; NO-FPXX: mtc1 $5, $f1 + +; FPXX: addiu $sp, $sp, -8 +; FPXX: sw $4, 0($sp) +; FPXX: sw $5, 4($sp) +; FPXX: ldc1 $f0, 0($sp) +} + +define double @call2(i32 %i, double %d) { + ret double %d + +; NO-FPXX: mtc1 $6, $f0 +; NO-FPXX: mtc1 $7, $f1 + +; FPXX: addiu $sp, $sp, -8 +; FPXX: sw $6, 0($sp) +; FPXX: sw $7, 4($sp) +; FPXX: ldc1 $f0, 0($sp) +} + +define double @call3(float %f1, float %f2, double %d) { + ret double %d + +; NO-FPXX: mtc1 $6, $f0 +; NO-FPXX: mtc1 $7, $f1 + +; FPXX: addiu $sp, $sp, -8 +; FPXX: sw $6, 0($sp) +; FPXX: sw $7, 4($sp) +; FPXX: ldc1 $f0, 0($sp) +} + +define double @call4(float %f, double %d, ...) { + ret double %d + +; NO-FPXX: mtc1 $6, $f0 +; NO-FPXX: mtc1 $7, $f1 + +; FPXX: addiu $sp, $sp, -8 +; FPXX: sw $6, 0($sp) +; FPXX: sw $7, 4($sp) +; FPXX: ldc1 $f0, 0($sp) +} +