aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Cardoso Lopes <bruno.cardoso@gmail.com>2007-11-05 03:02:32 +0000
committerBruno Cardoso Lopes <bruno.cardoso@gmail.com>2007-11-05 03:02:32 +0000
commitc7db5618f9e5e708b87d9ae6595b3fd510a2a0c0 (patch)
tree9cec3321f14a2ac587bc43aa4f2c0114a373377d
parent90a52145aba097dffcf92080975749778201f16c (diff)
downloadexternal_llvm-c7db5618f9e5e708b87d9ae6595b3fd510a2a0c0.zip
external_llvm-c7db5618f9e5e708b87d9ae6595b3fd510a2a0c0.tar.gz
external_llvm-c7db5618f9e5e708b87d9ae6595b3fd510a2a0c0.tar.bz2
Added support for PIC code with "explicit relocations" *only*.
Removed all macro code for PIC (goodbye "la"). Support tested with shootout bench. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43697 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp44
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp74
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp93
-rw-r--r--lib/Target/Mips/MipsISelLowering.h8
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td49
-rw-r--r--lib/Target/Mips/MipsMachineFunction.h20
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp22
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.h4
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp5
9 files changed, 215 insertions, 104 deletions
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 4ed3f64..2dc9c2f 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -250,7 +250,7 @@ emitFunctionStart(MachineFunction &MF)
emitMaskDirective(MF);
emitFMaskDirective(MF);
- if (MF.getTarget().getRelocationModel() == Reloc::Static) {
+ if (TM.getRelocationModel() == Reloc::Static) {
emitSetDirective(NOREORDER);
emitSetDirective(NOMACRO);
}
@@ -262,7 +262,7 @@ emitFunctionStart(MachineFunction &MF)
void MipsAsmPrinter::
emitFunctionEnd(MachineFunction &MF)
{
- if (MF.getTarget().getRelocationModel() == Reloc::Static) {
+ if (TM.getRelocationModel() == Reloc::Static) {
emitSetDirective(MACRO);
emitSetDirective(REORDER);
}
@@ -305,6 +305,9 @@ runOnMachineFunction(MachineFunction &MF)
printInstruction(II);
++EmittedInsts;
}
+
+ // Each Basic Block is separated by a newline
+ O << '\n';
}
// Emit function end directives
@@ -319,17 +322,41 @@ printOperand(const MachineInstr *MI, int opNum)
{
const MachineOperand &MO = MI->getOperand(opNum);
const MRegisterInfo &RI = *TM.getRegisterInfo();
- bool closeP=false;
-
- // %hi and %lo used on mips gas to break large constants
+ bool closeP = false;
+ bool isPIC = (TM.getRelocationModel() == Reloc::PIC_);
+ bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large);
+
+ // %hi and %lo used on mips gas to load global addresses on
+ // static code. %got is used to load global addresses when
+ // using PIC_. %call16 is used to load direct call targets
+ // on PIC_ and small code size. %call_lo and %call_hi load
+ // direct call targets on PIC_ and large code size.
if (MI->getOpcode() == Mips::LUi && !MO.isRegister()
&& !MO.isImmediate()) {
- O << "%hi(";
+ if ((isPIC) && (isCodeLarge))
+ O << "%call_hi(";
+ else
+ O << "%hi(";
closeP = true;
} else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()
&& !MO.isImmediate()) {
O << "%lo(";
closeP = true;
+ } else if ((isPIC) && (MI->getOpcode() == Mips::LW)
+ && (!MO.isRegister()) && (!MO.isImmediate())) {
+ const MachineOperand &firstMO = MI->getOperand(opNum-1);
+ const MachineOperand &lastMO = MI->getOperand(opNum+1);
+ if ((firstMO.isRegister()) && (lastMO.isRegister())) {
+ if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() == Mips::GP)
+ && (!isCodeLarge))
+ O << "%call16(";
+ else if ((firstMO.getReg() != Mips::T9) && (lastMO.getReg() == Mips::GP))
+ O << "%got(";
+ else if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() != Mips::GP)
+ && (isCodeLarge))
+ O << "%call_lo(";
+ closeP = true;
+ }
}
switch (MO.getType())
@@ -361,6 +388,7 @@ printOperand(const MachineInstr *MI, int opNum)
O << MO.getSymbolName();
break;
+ // FIXME: Verify correct
case MachineOperand::MO_ConstantPoolIndex:
O << TAI->getPrivateGlobalPrefix() << "CPI"
<< getFunctionNumber() << "_" << MO.getConstantPoolIndex();
@@ -385,7 +413,9 @@ printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier)
return;
}
- // Load/Store memory operands -- imm($reg)
+ // Load/Store memory operands -- imm($reg)
+ // If PIC target the target is loaded as the
+ // pattern lw $25,%call16($28)
printOperand(MI, opNum);
O << "(";
printOperand(MI, opNum+1);
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 85fa640..6165d58 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -15,6 +15,7 @@
#include "Mips.h"
#include "MipsISelLowering.h"
+#include "MipsMachineFunction.h"
#include "MipsRegisterInfo.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
@@ -135,20 +136,24 @@ SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base)
return true;
}
- // TargetExternalSymbol and TargetGlobalAddress are
- // lowered and their addresses go into registers, so
- // they should not be touched here.
- if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
- Addr.getOpcode() == ISD::TargetGlobalAddress))
- return false;
+ // on PIC code Load GA
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ if (Addr.getOpcode() == ISD::TargetGlobalAddress) {
+ Base = CurDAG->getRegister(Mips::GP, MVT::i32);
+ Offset = Addr;
+ return true;
+ }
+ } else {
+ if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
+ Addr.getOpcode() == ISD::TargetGlobalAddress))
+ return false;
+ }
// Operand is a result from an ADD.
- if (Addr.getOpcode() == ISD::ADD)
- {
- if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
- {
- if (Predicate_immSExt16(CN))
- {
+ if (Addr.getOpcode() == ISD::ADD) {
+ if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
+ if (Predicate_immSExt16(CN)) {
+
// If the first operand is a FI, get the TargetFI Node
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
(Addr.getOperand(0))) {
@@ -247,6 +252,51 @@ Select(SDOperand N)
SDOperand MFInFlag = SDOperand(RemNode, 0);
return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
}
+
+ /// Handle direct and indirect calls when using PIC. On PIC, when
+ /// GOT is smaller than about 64k (small code) the GA target is
+ /// loaded with only one instruction. Otherwise GA's target must
+ /// be loaded with 3 instructions.
+ case MipsISD::JmpLink: {
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ //bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large);
+ SDOperand Chain = Node->getOperand(0);
+ SDOperand Callee = Node->getOperand(1);
+ AddToISelQueue(Chain);
+ SDOperand T9Reg = CurDAG->getRegister(Mips::T9, MVT::i32);
+ SDOperand InFlag(0, 0);
+
+ if ( (isa<GlobalAddressSDNode>(Callee)) ||
+ (isa<ExternalSymbolSDNode>(Callee)) )
+ {
+ /// Direct call for global addresses and external symbols
+ SDOperand GPReg = CurDAG->getRegister(Mips::GP, MVT::i32);
+
+ // Use load to get GOT target
+ SDOperand Ops[] = { Callee, GPReg, Chain };
+ SDOperand Load = SDOperand(CurDAG->getTargetNode(Mips::LW, MVT::i32,
+ MVT::Other, Ops, 3), 0);
+ Chain = Load.getValue(1);
+ AddToISelQueue(Chain);
+
+ // Call target must be on T9
+ Chain = CurDAG->getCopyToReg(Chain, T9Reg, Load, InFlag);
+ } else
+ /// Indirect call
+ Chain = CurDAG->getCopyToReg(Chain, T9Reg, Callee, InFlag);
+
+ AddToISelQueue(Chain);
+
+ // Emit Jump and Link Register
+ SDNode *ResNode = CurDAG->getTargetNode(Mips::JALR, MVT::Other,
+ MVT::Flag, T9Reg, Chain);
+ Chain = SDOperand(ResNode, 0);
+ InFlag = SDOperand(ResNode, 1);
+ ReplaceUses(SDOperand(Node, 0), Chain);
+ ReplaceUses(SDOperand(Node, 1), InFlag);
+ return ResNode;
+ }
+ }
}
// Select the default instruction
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 5b4ee26..440d3e3 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -39,13 +39,11 @@ getTargetNodeName(unsigned Opcode) const
{
switch (Opcode)
{
- case MipsISD::JmpLink : return "MipsISD::JmpLink";
- case MipsISD::Hi : return "MipsISD::Hi";
- case MipsISD::Lo : return "MipsISD::Lo";
- case MipsISD::Ret : return "MipsISD::Ret";
- case MipsISD::Add : return "MipsISD::Add";
- case MipsISD::LoadAddr : return "MipsISD::LoadAddr";
- default : return NULL;
+ case MipsISD::JmpLink : return "MipsISD::JmpLink";
+ case MipsISD::Hi : return "MipsISD::Hi";
+ case MipsISD::Lo : return "MipsISD::Lo";
+ case MipsISD::Ret : return "MipsISD::Ret";
+ default : return NULL;
}
}
@@ -149,21 +147,24 @@ LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG)
{
SDOperand ResNode;
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
-
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
+ bool isPIC = (getTargetMachine().getRelocationModel() == Reloc::PIC_);
- // On PIC code global addresses are loaded with "la" instruction
- if (!(getTargetMachine().getRelocationModel() == Reloc::PIC_)) {
- const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32, MVT::Flag);
+ SDOperand HiPart;
+ if (!isPIC) {
+ const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32);
SDOperand Ops[] = { GA };
+ HiPart = DAG.getNode(MipsISD::Hi, VTs, 1, Ops, 1);
+ } else // Emit Load from Global Pointer
+ HiPart = DAG.getLoad(MVT::i32, DAG.getEntryNode(), GA, NULL, 0);
- SDOperand Hi = DAG.getNode(MipsISD::Hi, VTs, 2, Ops, 1);
- SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
+ // On functions and global targets not internal linked only
+ // a load from got/GP is necessary for PIC to work.
+ if ((isPIC) && ((!GV->hasInternalLinkage()) || (isa<Function>(GV))))
+ return HiPart;
- SDOperand InFlag = Hi.getValue(1);
- ResNode = DAG.getNode(MipsISD::Add, MVT::i32, Lo, Hi, InFlag);
- } else
- ResNode = DAG.getNode(MipsISD::LoadAddr, MVT::i32, GA);
+ SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
+ ResNode = DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo);
return ResNode;
}
@@ -211,7 +212,7 @@ LowerCALL(SDOperand Op, SelectionDAG &DAG)
/// LowerCCCCallTo - functions arguments are copied from virtual
/// regs to (physical regs)/(stack frame), CALLSEQ_START and
/// CALLSEQ_END are emitted.
-/// TODO: isVarArg, isTailCall, sret, GOT, linkage types.
+/// TODO: isVarArg, isTailCall, sret.
SDOperand MipsTargetLowering::
LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
{
@@ -244,7 +245,7 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
SmallVector<SDOperand, 8> MemOpChains;
SDOperand StackPtr;
- unsigned LastStackLoc=0;
+ int LastStackLoc=0;
// Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
@@ -268,8 +269,8 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
break;
}
- // Arguments that can be passed on register,
- // must be kept at RegsToPass vector
+ // Arguments that can be passed on register must be kept at
+ // RegsToPass vector
if (VA.isRegLoc()) {
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
} else {
@@ -294,14 +295,6 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
}
}
- // Create a stack location to hold GP when PIC is used
- if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
- LastStackLoc = (!LastStackLoc) ? (16) : (LastStackLoc+4);
- MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
- MFI->CreateFixedObject(4, LastStackLoc);
- MipsFI->setGPStackOffset(LastStackLoc);
- }
-
// Transform all store nodes into one single node because
// all store nodes are independent of each other.
if (!MemOpChains.empty())
@@ -321,13 +314,13 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
- // node so that legalize doesn't hack it. Otherwise we have an indirect call,
- // if PIC is used, the call must use register GP
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
+ // node so that legalize doesn't hack it.
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
+
// MipsJmpLink = #chain, #target_address, #opt_in_flags...
// = Chain, Callee, Reg#1, Reg#2, ...
//
@@ -349,6 +342,37 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
Chain = DAG.getNode(MipsISD::JmpLink, NodeTys, &Ops[0], Ops.size());
InFlag = Chain.getValue(1);
+ // Create a stack location to hold GP when PIC is used. This stack
+ // location is used on function prologue to save GP and also after all
+ // emited CALL's to restore GP.
+ if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
+
+ // Function can have an arbitrary number of calls, so
+ // hold the LastStackLoc with the biggest offset.
+ int FI;
+ MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
+ if (LastStackLoc >= MipsFI->getGPStackOffset()) {
+
+ LastStackLoc = (!LastStackLoc) ? (16) : (LastStackLoc+4);
+ // Create the frame index only once. SPOffset here can be anything
+ // (this will be fixed on processFunctionBeforeFrameFinalized)
+ if (MipsFI->getGPStackOffset() == -1) {
+ FI = MFI->CreateFixedObject(4, 0);
+ MipsFI->setGPFI(FI);
+ }
+ MipsFI->setGPStackOffset(LastStackLoc);
+ }
+
+
+ // Reload GP value.
+ FI = MipsFI->getGPFI();
+ SDOperand FIN = DAG.getFrameIndex(FI,getPointerTy());
+ SDOperand GPLoad = DAG.getLoad(MVT::i32, Chain, FIN, NULL, 0);
+ Chain = GPLoad.getValue(1);
+ Chain = DAG.getCopyToReg(Chain, DAG.getRegister(Mips::GP, MVT::i32),
+ GPLoad, SDOperand(0,0));
+ }
+
// Create the CALLSEQ_END node.
NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
Ops.clear();
@@ -389,10 +413,11 @@ LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall,
ResultVals.push_back(Chain.getValue(0));
}
- // Merge everything together with a MERGE_VALUES node.
ResultVals.push_back(Chain);
+
+ // Merge everything together with a MERGE_VALUES node.
return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(),
- &ResultVals[0], ResultVals.size()).Val;
+ &ResultVals[0], ResultVals.size()).Val;
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
index 2d230a7..37c39f3 100644
--- a/lib/Target/Mips/MipsISelLowering.h
+++ b/lib/Target/Mips/MipsISelLowering.h
@@ -38,13 +38,7 @@ namespace llvm {
Lo,
// Return
- Ret,
-
- // Need to support addition with a input flag
- Add,
-
- // Used on PIC Code to load global addresses
- LoadAddr
+ Ret
};
}
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index 70bc7dd..c6fcaed 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -22,20 +22,11 @@ def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
SDNPOutFlag]>;
-// Hi and Lo nodes are created to let easy manipulation of 16-bit when
-// handling 32-bit immediates. They are used on MipsISelLowering to
-// lower stuff like GlobalAddress, ExternalSymbol, ... on static model
-// This two nodes have nothing to do with Mips Registers Hi and Lo.
-def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
-def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
-
-// Necessary to generate glued instructions when loading GlobalAddress
-// into registers.
-def MipsAdd : SDNode<"MipsISD::Add", SDTIntBinOp, [SDNPCommutative,
- SDNPAssociative, SDNPOptInFlag]>;
-
-// Used to Load Addresses on PIC code.
-def MipsLoadAddr: SDNode<"MipsISD::LoadAddr", SDTIntUnaryOp>;
+// Hi and Lo nodes are used to handle global addresses. Used on
+// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
+// static model. (nothing to do with Mips Registers Hi and Lo)
+def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
+def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
// Return
def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
@@ -371,15 +362,9 @@ def IMPLICIT_DEF_CPURegs : PseudoInstMips<(outs CPURegs:$dst), (ins),
// are used, we have the same behavior, but get also a bunch of warnings
// from the assembler.
def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg),
- ".set noreorder\n\t.cpload $reg\n\t.set reorder", []>;
+ ".set noreorder\n\t.cpload $reg\n\t.set reorder\n", []>;
def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc),
- ".cprestore $loc", []>;
-
-// Used on PIC code only, it loads the address of label into register reg. The
-// address is calculated from the global pointer ($gp) and is expanded by the
-// assembler into two instructions "lw" and "addiu".
-def LA: PseudoInstMips<(outs CPURegs:$dst), (ins addrlabel:$label),
- "la $dst, $label", []>;
+ ".cprestore $loc\n", []>;
//===----------------------------------------------------------------------===//
// Instruction definition
@@ -393,17 +378,13 @@ def LA: PseudoInstMips<(outs CPURegs:$dst), (ins addrlabel:$label),
// ADDiu just accept 16-bit immediates but we handle this on Pat's.
// immZExt32 is used here so it can match GlobalAddress immediates.
-def ADDiu : ArithI<0x09, "addiu", MipsAdd, uimm16, immZExt16>;
+def ADDiu : ArithI<0x09, "addiu", add, uimm16, immZExt16>;
def ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>;
def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>;
def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>;
def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>;
def ADD : ArithOverflowR<0x00, 0x20, "add">;
def SUB : ArithOverflowR<0x00, 0x22, "sub">;
-def MADD : MArithR<0x00, "madd">;
-def MADDU : MArithR<0x01, "maddu">;
-def MSUB : MArithR<0x04, "msub">;
-def MSUBU : MArithR<0x05, "msubu">;
// Logical
def AND : LogicR<0x24, "and", and>;
@@ -481,10 +462,16 @@ def MTLO : MoveFromTo<0x13, "mtlo">;
// Count Leading
// CLO/CLZ are part of the newer MIPS32(tm) instruction
// set and not older Mips I keep this for future use
-// though.
+// though.
//def CLO : CountLeading<0x21, "clo">;
//def CLZ : CountLeading<0x20, "clz">;
+// MADD*/MSUB* are not part of MipsI either.
+//def MADD : MArithR<0x00, "madd">;
+//def MADDU : MArithR<0x01, "maddu">;
+//def MSUB : MArithR<0x04, "msub">;
+//def MSUBU : MArithR<0x05, "msubu">;
+
// No operation
let addr=0 in
def NOP : FJ<0, (outs), (ins), "nop", [], IIAlu>;
@@ -529,9 +516,8 @@ def : Pat<(MipsJmpLink CPURegs:$dst),
// GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable
def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
-def : Pat<(MipsAdd CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
+def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
(ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
-def : Pat<(MipsLoadAddr tglobaladdr:$in), (LA tglobaladdr:$in)>;
// Mips does not have not, so we increase the operation
def : Pat<(not CPURegs:$in),
@@ -544,6 +530,9 @@ def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
def : Pat<(truncstorei1 CPURegs:$src, addr:$addr),
(SB CPURegs:$src, addr:$addr)>;
+// some peepholes
+def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
+
///
/// brcond patterns
///
diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h
index 2515aa0..d4f4312 100644
--- a/lib/Target/Mips/MipsMachineFunction.h
+++ b/lib/Target/Mips/MipsMachineFunction.h
@@ -33,11 +33,6 @@ private:
/// the Return Address must be saved
int RAStackOffset;
- /// When PIC is used the GP must be saved on the stack
- /// on the function prologue, so a reference to its stack
- /// location must be kept.
- int GPStackOffset;
-
/// MipsFIHolder - Holds a FrameIndex and it's Stack Pointer Offset
struct MipsFIHolder {
@@ -48,6 +43,13 @@ private:
: FI(FrameIndex), SPOffset(StackPointerOffset) {}
};
+ /// When PIC is used the GP must be saved on the stack
+ /// on the function prologue and must be reloaded from this
+ /// stack location after every call. A reference to its stack
+ /// location and frame index must be kept to be used on
+ /// emitPrologue and processFunctionBeforeFrameFinalized.
+ MipsFIHolder GPHolder;
+
// On LowerFORMAL_ARGUMENTS the stack size is unknown,
// so the Stack Pointer Offset calculation of "not in
// register arguments" must be postponed to emitPrologue.
@@ -64,7 +66,7 @@ private:
public:
MipsFunctionInfo(MachineFunction& MF)
- : FPStackOffset(0), RAStackOffset(0),
+ : FPStackOffset(0), RAStackOffset(0), GPHolder(-1,-1),
HasLoadArgs(false), HasStoreVarArgs(false)
{}
@@ -74,8 +76,10 @@ public:
int getRAStackOffset() const { return RAStackOffset; }
void setRAStackOffset(int Off) { RAStackOffset = Off; }
- int getGPStackOffset() const { return GPStackOffset; }
- void setGPStackOffset(int Off) { GPStackOffset = Off; }
+ int getGPStackOffset() const { return GPHolder.SPOffset; }
+ int getGPFI() const { return GPHolder.FI; }
+ void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; }
+ void setGPFI(int FI) { GPHolder.FI = FI; }
int getTopSavedRegOffset() const {
return (RAStackOffset > FPStackOffset) ?
diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp
index cd61fe8..711a9cf 100644
--- a/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -203,6 +203,12 @@ foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const
return NewMI;
}
+MachineInstr *MipsRegisterInfo::
+foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
+ MachineInstr* LoadMI) const {
+ return NULL;
+}
+
//===----------------------------------------------------------------------===//
//
// Callee Saved Registers methods
@@ -325,7 +331,7 @@ void MipsRegisterInfo::
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
RegScavenger *RS) const
{
- MachineInstr &MI = *II;
+ MachineInstr &MI = *II;
MachineFunction &MF = *MI.getParent()->getParent();
unsigned i = 0;
@@ -359,7 +365,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
#endif
MI.getOperand(i-1).ChangeToImmediate(Offset);
- MI.getOperand(i).ChangeToRegister(getFrameRegister(MF),false);
+ MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
}
void MipsRegisterInfo::
@@ -453,7 +459,6 @@ emitPrologue(MachineFunction &MF) const
if ((isPIC) && (MFI->hasCalls()))
BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE))
.addImm(MipsFI->getGPStackOffset());
-
}
void MipsRegisterInfo::
@@ -498,6 +503,17 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
void MipsRegisterInfo::
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
+ // Set the SPOffset on the FI where GP must be saved/loaded.
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ if (MFI->hasCalls()) {
+ MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
+ #ifndef NDEBUG
+ DOUT << "processFunctionBeforeFrameFinalized\n";
+ DOUT << "GPOffset :" << MipsFI->getGPStackOffset() << "\n";
+ DOUT << "FI :" << MipsFI->getGPFI() << "\n";
+ #endif
+ MFI->setObjectOffset(MipsFI->getGPFI(), MipsFI->getGPStackOffset());
+ }
}
unsigned MipsRegisterInfo::
diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h
index 9afc3b5..adec3ed 100644
--- a/lib/Target/Mips/MipsRegisterInfo.h
+++ b/lib/Target/Mips/MipsRegisterInfo.h
@@ -59,9 +59,7 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo {
int FrameIndex) const;
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
- MachineInstr* LoadMI) const {
- return 0;
- }
+ MachineInstr* LoadMI) const;
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
unsigned DestReg, unsigned SrcReg,
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index 6451659..187dcee 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -35,6 +35,9 @@ createTargetAsmInfo() const
// On function prologue, the stack is created by decrementing
// its pointer. Once decremented, all references are done with positive
// offset from the stack/frame pointer, so StackGrowsUp is used.
+// When using CodeModel::Large the behaviour
+//
+//
MipsTargetMachine::
MipsTargetMachine(const Module &M, const std::string &FS):
Subtarget(*this, M, FS), DataLayout("E-p:32:32:32"),
@@ -43,6 +46,8 @@ MipsTargetMachine(const Module &M, const std::string &FS):
{
if (getRelocationModel() != Reloc::Static)
setRelocationModel(Reloc::PIC_);
+ if (getCodeModel() == CodeModel::Default)
+ setCodeModel(CodeModel::Small);
}
// return 0 and must specify -march to gen MIPS code.