summaryrefslogtreecommitdiff
path: root/lib/Target/Mips/MipsSEInstrInfo.cpp
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@mips.com>2013-05-13 18:23:35 +0000
committerAkira Hatanaka <ahatanaka@mips.com>2013-05-13 18:23:35 +0000
commit42f562a1694d24b41f36bbb4d4a086a2a470c625 (patch)
tree77e78bd7a2da75ad5133bb5924b6e0a9098bfad1 /lib/Target/Mips/MipsSEInstrInfo.cpp
parent4b6b53b0cec4fcf4d570daed3be41d6147d05224 (diff)
downloadllvm-42f562a1694d24b41f36bbb4d4a086a2a470c625.tar.gz
llvm-42f562a1694d24b41f36bbb4d4a086a2a470c625.tar.bz2
llvm-42f562a1694d24b41f36bbb4d4a086a2a470c625.tar.xz
[mips] Add option -mno-ldc1-sdc1.
This option is used when the user wants to avoid emitting double precision FP loads and stores. Double precision FP loads and stores are expanded to single precision instructions after register allocation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181718 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/Mips/MipsSEInstrInfo.cpp')
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.cpp62
1 files changed, 62 insertions, 0 deletions
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