diff options
author | Daniel Sanders <daniel.sanders@imgtec.com> | 2014-07-14 13:08:14 +0000 |
---|---|---|
committer | Daniel Sanders <daniel.sanders@imgtec.com> | 2014-07-14 13:08:14 +0000 |
commit | 7ddb0ab85f04f56371ae948052188d968725b8b7 (patch) | |
tree | 1e6a4c8d0784284e475f94b83ab343fae835d748 /llvm/lib | |
parent | d73e7cc8793c8501592161daa9ff307abc432155 (diff) | |
download | bcm5719-llvm-7ddb0ab85f04f56371ae948052188d968725b8b7.tar.gz bcm5719-llvm-7ddb0ab85f04f56371ae948052188d968725b8b7.zip |
[mips] For the FP64A ABI, odd-numbered double-precision moves must not use mtc1/mfc1.
Summary:
This is because the FP64A the hardware will redirect 32-bit reads/writes
from/to odd-numbered registers to the upper 32-bits of the corresponding
even register. In effect, simulating FR=0 mode when FR=0 mode is not
available.
Unfortunately, we have to make the decision to avoid mfc1/mtc1 before
register allocation so we currently do this for even registers too.
FPXX has a similar requirement on 32-bit architectures that lack
mfhc1/mthc1 so this patch also handles the affected moves from the FPU for
FPXX too. Moves to the FPU were supported by an earlier commit.
Differential Revision: http://reviews.llvm.org/D4484
llvm-svn: 212938
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/Mips/MipsMachineFunction.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsMachineFunction.h | 6 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsSEFrameLowering.cpp | 98 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsSEInstrInfo.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsSubtarget.cpp | 4 |
5 files changed, 119 insertions, 23 deletions
diff --git a/llvm/lib/Target/Mips/MipsMachineFunction.cpp b/llvm/lib/Target/Mips/MipsMachineFunction.cpp index a3306686fc4..bc896be4e1d 100644 --- a/llvm/lib/Target/Mips/MipsMachineFunction.cpp +++ b/llvm/lib/Target/Mips/MipsMachineFunction.cpp @@ -137,12 +137,12 @@ MachinePointerInfo MipsFunctionInfo::callPtrInfo(const GlobalValue *Val) { return MachinePointerInfo(E); } -int MipsFunctionInfo::getBuildPairF64_FI(const TargetRegisterClass *RC) { - if (BuildPairF64_FI == -1) { - BuildPairF64_FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(), - RC->getAlignment(), false); +int MipsFunctionInfo::getMoveF64ViaSpillFI(const TargetRegisterClass *RC) { + if (MoveF64ViaSpillFI == -1) { + MoveF64ViaSpillFI = MF.getFrameInfo()->CreateStackObject( + RC->getSize(), RC->getAlignment(), false); } - return BuildPairF64_FI; + return MoveF64ViaSpillFI; } void MipsFunctionInfo::anchor() { } diff --git a/llvm/lib/Target/Mips/MipsMachineFunction.h b/llvm/lib/Target/Mips/MipsMachineFunction.h index a667d43724c..61260e57815 100644 --- a/llvm/lib/Target/Mips/MipsMachineFunction.h +++ b/llvm/lib/Target/Mips/MipsMachineFunction.h @@ -55,7 +55,7 @@ public: MipsFunctionInfo(MachineFunction &MF) : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), Mips16SPAliasReg(0), VarArgsFrameIndex(0), CallsEhReturn(false), SaveS2(false), - BuildPairF64_FI(-1) {} + MoveF64ViaSpillFI(-1) {} ~MipsFunctionInfo(); @@ -97,7 +97,7 @@ public: void setSaveS2() { SaveS2 = true; } bool hasSaveS2() const { return SaveS2; } - int getBuildPairF64_FI(const TargetRegisterClass *RC); + int getMoveF64ViaSpillFI(const TargetRegisterClass *RC); std::map<const char *, const llvm::Mips16HardFloatInfo::FuncSignature *> StubsNeeded; @@ -141,7 +141,7 @@ private: /// FrameIndex for expanding BuildPairF64 nodes to spill and reload when the /// O32 FPXX ABI is enabled. -1 is used to denote invalid index. - int BuildPairF64_FI; + int MoveF64ViaSpillFI; /// MipsCallEntry maps. StringMap<const MipsCallEntry *> ExternalCallEntries; diff --git a/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp b/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp index f2276f19afa..d0a17cd834a 100644 --- a/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp +++ b/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp @@ -66,6 +66,8 @@ private: unsigned MFLoOpc); bool expandBuildPairF64(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, bool FP64) const; + bool expandExtractElementF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, bool FP64) const; MachineFunction &MF; MachineRegisterInfo &MRI; @@ -118,6 +120,14 @@ bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) { if (expandBuildPairF64(MBB, I, true)) MBB.erase(I); return false; + case Mips::ExtractElementF64: + if (expandExtractElementF64(MBB, I, false)) + MBB.erase(I); + return false; + case Mips::ExtractElementF64_64: + if (expandExtractElementF64(MBB, I, true)) + MBB.erase(I); + return false; case TargetOpcode::COPY: if (!expandCopy(MBB, I)) return false; @@ -269,9 +279,10 @@ bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, } /// 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. +/// expandBuildPairF64 does, for the case when ABI is fpxx and mthc1 is not +/// available and the case where the ABI is FP64A. 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 { @@ -280,10 +291,18 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, // // The case where dmtc1 is available doesn't need to be handled here // because it never creates a BuildPairF64 node. + // + // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence + // for odd-numbered double precision values (because the lower 32-bits is + // transferred with mtc1 which is redirected to the upper half of the even + // register). Unfortunately, we have to make this decision before register + // allocation so for now we use a spill/reload sequence for all + // double-precision values in regardless of being an odd/even register. const TargetMachine &TM = MF.getTarget(); - if (TM.getSubtarget<MipsSubtarget>().isABI_FPXX() - && !TM.getSubtarget<MipsSubtarget>().hasMTHC1()) { + const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); + if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || + (FP64 && !Subtarget.useOddSPReg())) { const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo*>(TM.getInstrInfo()); const MipsRegisterInfo &TRI = @@ -294,13 +313,18 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, unsigned HiReg = I->getOperand(2).getReg(); // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are - // the cases where mthc1 is not available). - assert(!TM.getSubtarget<MipsSubtarget>().isFP64bit()); + // the cases where mthc1 is not available). 64-bit architectures and + // MIPS32r2 or later can use FGR64 though. + assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() || + !Subtarget.isFP64bit()); const TargetRegisterClass *RC = &Mips::GPR32RegClass; - const TargetRegisterClass *RC2 = &Mips::AFGR64RegClass; + const TargetRegisterClass *RC2 = + FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; - int FI = MF.getInfo<MipsFunctionInfo>()->getBuildPairF64_FI(RC2); + // We re-use the same spill slot each time so that the stack frame doesn't + // grow too much in functions with a large number of moves. + int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC2); TII.storeRegToStack(MBB, I, LoReg, I->getOperand(1).isKill(), FI, RC, &TRI, 0); TII.storeRegToStack(MBB, I, HiReg, I->getOperand(2).isKill(), FI, RC, &TRI, @@ -312,6 +336,62 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, return false; } +/// This method expands the same instruction that MipsSEInstrInfo:: +/// expandExtractElementF64 does, for the case when ABI is fpxx and mfhc1 is not +/// available and the case where the ABI is FP64A. It is implemented here +/// because frame indexes are eliminated before MipsSEInstrInfo:: +/// expandExtractElementF64 is called. +bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + bool FP64) const { + // For fpxx and when mfhc1 is not available, use: + // spill + reload via ldc1 + // + // The case where dmfc1 is available doesn't need to be handled here + // because it never creates a ExtractElementF64 node. + // + // The FP64A ABI (fp64 with nooddspreg) must also use a spill/reload sequence + // for odd-numbered double precision values (because the lower 32-bits is + // transferred with mfc1 which is redirected to the upper half of the even + // register). Unfortunately, we have to make this decision before register + // allocation so for now we use a spill/reload sequence for all + // double-precision values in regardless of being an odd/even register. + + const TargetMachine &TM = MF.getTarget(); + const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); + if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || + (FP64 && !Subtarget.useOddSPReg())) { + const MipsSEInstrInfo &TII = + *static_cast<const MipsSEInstrInfo *>(TM.getInstrInfo()); + const MipsRegisterInfo &TRI = + *static_cast<const MipsRegisterInfo *>(TM.getRegisterInfo()); + + unsigned DstReg = I->getOperand(0).getReg(); + unsigned SrcReg = I->getOperand(1).getReg(); + unsigned N = I->getOperand(2).getImm(); + + // It should be impossible to have FGR64 on MIPS-II or MIPS32r1 (which are + // the cases where mfhc1 is not available). 64-bit architectures and + // MIPS32r2 or later can use FGR64 though. + assert(Subtarget.isGP64bit() || Subtarget.hasMTHC1() || + !Subtarget.isFP64bit()); + + const TargetRegisterClass *RC = + FP64 ? &Mips::FGR64RegClass : &Mips::AFGR64RegClass; + const TargetRegisterClass *RC2 = &Mips::GPR32RegClass; + + // We re-use the same spill slot each time so that the stack frame doesn't + // grow too much in functions with a large number of moves. + int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC); + TII.storeRegToStack(MBB, I, SrcReg, I->getOperand(1).isKill(), FI, RC, &TRI, + 0); + TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &TRI, N * 4); + return true; + } + + return false; +} + MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI) : MipsFrameLowering(STI, STI.stackAlignment()) {} diff --git a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp index d242659d076..26764611c50 100644 --- a/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -512,6 +512,7 @@ void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB, void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, bool FP64) const { + const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); unsigned DstReg = I->getOperand(0).getReg(); unsigned SrcReg = I->getOperand(1).getReg(); unsigned N = I->getOperand(2).getImm(); @@ -521,7 +522,15 @@ 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 && TM.getSubtarget<MipsSubtarget>().hasMTHC1()) { + // 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. @@ -543,6 +552,7 @@ void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB, void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, bool FP64) const { + const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); unsigned DstReg = I->getOperand(0).getReg(); unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); const MCInstrDesc& Mtc1Tdd = get(Mips::MTC1); @@ -564,10 +574,18 @@ void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, // 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 (TM.getSubtarget<MipsSubtarget>().hasMTHC1()) { + 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 @@ -582,7 +600,7 @@ void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, BuildMI(MBB, I, dl, get(FP64 ? Mips::MTHC1_D64 : Mips::MTHC1_D32), DstReg) .addReg(DstReg) .addReg(HiReg); - } else if (TM.getSubtarget<MipsSubtarget>().isABI_FPXX()) + } 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)) diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index 0254d4da4d2..902735d7810 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -153,9 +153,7 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, false); if (!isABI_O32() && !useOddSPReg()) - report_fatal_error("-mattr=+nooddspreg is not currently permitted for a " - "the O32 ABI.", - false); + report_fatal_error("-mattr=+nooddspreg requires the O32 ABI.", false); if (IsFPXX && (isABI_N32() || isABI_N64())) report_fatal_error("FPXX is not permitted for the N32/N64 ABI's.", false); |