Index: lib/Target/Mips/Mips64InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64InstrInfo.td +++ lib/Target/Mips/Mips64InstrInfo.td @@ -610,6 +610,12 @@ let AdditionalPredicates = [NotInMicroMips] in defm : MipsHighestHigherHiLoRelocs, SYM_64; +// gp_rel relocs +def : MipsPat<(add GPR64:$gp, (MipsGPRel tglobaladdr:$in)), + (DADDiu GPR64:$gp, tglobaladdr:$in)>, ABI_N64; +def : MipsPat<(add GPR64:$gp, (MipsGPRel tconstpool:$in)), + (DADDiu GPR64:$gp, tconstpool:$in)>, ABI_N64; + def : WrapperPat; def : WrapperPat; def : WrapperPat; Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -475,13 +475,12 @@ // (add $gp, %gp_rel(sym)) template SDValue getAddrGPRel(NodeTy *N, const SDLoc &DL, EVT Ty, - SelectionDAG &DAG) const { - assert(Ty == MVT::i32); + SelectionDAG &DAG, bool IsN64) const { SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL); - return DAG.getNode(ISD::ADD, DL, Ty, - DAG.getRegister(Mips::GP, Ty), - DAG.getNode(MipsISD::GPRel, DL, DAG.getVTList(Ty), - GPRel)); + return DAG.getNode( + ISD::ADD, DL, Ty, + DAG.getRegister(IsN64 ? Mips::GP_64 : Mips::GP, Ty), + DAG.getNode(MipsISD::GPRel, DL, DAG.getVTList(Ty), GPRel)); } /// This function fills Ops, which is the list of operands that will later Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -2057,7 +2057,7 @@ const GlobalObject *GO = GV->getBaseObject(); if (GO && TLOF->IsGlobalInSmallSection(GO, getTargetMachine())) // %gp_rel relocation - return getAddrGPRel(N, SDLoc(N), Ty, DAG); + return getAddrGPRel(N, SDLoc(N), Ty, DAG, ABI.IsN64()); // %hi/%lo relocation return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) @@ -2212,7 +2212,7 @@ if (TLOF->IsConstantInSmallSection(DAG.getDataLayout(), N->getConstVal(), getTargetMachine())) // %gp_rel relocation - return getAddrGPRel(N, SDLoc(N), Ty, DAG); + return getAddrGPRel(N, SDLoc(N), Ty, DAG, ABI.IsN64()); return Subtarget.hasSym32() ? getAddrNonPIC(N, SDLoc(N), Ty, DAG) : getAddrNonPICSym64(N, SDLoc(N), Ty, DAG); Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -220,6 +220,8 @@ AssemblerPredicate<"FeatureSym32">; def IsSym64 : Predicate<"!Subtarget->HasSym32()">, AssemblerPredicate<"!FeatureSym32">; +def IsN64 : Predicate<"Subtarget->isABI_N64()">; +def IsNotN64 : Predicate<"!Subtarget->isABI_N64()">; def RelocNotPIC : Predicate<"!TM.isPositionIndependent()">; def RelocPIC : Predicate<"TM.isPositionIndependent()">; def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; @@ -401,6 +403,16 @@ list AdditionalPredicates = [HasMadd4]; } +// Classses used for separating expansions that differ based on the ABI in +// use. +class ABI_N64 { + list AdditionalPredicates = [IsN64]; +} + +class ABI_NOT_N64 { + list AdditionalPredicates = [IsNotN64]; +} + //===----------------------------------------------------------------------===// class MipsPat : Pat, PredicateControl { @@ -2748,9 +2760,9 @@ // gp_rel relocs def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), - (ADDiu GPR32:$gp, tglobaladdr:$in)>; + (ADDiu GPR32:$gp, tglobaladdr:$in)>, ABI_NOT_N64; def : MipsPat<(add GPR32:$gp, (MipsGPRel tconstpool:$in)), - (ADDiu GPR32:$gp, tconstpool:$in)>; + (ADDiu GPR32:$gp, tconstpool:$in)>, ABI_NOT_N64; // wrapper_pic class WrapperPat: Index: test/CodeGen/Mips/2008-07-15-SmallSection.ll =================================================================== --- test/CodeGen/Mips/2008-07-15-SmallSection.ll +++ test/CodeGen/Mips/2008-07-15-SmallSection.ll @@ -1,14 +1,33 @@ -; RUN: llc < %s -march=mips -mcpu=mips32 -mips-ssection-threshold=8 \ +; RUN: llc < %s -march=mips -mcpu=mips32 -mips-ssection-threshold=8 -verify-machineinstrs \ ; RUN: -relocation-model=static -mattr=+noabicalls -mgpopt \ -; RUN: | FileCheck %s --check-prefixes=BASIC,COMMON -; RUN: llc < %s -march=mips -mcpu=mips32 -mips-ssection-threshold=8 \ +; RUN: | FileCheck %s --check-prefixes=BASIC,COMMON,ADDR32 +; RUN: llc < %s -march=mips -mcpu=mips32 -mips-ssection-threshold=8 -verify-machineinstrs \ ; RUN: -relocation-model=static -mattr=+noabicalls -mgpopt -membedded-data \ -; RUN: | FileCheck %s --check-prefixes=EMBDATA,COMMON +; RUN: | FileCheck %s --check-prefixes=EMBDATA,COMMON,ADDR32 + +; RUN: llc < %s -march=mips64 -mcpu=mips4 -mips-ssection-threshold=8 -verify-machineinstrs \ +; RUN: -relocation-model=static -mattr=+noabicalls -mgpopt -target-abi n64 \ +; RUN: | FileCheck %s --check-prefixes=BASIC,COMMON,N64 +; RUN: llc < %s -march=mips64 -mcpu=mips4 -mips-ssection-threshold=8 -verify-machineinstrs \ +; RUN: -relocation-model=static -mattr=+noabicalls,+sym32 -mgpopt -target-abi n64 \ +; RUN: | FileCheck %s --check-prefixes=BASIC,COMMON,N64 +; RUN: llc < %s -march=mips64 -mcpu=mips4 -mips-ssection-threshold=8 -verify-machineinstrs \ +; RUN: -relocation-model=static -mattr=+noabicalls -mgpopt -target-abi n32 \ +; RUN: | FileCheck %s --check-prefixes=BASIC,COMMON,ADDR32 ; Test the layout of objects when compiling for static, noabicalls environment. %struct.anon = type { i32, i32 } +; Check that when synthesizing a pointer to the second element of foo, that +; we use the correct addition operation. O32 and N32 have 32-bit address +; spaces, so they use addiu. N64 has a 64bit address space, but has a submode +; where symbol sizes are 32 bits. In those cases we use daddiu. + +; CHECK-LABEL: A1: +; N64: daddiu ${{[0-9]+}}, $gp, %gp_rel(foo) +; ADDR32: addiu ${{[0-9]+}}, $gp, %gp_rel(foo) + ; BASIC: .type s0,@object ; BASIC-NEXT: .section .sdata,"aw",@progbits