diff options
author | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2008-07-21 18:52:34 +0000 |
---|---|---|
committer | Bruno Cardoso Lopes <bruno.cardoso@gmail.com> | 2008-07-21 18:52:34 +0000 |
commit | 91fd532eb9a18c0fd8d91b975226ef6b41c772ec (patch) | |
tree | 5441c955f34bb60888c218900906b1cca1483227 /lib | |
parent | 6116a73da420d9b414a34ce2599dc7f6476e23fc (diff) | |
download | llvm-91fd532eb9a18c0fd8d91b975226ef6b41c772ec.tar.gz llvm-91fd532eb9a18c0fd8d91b975226ef6b41c772ec.tar.bz2 llvm-91fd532eb9a18c0fd8d91b975226ef6b41c772ec.tar.xz |
Added initial support for small sections on Mips.
Added gp_rel relocations to support addressing small section contents.
Added command line to specify small section threshold in bytes.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53869 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/Mips/MipsAsmPrinter.cpp | 11 | ||||
-rw-r--r-- | lib/Target/Mips/MipsISelLowering.cpp | 76 | ||||
-rw-r--r-- | lib/Target/Mips/MipsISelLowering.h | 5 | ||||
-rw-r--r-- | lib/Target/Mips/MipsInstrInfo.td | 12 | ||||
-rw-r--r-- | lib/Target/Mips/MipsSubtarget.cpp | 6 | ||||
-rw-r--r-- | lib/Target/Mips/MipsSubtarget.h | 5 | ||||
-rw-r--r-- | lib/Target/Mips/MipsTargetAsmInfo.cpp | 1 |
7 files changed, 87 insertions, 29 deletions
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 4981b903bd..d00680e54a 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/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/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index efc5d9bf8d..668e57d860 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/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/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 702533455f..3a1fd75317 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/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/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index de5a53617d..2f1a6f8152 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/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/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 3424388011..bc87e4ba7a 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/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/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 5140e1eb22..c3a03e3bcd 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/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/lib/Target/Mips/MipsTargetAsmInfo.cpp b/lib/Target/Mips/MipsTargetAsmInfo.cpp index ceaee4b8c9..40c6e7f954 100644 --- a/lib/Target/Mips/MipsTargetAsmInfo.cpp +++ b/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"; |