diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/Mips/MipsInstrFPU.td | 14 | ||||
-rw-r--r-- | lib/Target/Mips/MipsSEInstrInfo.cpp | 62 | ||||
-rw-r--r-- | lib/Target/Mips/MipsSEInstrInfo.h | 3 |
3 files changed, 75 insertions, 4 deletions
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 6b23057c9c..5fa79cb159 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -154,6 +154,7 @@ class LW_FT<string opstr, RegisterClass RC, InstrItinClass Itin, InstSE<(outs RC:$rt), (ins MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"), [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI> { let DecoderMethod = "DecodeFMem"; + let mayLoad = 1; } class SW_FT<string opstr, RegisterClass RC, InstrItinClass Itin, @@ -161,6 +162,7 @@ class SW_FT<string opstr, RegisterClass RC, InstrItinClass Itin, InstSE<(outs), (ins RC:$rt, MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"), [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI> { let DecoderMethod = "DecodeFMem"; + let mayStore = 1; } class MADDS_FT<string opstr, RegisterClass RC, InstrItinClass Itin, @@ -314,8 +316,12 @@ let Predicates = [NotN64, HasMips64, HasStdEnc], } let Predicates = [NotN64, NotMips64, HasStdEnc] in { - def LDC1 : LW_FT<"ldc1", AFGR64, IILoad, mem, load>, LW_FM<0x35>; - def SDC1 : SW_FT<"sdc1", AFGR64, IIStore, mem, store>, LW_FM<0x3d>; + let isPseudo = 1, isCodeGenOnly = 1 in { + def PseudoLDC1 : LW_FT<"", AFGR64, IILoad, mem, load>; + def PseudoSDC1 : SW_FT<"", AFGR64, IIStore, mem, store>; + } + def LDC1 : LW_FT<"ldc1", AFGR64, IILoad, mem>, LW_FM<0x35>; + def SDC1 : SW_FT<"sdc1", AFGR64, IIStore, mem>, LW_FM<0x3d>; } // Indexed loads and stores. @@ -523,7 +529,7 @@ let AddedComplexity = 40 in { } let Predicates = [NotN64, NotMips64, HasStdEnc] in { - def : LoadRegImmPat<LDC1, f64, load>; - def : StoreRegImmPat<SDC1, f64>; + def : LoadRegImmPat<PseudoLDC1, f64, load>; + def : StoreRegImmPat<PseudoSDC1, f64>; } } diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index 4183a72940..12ed1bc186 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -18,11 +18,17 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; +static cl::opt<bool> 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), @@ -253,6 +259,12 @@ bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { case Mips::ExtractElementF64: expandExtractElementF64(MBB, MI); 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); @@ -393,6 +405,56 @@ void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, .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_fpeven); + unsigned HiReg = TRI.getSubReg(ValReg.getReg(), Mips::sub_fpodd); + + if (!TM.getSubtarget<MipsSubtarget>().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 diff --git a/lib/Target/Mips/MipsSEInstrInfo.h b/lib/Target/Mips/MipsSEInstrInfo.h index 821d751c6d..416fff8a60 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.h +++ b/lib/Target/Mips/MipsSEInstrInfo.h @@ -87,6 +87,9 @@ private: MachineBasicBlock::iterator I) const; void expandBuildPairF64(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; + void expandDPLoadStore(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, unsigned OpcD, + unsigned OpcS) const; void expandEhReturn(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; }; |