X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsSEInstrInfo.cpp;h=786307b95f881585df43655ad10b7ed9897e57d8;hb=bd75a9292e761dcab32855e322d9985d7d787d1e;hp=374837e37d2c123cbf56b684737a8bffd3eb4e94;hpb=a6c3a4ee76ef8464d3c83472e15af521ade7eeb4;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index 374837e37d2..786307b95f8 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -24,16 +24,10 @@ using namespace llvm; -static cl::opt NoDPLoadStore("mno-ldc1-sdc1", cl::init(false), - cl::desc("Expand double precision loads and " - "stores to their single precision " - "counterparts.")); - -MipsSEInstrInfo::MipsSEInstrInfo(MipsTargetMachine &tm) - : MipsInstrInfo(tm, - tm.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J), - RI(*tm.getSubtargetImpl()), - IsN64(tm.getSubtarget().isABI_N64()) {} +MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI) + : MipsInstrInfo(STI, STI.getRelocationModel() == Reloc::PIC_ ? Mips::B + : Mips::J), + RI() {} const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { return RI; @@ -44,9 +38,8 @@ const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than loading from the stack slot. -unsigned MipsSEInstrInfo:: -isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const -{ +unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const { unsigned Opc = MI->getOpcode(); if ((Opc == Mips::LW) || (Opc == Mips::LD) || @@ -67,9 +60,8 @@ isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const /// the source reg along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than storing to the stack slot. -unsigned MipsSEInstrInfo:: -isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const -{ +unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const { unsigned Opc = MI->getOpcode(); if ((Opc == Mips::SW) || (Opc == Mips::SD) || @@ -89,19 +81,25 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, unsigned DestReg, unsigned SrcReg, bool KillSrc) const { unsigned Opc = 0, ZeroReg = 0; + bool isMicroMips = Subtarget.inMicroMipsMode(); if (Mips::GPR32RegClass.contains(DestReg)) { // Copy to CPU Reg. - if (Mips::GPR32RegClass.contains(SrcReg)) - Opc = Mips::ADDu, ZeroReg = Mips::ZERO; - else if (Mips::CCRRegClass.contains(SrcReg)) + if (Mips::GPR32RegClass.contains(SrcReg)) { + if (isMicroMips) + Opc = Mips::MOVE16_MM; + else + Opc = Mips::ADDu, ZeroReg = Mips::ZERO; + } else if (Mips::CCRRegClass.contains(SrcReg)) Opc = Mips::CFC1; else if (Mips::FGR32RegClass.contains(SrcReg)) Opc = Mips::MFC1; - else if (Mips::HI32RegClass.contains(SrcReg)) - Opc = Mips::MFHI, SrcReg = 0; - else if (Mips::LO32RegClass.contains(SrcReg)) - Opc = Mips::MFLO, SrcReg = 0; - else if (Mips::HI32DSPRegClass.contains(SrcReg)) + else if (Mips::HI32RegClass.contains(SrcReg)) { + Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI; + SrcReg = 0; + } else if (Mips::LO32RegClass.contains(SrcReg)) { + Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO; + SrcReg = 0; + } else if (Mips::HI32DSPRegClass.contains(SrcReg)) Opc = Mips::MFHI_DSP; else if (Mips::LO32DSPRegClass.contains(SrcReg)) Opc = Mips::MFLO_DSP; @@ -159,6 +157,10 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, else if (Mips::FGR64RegClass.contains(DestReg)) Opc = Mips::DMTC1; } + else if (Mips::MSA128BRegClass.contains(DestReg)) { // Copy to MSA reg + if (Mips::MSA128BRegClass.contains(SrcReg)) + Opc = Mips::MOVE_V; + } assert(Opc && "Cannot copy registers"); @@ -260,12 +262,37 @@ loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { MachineBasicBlock &MBB = *MI->getParent(); + bool isMicroMips = Subtarget.inMicroMipsMode(); + unsigned Opc; switch(MI->getDesc().getOpcode()) { default: return false; case Mips::RetRA: - expandRetRA(MBB, MI, Mips::RET); + expandRetRA(MBB, MI); + break; + case Mips::PseudoMFHI: + Opc = isMicroMips ? Mips::MFHI16_MM : Mips::MFHI; + expandPseudoMFHiLo(MBB, MI, Opc); + break; + case Mips::PseudoMFLO: + Opc = isMicroMips ? Mips::MFLO16_MM : Mips::MFLO; + expandPseudoMFHiLo(MBB, MI, Opc); + break; + case Mips::PseudoMFHI64: + expandPseudoMFHiLo(MBB, MI, Mips::MFHI64); + break; + case Mips::PseudoMFLO64: + expandPseudoMFHiLo(MBB, MI, Mips::MFLO64); + break; + case Mips::PseudoMTLOHI: + expandPseudoMTLoHi(MBB, MI, Mips::MTLO, Mips::MTHI, false); + break; + case Mips::PseudoMTLOHI64: + expandPseudoMTLoHi(MBB, MI, Mips::MTLO64, Mips::MTHI64, false); + break; + case Mips::PseudoMTLOHI_DSP: + expandPseudoMTLoHi(MBB, MI, Mips::MTLO_DSP, Mips::MTHI_DSP, true); break; case Mips::PseudoCVT_S_W: expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false); @@ -294,12 +321,6 @@ bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { case Mips::ExtractElementF64_64: expandExtractElementF64(MBB, MI, true); break; - case Mips::PseudoLDC1: - expandDPLoadStore(MBB, MI, Mips::LDC1, Mips::LWC1); - break; - case Mips::PseudoSDC1: - expandDPLoadStore(MBB, MI, Mips::SDC1, Mips::SWC1); - break; case Mips::MIPSeh_return32: case Mips::MIPSeh_return64: expandEhReturn(MBB, MI); @@ -329,6 +350,8 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { case Mips::BLEZ64: return Mips::BGTZ64; case Mips::BC1T: return Mips::BC1F; case Mips::BC1F: return Mips::BC1T; + case Mips::BEQZC_MM: return Mips::BNEZC_MM; + case Mips::BNEZC_MM: return Mips::BEQZC_MM; } } @@ -336,15 +359,18 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { - const MipsSubtarget &STI = TM.getSubtarget(); + MipsABIInfo ABI = Subtarget.getABI(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); - unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; - unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; + unsigned ADDu = ABI.GetPtrAdduOp(); + unsigned ADDiu = ABI.GetPtrAddiuOp(); + + if (Amount == 0) + return; if (isInt<16>(Amount))// addi sp, sp, amount BuildMI(MBB, I, DL, get(ADDiu), SP).addReg(SP).addImm(Amount); else { // Expand immediate that doesn't fit in 16-bit. - unsigned Reg = loadImmediate(Amount, MBB, I, DL, 0); + unsigned Reg = loadImmediate(Amount, MBB, I, DL, nullptr); BuildMI(MBB, I, DL, get(ADDu), SP).addReg(SP).addReg(Reg, RegState::Kill); } } @@ -356,7 +382,7 @@ MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB, MachineBasicBlock::iterator II, DebugLoc DL, unsigned *NewImm) const { MipsAnalyzeImmediate AnalyzeImm; - const MipsSubtarget &STI = TM.getSubtarget(); + const MipsSubtarget &STI = Subtarget; MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); unsigned Size = STI.isABI_N64() ? 64 : 32; unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi; @@ -399,14 +425,17 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::B || - Opc == Mips::J) ? + Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM) ? Opc : 0; } void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned Opc) const { - BuildMI(MBB, I, I->getDebugLoc(), get(Opc)).addReg(Mips::RA); + MachineBasicBlock::iterator I) const { + if (Subtarget.isGP64bit()) + BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn64)) + .addReg(Mips::RA_64); + else + BuildMI(MBB, I, I->getDebugLoc(), get(Mips::PseudoReturn)).addReg(Mips::RA); } std::pair @@ -421,6 +450,41 @@ MipsSEInstrInfo::compareOpndSize(unsigned Opc, return std::make_pair(DstRegSize > SrcRegSize, DstRegSize < SrcRegSize); } +void MipsSEInstrInfo::expandPseudoMFHiLo(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned NewOpc) const { + BuildMI(MBB, I, I->getDebugLoc(), get(NewOpc), I->getOperand(0).getReg()); +} + +void MipsSEInstrInfo::expandPseudoMTLoHi(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned LoOpc, + unsigned HiOpc, + bool HasExplicitDef) const { + // Expand + // lo_hi pseudomtlohi $gpr0, $gpr1 + // to these two instructions: + // mtlo $gpr0 + // mthi $gpr1 + + DebugLoc DL = I->getDebugLoc(); + const MachineOperand &SrcLo = I->getOperand(1), &SrcHi = I->getOperand(2); + MachineInstrBuilder LoInst = BuildMI(MBB, I, DL, get(LoOpc)); + MachineInstrBuilder HiInst = BuildMI(MBB, I, DL, get(HiOpc)); + LoInst.addReg(SrcLo.getReg(), getKillRegState(SrcLo.isKill())); + HiInst.addReg(SrcHi.getReg(), getKillRegState(SrcHi.isKill())); + + // Add lo/hi registers if the mtlo/hi instructions created have explicit + // def registers. + if (HasExplicitDef) { + unsigned DstReg = I->getOperand(0).getReg(); + unsigned DstLo = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo); + unsigned DstHi = getRegisterInfo().getSubReg(DstReg, Mips::sub_hi); + LoInst.addReg(DstLo, RegState::Define); + HiInst.addReg(DstHi, RegState::Define); + } +} + void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned CvtOpc, unsigned MovOpc, @@ -432,7 +496,8 @@ void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB, DebugLoc DL = I->getDebugLoc(); bool DstIsLarger, SrcIsLarger; - tie(DstIsLarger, SrcIsLarger) = compareOpndSize(CvtOpc, *MBB.getParent()); + std::tie(DstIsLarger, SrcIsLarger) = + compareOpndSize(CvtOpc, *MBB.getParent()); if (DstIsLarger) TmpReg = getRegisterInfo().getSubReg(DstReg, Mips::sub_lo); @@ -456,9 +521,30 @@ void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB, unsigned SubIdx = N ? Mips::sub_hi : Mips::sub_lo; unsigned SubReg = getRegisterInfo().getSubReg(SrcReg, SubIdx); - if (SubIdx == Mips::sub_hi && FP64) - BuildMI(MBB, I, dl, get(Mips::MFHC1), DstReg).addReg(SubReg); - else + // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload + // in MipsSEFrameLowering.cpp. + assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2())); + + // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload + // in MipsSEFrameLowering.cpp. + assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg())); + + if (SubIdx == Mips::sub_hi && Subtarget.hasMTHC1()) { + // FIXME: Strictly speaking MFHC1 only reads the top 32-bits however, we + // claim to read the whole 64-bits as part of a white lie used to + // temporarily work around a widespread bug in the -mfp64 support. + // The problem is that none of the 32-bit fpu ops mention the fact + // that they clobber the upper 32-bits of the 64-bit FPR. Fixing that + // requires a major overhaul of the FPU implementation which can't + // be done right now due to time constraints. + // MFHC1 is one of two instructions that are affected since they are + // the only instructions that don't read the lower 32-bits. + // We therefore pretend that it reads the bottom 32-bits to + // artificially create a dependency and prevent the scheduler + // changing the behaviour of the code. + BuildMI(MBB, I, dl, get(FP64 ? Mips::MFHC1_D64 : Mips::MFHC1_D32), DstReg) + .addReg(SrcReg); + } else BuildMI(MBB, I, dl, get(Mips::MFC1), DstReg).addReg(SubReg); } @@ -471,97 +557,83 @@ void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, DebugLoc dl = I->getDebugLoc(); const TargetRegisterInfo &TRI = getRegisterInfo(); - // mtc1 Lo, $fp - // mtc1 Hi, $fp + 1 + // When mthc1 is available, use: + // mtc1 Lo, $fp + // mthc1 Hi, $fp + // + // Otherwise, for O32 FPXX ABI: + // spill + reload via ldc1 + // This case is handled by the frame lowering code. + // + // Otherwise, for FP32: + // mtc1 Lo, $fp + // mtc1 Hi, $fp + 1 + // + // The case where dmtc1 is available doesn't need to be handled here + // because it never creates a BuildPairF64 node. + + // FPXX on MIPS-II or MIPS32r1 should have been handled with a spill/reload + // in MipsSEFrameLowering.cpp. + assert(!(Subtarget.isABI_FPXX() && !Subtarget.hasMips32r2())); + + // FP64A (FP64 with nooddspreg) should have been handled with a spill/reload + // in MipsSEFrameLowering.cpp. + assert(!(Subtarget.isFP64bit() && !Subtarget.useOddSPReg())); + BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_lo)) .addReg(LoReg); - if (FP64) - BuildMI(MBB, I, dl, get(Mips::MTHC1), TRI.getSubReg(DstReg, Mips::sub_hi)) - .addReg(HiReg); + if (Subtarget.hasMTHC1()) { + // FIXME: The .addReg(DstReg) is a white lie used to temporarily work + // around a widespread bug in the -mfp64 support. + // The problem is that none of the 32-bit fpu ops mention the fact + // that they clobber the upper 32-bits of the 64-bit FPR. Fixing that + // requires a major overhaul of the FPU implementation which can't + // be done right now due to time constraints. + // MTHC1 is one of two instructions that are affected since they are + // the only instructions that don't read the lower 32-bits. + // We therefore pretend that it reads the bottom 32-bits to + // artificially create a dependency and prevent the scheduler + // changing the behaviour of the code. + BuildMI(MBB, I, dl, get(FP64 ? Mips::MTHC1_D64 : Mips::MTHC1_D32), DstReg) + .addReg(DstReg) + .addReg(HiReg); + } else if (Subtarget.isABI_FPXX()) + llvm_unreachable("BuildPairF64 not expanded in frame lowering code!"); else BuildMI(MBB, I, dl, Mtc1Tdd, TRI.getSubReg(DstReg, Mips::sub_hi)) .addReg(HiReg); } -/// Add 4 to the displacement of operand MO. -static void fixDisp(MachineOperand &MO) { - switch (MO.getType()) { - default: - llvm_unreachable("Unhandled operand type."); - case MachineOperand::MO_Immediate: - MO.setImm(MO.getImm() + 4); - break; - case MachineOperand::MO_GlobalAddress: - case MachineOperand::MO_ConstantPoolIndex: - case MachineOperand::MO_BlockAddress: - case MachineOperand::MO_TargetIndex: - case MachineOperand::MO_ExternalSymbol: - MO.setOffset(MO.getOffset() + 4); - break; - } -} - -void MipsSEInstrInfo::expandDPLoadStore(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, - unsigned OpcD, unsigned OpcS) const { - // If NoDPLoadStore is false, just change the opcode. - if (!NoDPLoadStore) { - genInstrWithNewOpc(OpcD, I); - return; - } - - // Expand a double precision FP load or store to two single precision - // instructions. - - const TargetRegisterInfo &TRI = getRegisterInfo(); - const MachineOperand &ValReg = I->getOperand(0); - unsigned LoReg = TRI.getSubReg(ValReg.getReg(), Mips::sub_lo); - unsigned HiReg = TRI.getSubReg(ValReg.getReg(), Mips::sub_hi); - - if (!TM.getSubtarget().isLittle()) - std::swap(LoReg, HiReg); - - // Create an instruction which loads from or stores to the lower memory - // address. - MachineInstrBuilder MIB = genInstrWithNewOpc(OpcS, I); - MIB->getOperand(0).setReg(LoReg); - - // Create an instruction which loads from or stores to the higher memory - // address. - MIB = genInstrWithNewOpc(OpcS, I); - MIB->getOperand(0).setReg(HiReg); - fixDisp(MIB->getOperand(2)); -} - void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { // This pseudo instruction is generated as part of the lowering of // ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and // indirect jump to TargetReg - const MipsSubtarget &STI = TM.getSubtarget(); - unsigned ADDU = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; - unsigned JR = STI.isABI_N64() ? Mips::JR64 : Mips::JR; - unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; - unsigned RA = STI.isABI_N64() ? Mips::RA_64 : Mips::RA; - unsigned T9 = STI.isABI_N64() ? Mips::T9_64 : Mips::T9; - unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; + MipsABIInfo ABI = Subtarget.getABI(); + unsigned ADDU = ABI.GetPtrAdduOp(); + unsigned SP = Subtarget.isGP64bit() ? Mips::SP_64 : Mips::SP; + unsigned RA = Subtarget.isGP64bit() ? Mips::RA_64 : Mips::RA; + unsigned T9 = Subtarget.isGP64bit() ? Mips::T9_64 : Mips::T9; + unsigned ZERO = Subtarget.isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; unsigned OffsetReg = I->getOperand(0).getReg(); unsigned TargetReg = I->getOperand(1).getReg(); // addu $ra, $v0, $zero // addu $sp, $sp, $v1 - // jr $ra + // jr $ra (via RetRA) + const TargetMachine &TM = MBB.getParent()->getTarget(); if (TM.getRelocationModel() == Reloc::PIC_) - BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(ADDU), T9) - .addReg(TargetReg).addReg(ZERO); - BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(ADDU), RA) - .addReg(TargetReg).addReg(ZERO); - BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(ADDU), SP) - .addReg(SP).addReg(OffsetReg); - BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(JR)).addReg(RA); + BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), T9) + .addReg(TargetReg) + .addReg(ZERO); + BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), RA) + .addReg(TargetReg) + .addReg(ZERO); + BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), SP).addReg(SP).addReg(OffsetReg); + expandRetRA(MBB, I); } -const MipsInstrInfo *llvm::createMipsSEInstrInfo(MipsTargetMachine &TM) { - return new MipsSEInstrInfo(TM); +const MipsInstrInfo *llvm::createMipsSEInstrInfo(const MipsSubtarget &STI) { + return new MipsSEInstrInfo(STI); }