summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp4
-rw-r--r--llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp15
-rw-r--r--llvm/lib/Target/Mips/MicroMips64r6InstrInfo.td28
-rw-r--r--llvm/lib/Target/Mips/Mips.td2
-rw-r--r--llvm/lib/Target/Mips/Mips64InstrInfo.td114
-rw-r--r--llvm/lib/Target/Mips/MipsAsmPrinter.cpp4
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.cpp43
-rw-r--r--llvm/lib/Target/Mips/MipsISelLowering.h53
-rw-r--r--llvm/lib/Target/Mips/MipsInstrInfo.td80
-rw-r--r--llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp2
-rw-r--r--llvm/lib/Target/Mips/MipsSubtarget.cpp7
-rw-r--r--llvm/lib/Target/Mips/MipsSubtarget.h6
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; }
OpenPOWER on IntegriCloud