diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp | 15 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td | 28 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/Mips.td | 2 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/Mips64InstrInfo.td | 114 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsAsmPrinter.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.cpp | 43 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsISelLowering.h | 53 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.td | 80 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsSubtarget.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsSubtarget.h | 6 |
12 files changed, 241 insertions, 117 deletions
diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index b2efd726da5..44494b12fe2 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -524,6 +524,8 @@ bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, case ELF::R_MIPS_GOT16: case ELF::R_MIPS16_GOT16: case ELF::R_MICROMIPS_GOT16: + case ELF::R_MIPS_HIGHER: + case ELF::R_MIPS_HIGHEST: case ELF::R_MIPS_HI16: case ELF::R_MIPS16_HI16: case ELF::R_MICROMIPS_HI16: @@ -567,8 +569,6 @@ bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, case ELF::R_MIPS_INSERT_A: case ELF::R_MIPS_INSERT_B: case ELF::R_MIPS_DELETE: - case ELF::R_MIPS_HIGHER: - case ELF::R_MIPS_HIGHEST: case ELF::R_MIPS_CALL_HI16: case ELF::R_MIPS_CALL_LO16: case ELF::R_MIPS_SCN_DISP: diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 7f79eb400f5..2ab5aea4bfa 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -721,10 +721,6 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, if (Features[Mips::FeatureNaN2008]) EFlags |= ELF::EF_MIPS_NAN2008; - // -mabicalls and -mplt are not implemented but we should act as if they were - // given. - EFlags |= ELF::EF_MIPS_CPIC; - MCA.setELFHeaderEFlags(EFlags); } @@ -795,10 +791,13 @@ void MipsTargetELFStreamer::finish() { } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64]) EFlags |= ELF::EF_MIPS_32BITMODE; - // If we've set the cpic eflag and we're n64, go ahead and set the pic - // one as well. - if (EFlags & ELF::EF_MIPS_CPIC && getABI().IsN64()) - EFlags |= ELF::EF_MIPS_PIC; + // -mplt is not implemented but we should act as if it was + // given. + if (!Features[Mips::FeatureNoABICalls]) + EFlags |= ELF::EF_MIPS_CPIC; + + if (Pic) + EFlags |= ELF::EF_MIPS_PIC | ELF::EF_MIPS_CPIC; MCA.setELFHeaderEFlags(EFlags); diff --git a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td index 05aad515da4..6b7f39e9dd7 100644 --- a/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td @@ -475,29 +475,11 @@ defm : MaterializeImms<i64, ZERO_64, DADDIU_MM64R6, LUi64, ORi64>; // //===----------------------------------------------------------------------===// -def : MipsPat<(MipsLo tglobaladdr:$in), - (DADDIU_MM64R6 ZERO_64, tglobaladdr:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo tblockaddress:$in), - (DADDIU_MM64R6 ZERO_64, tblockaddress:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo tjumptable:$in), - (DADDIU_MM64R6 ZERO_64, tjumptable:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo tconstpool:$in), - (DADDIU_MM64R6 ZERO_64, tconstpool:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo tglobaltlsaddr:$in), - (DADDIU_MM64R6 ZERO_64, tglobaltlsaddr:$in)>, ISA_MICROMIPS64R6; -def : MipsPat<(MipsLo texternalsym:$in), - (DADDIU_MM64R6 ZERO_64, texternalsym:$in)>, ISA_MICROMIPS64R6; - -def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tglobaladdr:$lo)>, ISA_MICROMIPS64R6; -def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tblockaddress:$lo)>, ISA_MICROMIPS64R6; -def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tjumptable:$lo)>, ISA_MICROMIPS64R6; -def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tconstpool:$lo)>, ISA_MICROMIPS64R6; -def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)), - (DADDIU_MM64R6 GPR64:$hi, tglobaltlsaddr:$lo)>, ISA_MICROMIPS64R6; +defm : MipsHiLoRelocs<LUi64, DADDIU_MM64R6, ZERO_64, GPR64Opnd>, SYM_32, + ISA_MICROMIPS64R6; + +defm : MipsHighestHigherHiLoRelocs<LUi64, DADDIU_MM64R6>, SYM_64, + ISA_MICROMIPS64R6; def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs), (DADDU_MM64R6 GPR64:$lhs, GPR64:$rhs)>, ISA_MICROMIPS64R6; diff --git a/llvm/lib/Target/Mips/Mips.td b/llvm/lib/Target/Mips/Mips.td index 670272d47e9..9615bc38bfc 100644 --- a/llvm/lib/Target/Mips/Mips.td +++ b/llvm/lib/Target/Mips/Mips.td @@ -156,6 +156,8 @@ def FeatureMips64r6 : SubtargetFeature<"mips64r6", "MipsArchVersion", "Mips64r6 ISA Support [experimental]", [FeatureMips32r6, FeatureMips64r5, FeatureNaN2008]>; +def FeatureSym32 : SubtargetFeature<"sym32", "HasSym32", "true", + "Symbols are 32 bit on Mips64">; def FeatureMips16 : SubtargetFeature<"mips16", "InMips16Mode", "true", "Mips16 mode">; diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td index 521e22fb799..03882dadbe1 100644 --- a/llvm/lib/Target/Mips/Mips64InstrInfo.td +++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td @@ -513,41 +513,87 @@ def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>; def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>; // hi/lo relocs -def : MipsPat<(MipsHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; -def : MipsPat<(MipsHi tblockaddress:$in), (LUi64 tblockaddress:$in)>; -def : MipsPat<(MipsHi tjumptable:$in), (LUi64 tjumptable:$in)>; -def : MipsPat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>; -def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>; -def : MipsPat<(MipsHi texternalsym:$in), (LUi64 texternalsym:$in)>; +let AdditionalPredicates = [NotInMicroMips] in +defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, SYM_32; + +def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; +def : MipsPat<(MipsGotHi texternalsym:$in), (LUi64 texternalsym:$in)>; + +multiclass MipsHighestHigherHiLoRelocs<Instruction Lui, Instruction Daddiu> { + def : MipsPat<(MipsJmpLink (i64 texternalsym:$dst)), + (JAL texternalsym:$dst)>; + def : MipsPat<(MipsHighest (i64 tglobaladdr:$in)), + (Lui tglobaladdr:$in)>; + def : MipsPat<(MipsHighest (i64 tblockaddress:$in)), + (Lui tblockaddress:$in)>; + def : MipsPat<(MipsHighest (i64 tjumptable:$in)), + (Lui tjumptable:$in)>; + def : MipsPat<(MipsHighest (i64 tconstpool:$in)), + (Lui tconstpool:$in)>; + def : MipsPat<(MipsHighest (i64 tglobaltlsaddr:$in)), + (Lui tglobaltlsaddr:$in)>; + def : MipsPat<(MipsHighest (i64 texternalsym:$in)), + (Lui texternalsym:$in)>; + + def : MipsPat<(MipsHigher (i64 tglobaladdr:$in)), + (Daddiu ZERO_64, tglobaladdr:$in)>; + def : MipsPat<(MipsHigher (i64 tblockaddress:$in)), + (Daddiu ZERO_64, tblockaddress:$in)>; + def : MipsPat<(MipsHigher (i64 tjumptable:$in)), + (Daddiu ZERO_64, tjumptable:$in)>; + def : MipsPat<(MipsHigher (i64 tconstpool:$in)), + (Daddiu ZERO_64, tconstpool:$in)>; + def : MipsPat<(MipsHigher (i64 tglobaltlsaddr:$in)), + (Daddiu ZERO_64, tglobaltlsaddr:$in)>; + def : MipsPat<(MipsHigher (i64 texternalsym:$in)), + (Daddiu ZERO_64, texternalsym:$in)>; + + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaladdr:$lo))), + (Daddiu GPR64:$hi, tglobaladdr:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tblockaddress:$lo))), + (Daddiu GPR64:$hi, tblockaddress:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tjumptable:$lo))), + (Daddiu GPR64:$hi, tjumptable:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tconstpool:$lo))), + (Daddiu GPR64:$hi, tconstpool:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaltlsaddr:$lo))), + (Daddiu GPR64:$hi, tglobaltlsaddr:$lo)>; + + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))), + (Daddiu GPR64:$hi, tglobaladdr:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tblockaddress:$lo))), + (Daddiu GPR64:$hi, tblockaddress:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tjumptable:$lo))), + (Daddiu GPR64:$hi, tjumptable:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tconstpool:$lo))), + (Daddiu GPR64:$hi, tconstpool:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaltlsaddr:$lo))), + (Daddiu GPR64:$hi, tglobaltlsaddr:$lo)>; + + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))), + (Daddiu GPR64:$hi, tglobaladdr:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tblockaddress:$lo))), + (Daddiu GPR64:$hi, tblockaddress:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tjumptable:$lo))), + (Daddiu GPR64:$hi, tjumptable:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tconstpool:$lo))), + (Daddiu GPR64:$hi, tconstpool:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaltlsaddr:$lo))), + (Daddiu GPR64:$hi, tglobaltlsaddr:$lo)>; + +} + +// highest/higher/hi/lo relocs +let AdditionalPredicates = [NotInMicroMips] in +defm : MipsHighestHigherHiLoRelocs<LUi64, DADDiu>, SYM_64; + +def : WrapperPat<tglobaladdr, DADDiu, GPR64>; +def : WrapperPat<tconstpool, DADDiu, GPR64>; +def : WrapperPat<texternalsym, DADDiu, GPR64>; +def : WrapperPat<tblockaddress, DADDiu, GPR64>; +def : WrapperPat<tjumptable, DADDiu, GPR64>; +def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>; -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>; - def : MipsPat<(MipsLo tblockaddress:$in), - (DADDiu ZERO_64, tblockaddress:$in)>; - def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>; - def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>; - def : MipsPat<(MipsLo tglobaltlsaddr:$in), - (DADDiu ZERO_64, tglobaltlsaddr:$in)>; - def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>; - - def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)), - (DADDiu GPR64:$hi, tglobaladdr:$lo)>; - def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)), - (DADDiu GPR64:$hi, tblockaddress:$lo)>; - def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)), - (DADDiu GPR64:$hi, tjumptable:$lo)>; - def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)), - (DADDiu GPR64:$hi, tconstpool:$lo)>; - def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)), - (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>; - - def : WrapperPat<tglobaladdr, DADDiu, GPR64>; - def : WrapperPat<tconstpool, DADDiu, GPR64>; - def : WrapperPat<texternalsym, DADDiu, GPR64>; - def : WrapperPat<tblockaddress, DADDiu, GPR64>; - def : WrapperPat<tjumptable, DADDiu, GPR64>; - def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>; -} defm : BrcondPats<GPR64, BEQ64, BEQ, BNE64, SLT64, SLTu64, SLTi64, SLTiu64, ZERO_64>; diff --git a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 04d6529a073..04c5d96673f 100644 --- a/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -574,6 +574,8 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, case MipsII::MO_GOT: O << "%got("; break; case MipsII::MO_ABS_HI: O << "%hi("; break; case MipsII::MO_ABS_LO: O << "%lo("; break; + case MipsII::MO_HIGHER: O << "%higher("; break; + case MipsII::MO_HIGHEST: O << "%highest(("; break; case MipsII::MO_TLSGD: O << "%tlsgd("; break; case MipsII::MO_GOTTPREL: O << "%gottprel("; break; case MipsII::MO_TPREL_HI: O << "%tprel_hi("; break; @@ -698,7 +700,7 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // Ideally it should test for properties of the ABI and not the ABI // itself. // For the moment, I'm only correcting enough to make MIPS-IV work. - if (!isPositionIndependent() && !ABI.IsN64()) + if (!isPositionIndependent() && STI.hasSym32()) TS.emitDirectiveOptionPic0(); } diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index 9c511bd7782..f0f2424f722 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -112,8 +112,11 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::FIRST_NUMBER: break; case MipsISD::JmpLink: return "MipsISD::JmpLink"; case MipsISD::TailCall: return "MipsISD::TailCall"; + case MipsISD::Highest: return "MipsISD::Highest"; + case MipsISD::Higher: return "MipsISD::Higher"; case MipsISD::Hi: return "MipsISD::Hi"; case MipsISD::Lo: return "MipsISD::Lo"; + case MipsISD::GotHi: return "MipsISD::GotHi"; case MipsISD::GPRel: return "MipsISD::GPRel"; case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer"; case MipsISD::Ret: return "MipsISD::Ret"; @@ -1733,7 +1736,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); const GlobalValue *GV = N->getGlobal(); - if (!isPositionIndependent() && !ABI.IsN64()) { + if (!isPositionIndependent()) { const MipsTargetObjectFile *TLOF = static_cast<const MipsTargetObjectFile *>( getTargetMachine().getObjFileLowering()); @@ -1742,8 +1745,10 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, // %gp_rel relocation return getAddrGPRel(N, SDLoc(N), Ty, DAG); - // %hi/%lo relocation - return getAddrNonPIC(N, SDLoc(N), Ty, DAG); + // %hi/%lo relocation + return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) + // %highest/%higher/%hi/%lo relocation + : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); } // Every other architecture would use shouldAssumeDSOLocal in here, but @@ -1777,8 +1782,9 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); EVT Ty = Op.getValueType(); - if (!isPositionIndependent() && !ABI.IsN64()) - return getAddrNonPIC(N, SDLoc(N), Ty, DAG); + if (!isPositionIndependent()) + return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) + : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } @@ -1870,8 +1876,9 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const JumpTableSDNode *N = cast<JumpTableSDNode>(Op); EVT Ty = Op.getValueType(); - if (!isPositionIndependent() && !ABI.IsN64()) - return getAddrNonPIC(N, SDLoc(N), Ty, DAG); + if (!isPositionIndependent()) + return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) + : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } @@ -1882,7 +1889,7 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); EVT Ty = Op.getValueType(); - if (!isPositionIndependent() && !ABI.IsN64()) { + if (!isPositionIndependent()) { const MipsTargetObjectFile *TLOF = static_cast<const MipsTargetObjectFile *>( getTargetMachine().getObjFileLowering()); @@ -1892,10 +1899,11 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const // %gp_rel relocation return getAddrGPRel(N, SDLoc(N), Ty, DAG); - return getAddrNonPIC(N, SDLoc(N), Ty, DAG); + return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) + : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); } - return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { @@ -2796,14 +2804,13 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // 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. - bool IsPICCall = (ABI.IsN64() || IsPIC); // true if calls are translated to - // jalr $25 + SDValue CalleeLo; EVT Ty = Callee.getValueType(); bool GlobalOrExternal = false, IsCallReloc = false; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { - if (IsPICCall) { + if (IsPIC) { const GlobalValue *Val = G->getGlobal(); InternalLinkage = Val->hasInternalLinkage(); @@ -2828,7 +2835,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { const char *Sym = S->getSymbol(); - if (!ABI.IsN64() && !IsPIC) // !N64 && static + if (!IsPIC) // static Callee = DAG.getTargetExternalSymbol( Sym, getPointerTy(DAG.getDataLayout()), MipsII::MO_NO_FLAG); else if (LargeGOT) { @@ -2836,7 +2843,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Sym)); IsCallReloc = true; - } else { // N64 || PIC + } else { // PIC Callee = getAddrGlobal(S, DL, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Sym)); IsCallReloc = true; @@ -2848,7 +2855,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SmallVector<SDValue, 8> Ops(1, Chain); SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage, + getOpndList(Ops, RegsToPass, IsPIC, GlobalOrExternal, InternalLinkage, IsCallReloc, CLI, Callee, Chain); if (IsTailCall) { @@ -3683,7 +3690,9 @@ bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { } unsigned MipsTargetLowering::getJumpTableEncoding() const { - if (ABI.IsN64()) + + // FIXME: For space reasons this should be: EK_GPRel32BlockAddress. + if (ABI.IsN64() && isPositionIndependent()) return MachineJumpTableInfo::EK_GPRel64BlockAddress; return TargetLowering::getJumpTableEncoding(); diff --git a/llvm/lib/Target/Mips/MipsISelLowering.h b/llvm/lib/Target/Mips/MipsISelLowering.h index cddf0903ca6..abc34be6377 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/llvm/lib/Target/Mips/MipsISelLowering.h @@ -37,14 +37,23 @@ namespace llvm { // Tail call TailCall, - // Get the Higher 16 bits from a 32-bit immediate + // Get the Highest (63-48) 16 bits from a 64-bit immediate + Highest, + + // Get the Higher (47-32) 16 bits from a 64-bit immediate + Higher, + + // Get the High 16 bits from a 32/64-bit immediate // No relation with Mips Hi register Hi, - // Get the Lower 16 bits from a 32-bit immediate + // Get the Lower 16 bits from a 32/64-bit immediate // No relation with Mips Lo register Lo, + // Get the High 16 bits from a 32 bit immediate for accessing the GOT. + GotHi, + // Handle gp_rel (small data/bss sections) relocation. GPRel, @@ -297,7 +306,7 @@ namespace llvm { } bool isJumpTableRelative() const override { - return getTargetMachine().isPositionIndependent() || ABI.IsN64(); + return getTargetMachine().isPositionIndependent(); } protected: @@ -344,8 +353,8 @@ namespace llvm { SelectionDAG &DAG, unsigned HiFlag, unsigned LoFlag, SDValue Chain, const MachinePointerInfo &PtrInfo) const { - SDValue Hi = - DAG.getNode(MipsISD::Hi, DL, Ty, getTargetNode(N, Ty, DAG, HiFlag)); + SDValue Hi = DAG.getNode(MipsISD::GotHi, DL, Ty, + getTargetNode(N, Ty, DAG, HiFlag)); Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty)); SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi, getTargetNode(N, Ty, DAG, LoFlag)); @@ -356,6 +365,8 @@ namespace llvm { // computing a symbol's address in non-PIC mode: // // (add %hi(sym), %lo(sym)) + // + // This method covers O32, N32 and N64 in sym32 mode. template <class NodeTy> SDValue getAddrNonPIC(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG) const { @@ -364,7 +375,37 @@ namespace llvm { return DAG.getNode(ISD::ADD, DL, Ty, DAG.getNode(MipsISD::Hi, DL, Ty, Hi), DAG.getNode(MipsISD::Lo, DL, Ty, Lo)); - } + } + + // This method creates the following nodes, which are necessary for + // computing a symbol's address in non-PIC mode for N64. + // + // (add (shl (add (shl (add %highest(sym), %higher(sim)), 16), %high(sym)), + // 16), %lo(%sym)) + // + // FIXME: This method is not efficent for (micro)MIPS64R6. + template <class NodeTy> + SDValue getAddrNonPICSym64(NodeTy *N, const SDLoc &DL, EVT Ty, + SelectionDAG &DAG) const { + SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); + SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); + + SDValue Highest = + DAG.getNode(MipsISD::Highest, DL, Ty, + getTargetNode(N, Ty, DAG, MipsII::MO_HIGHEST)); + SDValue Higher = getTargetNode(N, Ty, DAG, MipsII::MO_HIGHER); + SDValue HigherPart = + DAG.getNode(ISD::ADD, DL, Ty, Highest, + DAG.getNode(MipsISD::Higher, DL, Ty, Higher)); + SDValue Cst = DAG.getConstant(16, DL, MVT::i32); + SDValue Shift = DAG.getNode(ISD::SHL, DL, Ty, HigherPart, Cst); + SDValue Add = DAG.getNode(ISD::ADD, DL, Ty, Shift, + DAG.getNode(MipsISD::Hi, DL, Ty, Hi)); + SDValue Shift2 = DAG.getNode(ISD::SHL, DL, Ty, Add, Cst); + + return DAG.getNode(ISD::ADD, DL, Ty, Shift2, + DAG.getNode(MipsISD::Lo, DL, Ty, Lo)); + } // This method creates the following nodes, which are necessary for // computing a symbol's address using gp-relative addressing: diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 5bc48336121..883dac3549f 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -59,10 +59,20 @@ def MipsTailCall : SDNode<"MipsISD::TailCall", SDT_MipsJmpLink, // 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) + +// Hi is the odd node out, on MIPS64 it can expand to either daddiu when +// using static relocations with 64 bit symbols, or lui when using 32 bit +// symbols. +def MipsHigher : SDNode<"MipsISD::Higher", SDTIntUnaryOp>; +def MipsHighest : SDNode<"MipsISD::Highest", SDTIntUnaryOp>; def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; + def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>; +// Hi node for accessing the GOT. +def MipsGotHi : SDNode<"MipsISD::GotHi", SDTIntUnaryOp>; + // TlsGd node is used to handle General Dynamic TLS def MipsTlsGd : SDNode<"MipsISD::TlsGd", SDTIntUnaryOp>; @@ -205,6 +215,10 @@ def HasCnMips : Predicate<"Subtarget->hasCnMips()">, AssemblerPredicate<"FeatureCnMips">; def NotCnMips : Predicate<"!Subtarget->hasCnMips()">, AssemblerPredicate<"!FeatureCnMips">; +def IsSym32 : Predicate<"Subtarget->HasSym32()">, + AssemblerPredicate<"FeatureSym32">; +def IsSym64 : Predicate<"!Subtarget->HasSym32()">, + AssemblerPredicate<"!FeatureSym32">; def RelocNotPIC : Predicate<"!TM.isPositionIndependent()">; def RelocPIC : Predicate<"TM.isPositionIndependent()">; def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; @@ -237,6 +251,14 @@ class PTR_32 { list<Predicate> PTRPredicates = [IsPTR32bit]; } class PTR_64 { list<Predicate> PTRPredicates = [IsPTR64bit]; } //===----------------------------------------------------------------------===// +// Mips Symbol size adjectives. +// They are mutally exculsive. +//===----------------------------------------------------------------------===// + +class SYM_32 { list<Predicate> SYMPredicates = [IsSym32]; } +class SYM_64 { list<Predicate> SYMPredicates = [IsSym64]; } + +//===----------------------------------------------------------------------===// // Mips ISA/ASE membership and instruction group membership adjectives. // They are mutually exclusive. //===----------------------------------------------------------------------===// @@ -2647,30 +2669,40 @@ def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)), def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)), (TAILCALL texternalsym:$dst)>; // hi/lo relocs -def : MipsPat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; -def : MipsPat<(MipsHi tblockaddress:$in), (LUi tblockaddress:$in)>; -def : MipsPat<(MipsHi tjumptable:$in), (LUi tjumptable:$in)>; -def : MipsPat<(MipsHi tconstpool:$in), (LUi tconstpool:$in)>; -def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>; -def : MipsPat<(MipsHi texternalsym:$in), (LUi texternalsym:$in)>; - -def : MipsPat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; -def : MipsPat<(MipsLo tblockaddress:$in), (ADDiu ZERO, tblockaddress:$in)>; -def : MipsPat<(MipsLo tjumptable:$in), (ADDiu ZERO, tjumptable:$in)>; -def : MipsPat<(MipsLo tconstpool:$in), (ADDiu ZERO, tconstpool:$in)>; -def : MipsPat<(MipsLo tglobaltlsaddr:$in), (ADDiu ZERO, tglobaltlsaddr:$in)>; -def : MipsPat<(MipsLo texternalsym:$in), (ADDiu ZERO, texternalsym:$in)>; - -def : MipsPat<(add GPR32:$hi, (MipsLo tglobaladdr:$lo)), - (ADDiu GPR32:$hi, tglobaladdr:$lo)>; -def : MipsPat<(add GPR32:$hi, (MipsLo tblockaddress:$lo)), - (ADDiu GPR32:$hi, tblockaddress:$lo)>; -def : MipsPat<(add GPR32:$hi, (MipsLo tjumptable:$lo)), - (ADDiu GPR32:$hi, tjumptable:$lo)>; -def : MipsPat<(add GPR32:$hi, (MipsLo tconstpool:$lo)), - (ADDiu GPR32:$hi, tconstpool:$lo)>; -def : MipsPat<(add GPR32:$hi, (MipsLo tglobaltlsaddr:$lo)), - (ADDiu GPR32:$hi, tglobaltlsaddr:$lo)>; +multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu, + Register ZeroReg, RegisterOperand GPROpnd> { + def : MipsPat<(MipsHi tglobaladdr:$in), (Lui tglobaladdr:$in)>; + def : MipsPat<(MipsHi tblockaddress:$in), (Lui tblockaddress:$in)>; + def : MipsPat<(MipsHi tjumptable:$in), (Lui tjumptable:$in)>; + def : MipsPat<(MipsHi tconstpool:$in), (Lui tconstpool:$in)>; + def : MipsPat<(MipsHi tglobaltlsaddr:$in), (Lui tglobaltlsaddr:$in)>; + def : MipsPat<(MipsHi texternalsym:$in), (Lui texternalsym:$in)>; + + def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>; + def : MipsPat<(MipsLo tblockaddress:$in), + (Addiu ZeroReg, tblockaddress:$in)>; + def : MipsPat<(MipsLo tjumptable:$in), (Addiu ZeroReg, tjumptable:$in)>; + def : MipsPat<(MipsLo tconstpool:$in), (Addiu ZeroReg, tconstpool:$in)>; + def : MipsPat<(MipsLo tglobaltlsaddr:$in), + (Addiu ZeroReg, tglobaltlsaddr:$in)>; + def : MipsPat<(MipsLo texternalsym:$in), (Addiu ZeroReg, texternalsym:$in)>; + + def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaladdr:$lo)), + (Addiu GPROpnd:$hi, tglobaladdr:$lo)>; + def : MipsPat<(add GPROpnd:$hi, (MipsLo tblockaddress:$lo)), + (Addiu GPROpnd:$hi, tblockaddress:$lo)>; + def : MipsPat<(add GPROpnd:$hi, (MipsLo tjumptable:$lo)), + (Addiu GPROpnd:$hi, tjumptable:$lo)>; + def : MipsPat<(add GPROpnd:$hi, (MipsLo tconstpool:$lo)), + (Addiu GPROpnd:$hi, tconstpool:$lo)>; + def : MipsPat<(add GPROpnd:$hi, (MipsLo tglobaltlsaddr:$lo)), + (Addiu GPROpnd:$hi, tglobaltlsaddr:$lo)>; +} + +defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>; + +def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; +def : MipsPat<(MipsGotHi texternalsym:$in), (LUi texternalsym:$in)>; // gp_rel relocs def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), diff --git a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index 92d3c001df9..edec1073c04 100644 --- a/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -97,11 +97,13 @@ bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI, // Check if MI is "addiu $dst, $zero, 0" or "daddiu $dst, $zero, 0". if ((MI.getOpcode() == Mips::ADDiu) && (MI.getOperand(1).getReg() == Mips::ZERO) && + (MI.getOperand(2).isImm()) && (MI.getOperand(2).getImm() == 0)) { DstReg = MI.getOperand(0).getReg(); ZeroReg = Mips::ZERO; } else if ((MI.getOpcode() == Mips::DADDiu) && (MI.getOperand(1).getReg() == Mips::ZERO_64) && + (MI.getOperand(2).isImm()) && (MI.getOperand(2).getImm() == 0)) { DstReg = MI.getOperand(0).getReg(); ZeroReg = Mips::ZERO_64; diff --git a/llvm/lib/Target/Mips/MipsSubtarget.cpp b/llvm/lib/Target/Mips/MipsSubtarget.cpp index 3e7570ff46e..8f5ecadecde 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -70,8 +70,8 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU, HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false), InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 | Mips_Os16), - Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasEVA(false), TM(TM), - TargetTriple(TT), TSInfo(), + Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false), + HasEVA(false), TM(TM), TargetTriple(TT), TSInfo(), InstrInfo( MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))), FrameLowering(MipsFrameLowering::create(*this)), @@ -117,6 +117,9 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU, if (NoABICalls && TM.isPositionIndependent()) report_fatal_error("position-independent code requires '-mabicalls'"); + if (isABI_N64() && !TM.isPositionIndependent() && !hasSym32()) + NoABICalls = true; + // Set UseSmallSection. UseSmallSection = GPOpt; if (!NoABICalls && GPOpt) { diff --git a/llvm/lib/Target/Mips/MipsSubtarget.h b/llvm/lib/Target/Mips/MipsSubtarget.h index 38d3cee7047..5f6fc7ca3ce 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/llvm/lib/Target/Mips/MipsSubtarget.h @@ -142,6 +142,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // UseTCCInDIV -- Enables the use of trapping in the assembler. bool UseTCCInDIV; + // Sym32 -- On Mips64 symbols are 32 bits. + bool HasSym32; + // HasEVA -- supports EVA ASE. bool HasEVA; @@ -229,6 +232,9 @@ public: unsigned getGPRSizeInBytes() const { return isGP64bit() ? 8 : 4; } bool isPTR64bit() const { return IsPTR64bit; } bool isPTR32bit() const { return !IsPTR64bit; } + bool hasSym32() const { + return (HasSym32 && isABI_N64()) || isABI_N32() || isABI_O32(); + } bool isSingleFloat() const { return IsSingleFloat; } bool hasVFPU() const { return HasVFPU; } bool inMips16Mode() const { return InMips16Mode; } |