diff options
| -rw-r--r-- | llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.cpp | 76 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.h | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.td | 12 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsSubtarget.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsSubtarget.h | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsTargetAsmInfo.cpp | 1 | 
7 files changed, 87 insertions, 29 deletions
diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 4981b903bd2..d00680e54a1 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -360,7 +360,11 @@ printOperand(const MachineInstr *MI, int opNum)      closeP = true;    } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()                && !MO.isImmediate()) { -    O << "%lo("; +    const MachineOperand &firstMO = MI->getOperand(opNum-1); +    if (firstMO.getReg() == Mips::GP) +      O << "%gp_rel("; +    else +      O << "%lo(";      closeP = true;    } else if ((isPIC) && (MI->getOpcode() == Mips::LW)               && (!MO.isRegister()) && (!MO.isImmediate())) { @@ -490,14 +494,13 @@ printModuleLevelGV(const GlobalVariable* GVar) {    Constant *C = GVar->getInitializer();    const Type *CTy = C->getType();    unsigned Size = TD->getABITypeSize(CTy); +  const ConstantArray *CVA = dyn_cast<ConstantArray>(C);    bool printSizeAndType = true;    // A data structure or array is aligned in memory to the largest    // alignment boundary required by any data type inside it (this matches    // the Preferred Type Alignment). For integral types, the alignment is    // the type size. -  //unsigned Align = TD->getPreferredAlignmentLog(I); -  //unsigned Align = TD->getPrefTypeAlignment(C->getType());    unsigned Align;    if (CTy->getTypeID() == Type::IntegerTyID ||        CTy->getTypeID() == Type::VoidTyID) { @@ -546,6 +549,8 @@ printModuleLevelGV(const GlobalVariable* GVar) {      O << TAI->getGlobalDirective() << name << '\n';      // Fall Through     case GlobalValue::InternalLinkage: +    if (CVA && CVA->isCString()) +      printSizeAndType = false;        break;     case GlobalValue::GhostLinkage:      cerr << "Should not have any unmaterialized functions!\n"; diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index efc5d9bf8d6..668e57d8601 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -20,6 +20,7 @@  #include "MipsSubtarget.h"  #include "llvm/DerivedTypes.h"  #include "llvm/Function.h" +#include "llvm/GlobalVariable.h"  #include "llvm/Intrinsics.h"  #include "llvm/CallingConv.h"  #include "llvm/CodeGen/CallingConvLower.h" @@ -43,6 +44,7 @@ getTargetNodeName(unsigned Opcode) const      case MipsISD::JmpLink   : return "MipsISD::JmpLink";      case MipsISD::Hi        : return "MipsISD::Hi";      case MipsISD::Lo        : return "MipsISD::Lo"; +    case MipsISD::GPRel     : return "MipsISD::GPRel";      case MipsISD::Ret       : return "MipsISD::Ret";      case MipsISD::SelectCC  : return "MipsISD::SelectCC";      case MipsISD::FPBrcond  : return "MipsISD::FPBrcond"; @@ -89,8 +91,6 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)    setOperationAction(ISD::SELECT_CC,        MVT::f32,   Custom);    // Operations not directly supported by Mips. -  setConvertAction(MVT::f64, MVT::f32, Expand); -    setOperationAction(ISD::BR_JT,             MVT::Other, Expand);    setOperationAction(ISD::BR_CC,             MVT::Other, Expand);    setOperationAction(ISD::SELECT_CC,         MVT::Other, Expand); @@ -234,34 +234,71 @@ AddLiveIn(MachineFunction &MF, unsigned PReg, TargetRegisterClass *RC)    return VReg;  } +// Discover if this global address can be placed into small data/bss section.  +// This should happen for globals with size less than small section size  +// threshold in no abicall environments. Data in this section must be addressed  +// using gp_rel operator. +bool MipsTargetLowering::IsGlobalInSmallSection(GlobalValue *GV) +{ +  const TargetData *TD = getTargetData(); +  const Value *V = dyn_cast<Value>(GV); +  const GlobalVariable *GVA = dyn_cast<GlobalVariable>(V); +   +  //const PointerType *PTy = GV->getType(); +  const Type *Ty = GV->getType()->getElementType(); +  unsigned Size = TD->getABITypeSize(Ty); + +  // if this is a internal constant string, there is a special +  // section for it, but not in small data/bss. +  if (GVA->hasInitializer() && GV->hasInternalLinkage()) { +    Constant *C = GVA->getInitializer(); +    const ConstantArray *CVA = dyn_cast<ConstantArray>(C); +    if (CVA && CVA->isCString())  +      return false; +  } + +  if (Size > 0 && (Size <= Subtarget->getSSectionThreshold())) +    return true; + +  return false; +} +  //===----------------------------------------------------------------------===//  //  Misc Lower Operation implementation  //===----------------------------------------------------------------------===//  SDOperand MipsTargetLowering::  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_); -  SDOperand HiPart;  -  if (!isPIC) { +  if (!Subtarget->hasABICall()) { +    if (isa<Function>(GV)) return GA;      const MVT *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); - -  // 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 Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA); -  ResNode = DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo); +    if (IsGlobalInSmallSection(GV)) { // %gp_rel relocation +      SDOperand GPRelNode = DAG.getNode(MipsISD::GPRel, VTs, 1, Ops, 1); +      SDOperand GOT = DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, MVT::i32); +      return DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode);  +    } +    // %hi/%lo relocation +    SDOperand HiPart = DAG.getNode(MipsISD::Hi, VTs, 1, Ops, 1); +    SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA); +    return DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo); + +  } else { // Abicall relocations, TODO: make this cleaner. +    SDOperand ResNode = DAG.getLoad(MVT::i32, DAG.getEntryNode(), GA, NULL, 0); +    // On functions and global targets not internal linked only +    // a load from got/GP is necessary for PIC to work. +    if (!GV->hasInternalLinkage() || isa<Function>(GV)) +      return ResNode; +    SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA); +    return DAG.getNode(ISD::ADD, MVT::i32, ResNode, Lo); +  } -  return ResNode; +  assert(0 && "Dont know how to handle GlobalAddress"); +  return SDOperand(0,0);  }  SDOperand MipsTargetLowering:: @@ -596,9 +633,8 @@ LowerCCCArguments(SDOperand Op, SelectionDAG &DAG)    unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF); -  // GP holds the GOT address on PIC calls. -  if (getTargetMachine().getRelocationModel() == Reloc::PIC_) -    AddLiveIn(MF, Mips::GP, Mips::CPURegsRegisterClass); +  // GP must be live into PIC and non-PIC call target. +  AddLiveIn(MF, Mips::GP, Mips::CPURegsRegisterClass);    // Assign locations to all of the incoming arguments.    SmallVector<CCValAssign, 16> ArgLocs; diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index 702533455ff..3a1fd75317e 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -37,6 +37,9 @@ namespace llvm {        // No relation with Mips Lo register        Lo,  +      // Handle gp_rel (small data/bss sections) relocation. +      GPRel, +        // Select CC Pseudo Instruction        SelectCC, @@ -83,7 +86,7 @@ namespace llvm {      SDOperand LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC);      SDNode *LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode*TheCall,                              unsigned CallingConv, SelectionDAG &DAG); -    SDOperand getReturnAddressFrameIndex(SelectionDAG &DAG); +    bool IsGlobalInSmallSection(GlobalValue *GV);       // Lower Operand specifics      SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG); diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index de5a53617df..2f1a6f81528 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -31,9 +31,9 @@ def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,  // 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 MipsHi  : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; -def MipsLo  : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; +def MipsHi    : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; +def MipsLo    : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; +def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>;  // Return  def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain,  @@ -555,13 +555,15 @@ 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<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;  def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)),            (ADDiu CPURegs:$hi, tglobaladdr:$lo)>;  def : Pat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; -def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>; +//def : Pat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>;  def : Pat<(add CPURegs:$hi, (MipsLo tjumptable:$lo)),            (ADDiu CPURegs:$hi, tjumptable:$lo)>; +def : Pat<(add CPURegs:$gp, (MipsGPRel tglobaladdr:$in)),  +          (ADDiu CPURegs:$gp, tglobaladdr:$in)>;  // Mips does not have "not", so we expand our way  def : Pat<(not CPURegs:$in), diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index 34243880114..bc87e4ba7ae 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -22,6 +22,9 @@ cl::opt<bool> NotABICall("disable-mips-abicall", cl::Hidden,                cl::desc("Disable code for SVR4-style dynamic objects"));  cl::opt<bool> AbsoluteCall("enable-mips-absolute-call", cl::Hidden,                cl::desc("Enable absolute call within abicall")); +cl::opt<unsigned> SSThreshold("mips-ssection-threshold", cl::Hidden, +              cl::desc("Small data and bss section threshold size (default=8)"), +              cl::init(8));  MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,                                const std::string &FS, bool little) :  @@ -35,6 +38,9 @@ MipsSubtarget::MipsSubtarget(const TargetMachine &TM, const Module &M,    ParseSubtargetFeatures(FS, CPU);    const std::string& TT = M.getTargetTriple(); +  // Small section size threshold +  SSectionThreshold = SSThreshold; +    // Is the target system Linux ?    if (TT.find("linux") == std::string::npos)      IsLinux = false; diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index 5140e1eb22d..c3a03e3bcda 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -71,6 +71,10 @@ protected:    // isLinux - Target system is Linux. Is false we consider ELFOS for now.    bool IsLinux; +  // Put global and static items less than or equal to SSectionThreshold  +  // bytes into the small data or bss section. The default is 8. +  unsigned SSectionThreshold; +    InstrItineraryData InstrItins;  public: @@ -102,6 +106,7 @@ public:    bool hasABICall() const { return HasABICall; };    bool hasAbsoluteCall() const { return HasAbsoluteCall; };    bool isLinux() const { return IsLinux; }; +  unsigned getSSectionThreshold() const { return SSectionThreshold; }  };  } // End llvm namespace diff --git a/llvm/lib/Target/Mips/MipsTargetAsmInfo.cpp b/llvm/lib/Target/Mips/MipsTargetAsmInfo.cpp index ceaee4b8c99..40c6e7f9545 100644 --- a/llvm/lib/Target/Mips/MipsTargetAsmInfo.cpp +++ b/llvm/lib/Target/Mips/MipsTargetAsmInfo.cpp @@ -31,6 +31,7 @@ MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM):    ZeroDirective               = "\t.space\t";    BSSSection                  = "\t.section\t.bss";    LCOMMDirective              = "\t.lcomm\t"; +  CStringSection              = ".rodata.str";    if (!TM.getSubtarget<MipsSubtarget>().hasABICall())      JumpTableDirective = "\t.word\t";  | 

