summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorReed Kotler <rkotler@mips.com>2013-02-08 03:57:41 +0000
committerReed Kotler <rkotler@mips.com>2013-02-08 03:57:41 +0000
commit61b97b8c1721ba45e5c10ca307ceebe1efdf72a9 (patch)
treea02cefffc029f07e95256f86a4c56c16f633a2d5 /lib
parentd2bcda7706cc2a6caf3b4b304b39a9649c703278 (diff)
downloadllvm-61b97b8c1721ba45e5c10ca307ceebe1efdf72a9.tar.gz
llvm-61b97b8c1721ba45e5c10ca307ceebe1efdf72a9.tar.bz2
llvm-61b97b8c1721ba45e5c10ca307ceebe1efdf72a9.tar.xz
When Mips16 frames grow large, the immediate field may exceed the maximum
allowed size for the instruction. This code uses RegScavenger to fix this. We sometimes need 2 registers for Mips16 so we must handle things differently than how register scavenger is normally used. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174696 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.cpp75
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.h12
-rw-r--r--lib/Target/Mips/Mips16RegisterInfo.cpp13
3 files changed, 90 insertions, 10 deletions
diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp
index 117faea86f..9f27ac3517 100644
--- a/lib/Target/Mips/Mips16InstrInfo.cpp
+++ b/lib/Target/Mips/Mips16InstrInfo.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
@@ -306,11 +307,79 @@ void Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
/// This function generates the sequence of instructions needed to get the
/// result of adding register REG and immediate IMM.
unsigned
-Mips16InstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
+Mips16InstrInfo::loadImmediate(unsigned FrameReg,
+ int64_t Imm, MachineBasicBlock &MBB,
MachineBasicBlock::iterator II, DebugLoc DL,
- unsigned *NewImm) const {
+ unsigned &NewImm) const {
+ //
+ // given original instruction is:
+ // Instr rx, T[offset] where offset is too big.
+ //
+ // lo = offset & 0xFFFF
+ // hi = ((offset >> 16) + (lo >> 15)) & 0xFFFF;
+ //
+ // let T = temporary register
+ // li T, hi
+ // shl T, 16
+ // add T, Rx, T
+ //
+ RegScavenger rs;
+ int32_t lo = Imm & 0xFFFF;
+ int32_t hi = ((Imm >> 16) + (lo >> 15)) & 0xFFFF;
+ NewImm = lo;
+ unsigned Reg =0;
+ unsigned SpReg = 0;
+ rs.enterBasicBlock(&MBB);
+ rs.forward(II);
+ //
+ // we use T0 for the first register, if we need to save something away.
+ // we use T1 for the second register, if we need to save something away.
+ //
+ unsigned FirstRegSaved =0, SecondRegSaved=0;
+ unsigned FirstRegSavedTo = 0, SecondRegSavedTo = 0;
+
+ Reg = rs.FindUnusedReg(&Mips::CPU16RegsRegClass);
+ if (Reg == 0) {
+ FirstRegSaved = Reg = Mips::V0;
+ FirstRegSavedTo = Mips::T0;
+ copyPhysReg(MBB, II, DL, FirstRegSavedTo, FirstRegSaved, true);
+ }
+ else
+ rs.setUsed(Reg);
+ BuildMI(MBB, II, DL, get(Mips::LiRxImmX16), Reg).addImm(hi);
+ BuildMI(MBB, II, DL, get(Mips::SllX16), Reg).addReg(Reg).
+ addImm(16);
+ if (FrameReg == Mips::SP) {
+ SpReg = rs.FindUnusedReg(&Mips::CPU16RegsRegClass);
+ if (SpReg == 0) {
+ if (Reg != Mips::V1) {
+ SecondRegSaved = SpReg = Mips::V1;
+ SecondRegSavedTo = Mips::T1;
+ }
+ else {
+ SecondRegSaved = SpReg = Mips::V0;
+ SecondRegSavedTo = Mips::T0;
+ }
+ copyPhysReg(MBB, II, DL, SecondRegSavedTo, SecondRegSaved, true);
+ }
+ else
+ rs.setUsed(SpReg);
- return 0;
+ copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false);
+ BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(SpReg)
+ .addReg(Reg);
+ }
+ else
+ BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(FrameReg)
+ .addReg(Reg, RegState::Kill);
+ if (FirstRegSaved || SecondRegSaved) {
+ II = llvm::next(II);
+ if (FirstRegSaved)
+ copyPhysReg(MBB, II, DL, FirstRegSaved, FirstRegSavedTo, true);
+ if (SecondRegSaved)
+ copyPhysReg(MBB, II, DL, SecondRegSaved, SecondRegSavedTo, true);
+ }
+ return Reg;
}
unsigned Mips16InstrInfo::GetAnalyzableBrOpc(unsigned Opc) const {
diff --git a/lib/Target/Mips/Mips16InstrInfo.h b/lib/Target/Mips/Mips16InstrInfo.h
index 3704e2573f..26a5a5e5fb 100644
--- a/lib/Target/Mips/Mips16InstrInfo.h
+++ b/lib/Target/Mips/Mips16InstrInfo.h
@@ -77,12 +77,14 @@ public:
void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
- /// Emit a series of instructions to load an immediate. If NewImm is a
- /// non-NULL parameter, the last instruction is not emitted, but instead
- /// its immediate operand is returned in NewImm.
- unsigned loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
+ /// Emit a series of instructions to load an immediate.
+ // This is to adjust some FrameReg. We return the new register to be used
+ // in place of FrameReg and the adjusted immediate field (&NewImm)
+ //
+ unsigned loadImmediate(unsigned FrameReg,
+ int64_t Imm, MachineBasicBlock &MBB,
MachineBasicBlock::iterator II, DebugLoc DL,
- unsigned *NewImm) const;
+ unsigned &NewImm) const;
private:
virtual unsigned GetAnalyzableBrOpc(unsigned Opc) const;
diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp
index c2e09a7206..a181a34cbd 100644
--- a/lib/Target/Mips/Mips16RegisterInfo.cpp
+++ b/lib/Target/Mips/Mips16RegisterInfo.cpp
@@ -1,3 +1,4 @@
+
//===-- Mips16RegisterInfo.cpp - MIPS16 Register Information -== ----------===//
//
// The LLVM Compiler Infrastructure
@@ -12,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "Mips16RegisterInfo.h"
+#include "Mips16InstrInfo.h"
#include "Mips.h"
#include "Mips16InstrInfo.h"
#include "MipsAnalyzeImmediate.h"
@@ -23,6 +25,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/DebugInfo.h"
#include "llvm/IR/Constants.h"
@@ -140,6 +143,7 @@ void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
// by adding the size of the stack:
// incoming argument, callee-saved register location or local variable.
int64_t Offset;
+ bool IsKill = false;
Offset = SPOffset + (int64_t)StackSize;
Offset += MI.getOperand(OpNo + 1).getImm();
@@ -148,9 +152,14 @@ void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
if (!MI.isDebugValue() && ( ((FrameReg != Mips::SP) && !isInt<16>(Offset)) ||
((FrameReg == Mips::SP) && !isInt<15>(Offset)) )) {
- llvm_unreachable("frame offset does not fit in instruction");
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc DL = II->getDebugLoc();
+ unsigned NewImm;
+ FrameReg = TII.loadImmediate(FrameReg, Offset, MBB, II, DL, NewImm);
+ Offset = SignExtend64<16>(NewImm);
+ IsKill = true;
}
- MI.getOperand(OpNo).ChangeToRegister(FrameReg, false);
+ MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill);
MI.getOperand(OpNo + 1).ChangeToImmediate(Offset);