diff options
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 19 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelLowering.h | 3 |
3 files changed, 36 insertions, 15 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 8af96804ced..7d9ea93f533 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4897,9 +4897,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) { SDValue TOCbase = N->getOperand(1); SDNode *Tmp = CurDAG->getMachineNode(PPC::ADDIStocHA, dl, MVT::i64, TOCbase, GA); - - if (isa<JumpTableSDNode>(GA) || isa<BlockAddressSDNode>(GA) || - CModel == CodeModel::Large) { + if (PPCLowering->isAccessedAsGotIndirect(GA)) { + // If it is access as got-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); @@ -4907,18 +4907,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) { return; } - if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(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; - } - } - + // Build the address relative to the TOC-pointer.. ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL, dl, MVT::i64, SDValue(Tmp, 0), GA)); return; diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 608a977893b..dd99b71eda6 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -13710,6 +13710,35 @@ unsigned PPCTargetLowering::getRegisterByName(const char* RegName, EVT VT, report_fatal_error("Invalid register name global variable"); } +bool PPCTargetLowering::isAccessedAsGotIndirect(SDValue GA) const { + // 32-bit SVR4 ABI access everything as got-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 got-indirect. + if (isa<JumpTableSDNode>(GA) || isa<BlockAddressSDNode>(GA)) + return true; + + if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(GA)) { + const GlobalValue *GV = G->getGlobal(); + unsigned char GVFlags = Subtarget.classifyGlobalReference(GV); + // The NLP flag indicates that a global access has to use an + // extra indirection. + 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. diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h index 1020cab48c8..7a6c22fb9cf 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -789,6 +789,9 @@ namespace llvm { return true; } + // Returns true if the address of the global is stored in TOC entry. + bool isAccessedAsGotIndirect(SDValue N) const; + bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; bool getTgtMemIntrinsic(IntrinsicInfo &Info, |