Index: llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4888,9 +4888,9 @@ SDValue TOCbase = N->getOperand(1); SDNode *Tmp = CurDAG->getMachineNode(PPC::ADDIStocHA, dl, MVT::i64, TOCbase, GA); - - if (isa(GA) || isa(GA) || - CModel == CodeModel::Large) { + if (PPCLowering->isAccessedAsTOCIndirect(GA)) { + // If it is access as TOC indirect, we need an extra LD to load + // the address. SDNode *MN = CurDAG->getMachineNode(PPC::LDtocL, dl, MVT::i64, GA, SDValue(Tmp, 0)); transferMemOperands(N, MN); @@ -4898,18 +4898,7 @@ return; } - if (GlobalAddressSDNode *G = dyn_cast(GA)) { - const GlobalValue *GV = G->getGlobal(); - unsigned char GVFlags = PPCSubTarget->classifyGlobalReference(GV); - if (GVFlags & PPCII::MO_NLP_FLAG) { - SDNode *MN = CurDAG->getMachineNode(PPC::LDtocL, dl, MVT::i64, GA, - SDValue(Tmp, 0)); - transferMemOperands(N, MN); - ReplaceNode(N, MN); - return; - } - } - + // The TOC entry keeps the global address. ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL, dl, MVT::i64, SDValue(Tmp, 0), GA)); return; Index: llvm/lib/Target/PowerPC/PPCISelLowering.h =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.h +++ llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -789,6 +789,9 @@ return true; } + // Returns true if the address of the global is stored in TOC entry. + bool isAccessedAsTOCIndirect(SDValue N) const; + bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; bool getTgtMemIntrinsic(IntrinsicInfo &Info, Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -13710,6 +13710,35 @@ report_fatal_error("Invalid register name global variable"); } +bool PPCTargetLowering::isAccessedAsTOCIndirect(SDValue GA) const { + // 32-bit SVR4 ABI access everything as toc-indirect. + if (Subtarget.isSVR4ABI() && !Subtarget.isPPC64()) + return true; + + CodeModel::Model CModel = getTargetMachine().getCodeModel(); + // If it is small or large code model, module locals are accessed + // indirectly by loading their address from .toc/.got. The difference + // is that for large code model we have ADDISTocHa + LDtocL and for + // small code model we simply have LDtoc. + if (CModel == CodeModel::Small || CModel == CodeModel::Large) + return true; + + // JumpTable and BlockAddress are accessed as toc-indirect. + if (isa(GA) || isa(GA)) + return true; + + // If the global reference is actually to a non-lazy-pointer, we have to + // do an extra load to get the address of the global. + if (GlobalAddressSDNode *G = dyn_cast(GA)) { + const GlobalValue *GV = G->getGlobal(); + unsigned char GVFlags = Subtarget.classifyGlobalReference(GV); + if (GVFlags & PPCII::MO_NLP_FLAG) + return true; + } + + return false; +} + bool PPCTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { // The PowerPC target isn't yet aware of offsets.