diff options
author | Simon Dardis <simon.dardis@imgtec.com> | 2017-01-26 10:19:02 +0000 |
---|---|---|
committer | Simon Dardis <simon.dardis@imgtec.com> | 2017-01-26 10:19:02 +0000 |
commit | 09e65efd09b862f7410c7ea80b977bd4b87f8275 (patch) | |
tree | d3744d646176f213471d621c417559e26ee794d2 /llvm/lib/Target | |
parent | 278c722e6d01c3737785aa625e622eb430d27845 (diff) | |
download | bcm5719-llvm-09e65efd09b862f7410c7ea80b977bd4b87f8275.tar.gz bcm5719-llvm-09e65efd09b862f7410c7ea80b977bd4b87f8275.zip |
[mips] N64 static relocation model support
This patch makes one change to GOT handling and two changes to N64's
relocation model handling. Furthermore, the jumptable encodings have
been corrected for static N64.
Big GOT handling is now done via a new SDNode MipsGotHi - this node is
unconditionally lowered to an lui instruction.
The first change to N64's relocation handling is the lifting of the
restriction that N64 always uses PIC. Now it is possible to target static
environments.
The second change adds support for 64 bit symbols and enables them by
default. Previously N64 had patterns for sym32 mode only. In this mode all
symbols are assumed to have 32 bit addresses. sym32 mode support
is selectable with attribute 'sym32'. A follow on patch for clang will
add the necessary frontend parameter.
This partially resolves PR/23485.
Thanks to Brooks Davis for reporting the issue!
Reviewers: dsanders, seanbruno, zoran.jovanovic, vkalintiris
Differential Revision: https://reviews.llvm.org/D23652
llvm-svn: 293164
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp | 16 | ||||
-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 | 3 | ||||
-rw-r--r-- | llvm/lib/Target/Mips/MipsSubtarget.h | 6 |
12 files changed, 240 insertions, 115 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..93c74fa3a9a 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,14 @@ 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] && !getABI().IsN64()) || + (getABI().IsN64() && Features[Mips::FeatureSym32])) + 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..2e346d6366b 100644 --- a/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -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; } |