From: Ulrich Weigand Date: Fri, 31 Oct 2014 10:33:14 +0000 (+0000) Subject: [PowerPC] Load BlockAddress values from the TOC in 64-bit SVR4 code X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=8a9c531e9adfdd7fee915fbcfb9ecad18da5674c [PowerPC] Load BlockAddress values from the TOC in 64-bit SVR4 code Since block address values can be larger than 2GB in 64-bit code, they cannot be loaded simply using an @l / @ha pair, but instead must be loaded from the TOC, just like GlobalAddress, ConstantPool, and JumpTable values are. The commit also fixes a bug in PPCLinuxAsmPrinter::doFinalization where temporary labels could not be used as TOC values, since code would attempt (and fail) to use GetOrCreateSymbol to create a symbol of the same name as the temporary label. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220959 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 5b68a9eaacf..03338886737 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -385,7 +385,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MachineOperand &MO = MI->getOperand(1); // Map symbol -> label of TOC entry - assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); + assert(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()); MCSymbol *MOSymbol = nullptr; if (MO.isGlobal()) MOSymbol = getSymbol(MO.getGlobal()); @@ -393,6 +393,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { MOSymbol = GetCPISymbol(MO.getIndex()); else if (MO.isJTI()) MOSymbol = GetJTISymbol(MO.getIndex()); + else if (MO.isBlockAddress()) + MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress()); MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); @@ -409,6 +411,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { } case PPC::LDtocJTI: case PPC::LDtocCPT: + case PPC::LDtocBA: case PPC::LDtoc: { // Transform %X3 = LDtoc , %X2 LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); @@ -419,7 +422,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const MachineOperand &MO = MI->getOperand(1); // Map symbol -> label of TOC entry - assert(MO.isGlobal() || MO.isCPI() || MO.isJTI()); + assert(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()); MCSymbol *MOSymbol = nullptr; if (MO.isGlobal()) MOSymbol = getSymbol(MO.getGlobal()); @@ -427,6 +430,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { MOSymbol = GetCPISymbol(MO.getIndex()); else if (MO.isJTI()) MOSymbol = GetJTISymbol(MO.getIndex()); + else if (MO.isBlockAddress()) + MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress()); MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); @@ -448,7 +453,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { // reference the symbol directly. TmpInst.setOpcode(PPC::ADDIS8); const MachineOperand &MO = MI->getOperand(2); - assert((MO.isGlobal() || MO.isCPI() || MO.isJTI()) && + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || + MO.isBlockAddress()) && "Invalid operand for ADDIStocHA!"); MCSymbol *MOSymbol = nullptr; bool IsExternal = false; @@ -468,9 +474,12 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { MOSymbol = GetCPISymbol(MO.getIndex()); else if (MO.isJTI()) MOSymbol = GetJTISymbol(MO.getIndex()); + else if (MO.isBlockAddress()) + MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress()); if (IsExternal || IsNonLocalFunction || IsCommon || IsAvailExt || - MO.isJTI() || TM.getCodeModel() == CodeModel::Large) + MO.isJTI() || MO.isBlockAddress() || + TM.getCodeModel() == CodeModel::Large) MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); const MCExpr *Exp = @@ -489,12 +498,17 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { // associated TOC entry. Otherwise reference the symbol directly. TmpInst.setOpcode(PPC::LD); const MachineOperand &MO = MI->getOperand(1); - assert((MO.isGlobal() || MO.isJTI() || MO.isCPI()) && + assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || + MO.isBlockAddress()) && "Invalid operand for LDtocL!"); MCSymbol *MOSymbol = nullptr; if (MO.isJTI()) MOSymbol = lookUpOrCreateTOCEntry(GetJTISymbol(MO.getIndex())); + else if (MO.isBlockAddress()) { + MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress()); + MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); + } else if (MO.isCPI()) { MOSymbol = GetCPISymbol(MO.getIndex()); if (TM.getCodeModel() == CodeModel::Large) @@ -978,7 +992,7 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) { for (MapVector::iterator I = TOC.begin(), E = TOC.end(); I != E; ++I) { OutStreamer.EmitLabel(I->second); - MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName()); + MCSymbol *S = I->first; if (isPPC64) TS.emitTCEntry(*S); else diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 2d3006310d3..0b731cfba6a 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -1452,7 +1452,7 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) { // For medium and large code model, we generate two instructions as // described below. Otherwise we allow SelectCodeCommon to handle this, - // selecting one of LDtoc, LDtocJTI, and LDtocCPT. + // selecting one of LDtoc, LDtocJTI, LDtocCPT, and LDtocBA. CodeModel::Model CModel = TM.getCodeModel(); if (CModel != CodeModel::Medium && CModel != CodeModel::Large) break; @@ -1469,7 +1469,8 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) { SDNode *Tmp = CurDAG->getMachineNode(PPC::ADDIStocHA, dl, MVT::i64, TOCbase, GA); - if (isa(GA) || CModel == CodeModel::Large) + if (isa(GA) || isa(GA) || + CModel == CodeModel::Large) return CurDAG->getMachineNode(PPC::LDtocL, dl, MVT::i64, GA, SDValue(Tmp, 0)); diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 72d3a59192b..c9e2802f7ad 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1638,8 +1638,16 @@ SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const { EVT PtrVT = Op.getValueType(); + BlockAddressSDNode *BASDN = cast(Op); + const BlockAddress *BA = BASDN->getBlockAddress(); - const BlockAddress *BA = cast(Op)->getBlockAddress(); + // 64-bit SVR4 ABI code is always position-independent. + // The actual BlockAddress is stored in the TOC. + if (Subtarget.isSVR4ABI() && Subtarget.isPPC64()) { + SDValue GA = DAG.getTargetBlockAddress(BA, PtrVT, BASDN->getOffset()); + return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(BASDN), MVT::i64, GA, + DAG.getRegister(PPC::X2, MVT::i64)); + } unsigned MOHiFlag, MOLoFlag; bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag); diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td index b3e551d29cd..04ab8b39eb2 100644 --- a/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/lib/Target/PowerPC/PPCInstr64Bit.td @@ -786,7 +786,7 @@ let canFoldAsLoad = 1, PPC970_Unit = 2 in { def LD : DSForm_1<58, 0, (outs g8rc:$rD), (ins memrix:$src), "ld $rD, $src", IIC_LdStLD, [(set i64:$rD, (aligned4load ixaddr:$src))]>, isPPC64; -// The following three definitions are selected for small code model only. +// The following four definitions are selected for small code model only. // Otherwise, we need to create two instructions to form a 32-bit offset, // so we have a custom matcher for TOC_ENTRY in PPCDAGToDAGIsel::Select(). def LDtoc: Pseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc:$reg), @@ -801,6 +801,10 @@ def LDtocCPT: Pseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc:$reg), "#LDtocCPT", [(set i64:$rD, (PPCtoc_entry tconstpool:$disp, i64:$reg))]>, isPPC64; +def LDtocBA: Pseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc:$reg), + "#LDtocCPT", + [(set i64:$rD, + (PPCtoc_entry tblockaddress:$disp, i64:$reg))]>, isPPC64; let hasSideEffects = 1, isCodeGenOnly = 1, RST = 2, Defs = [X2] in def LDinto_toc: DSForm_1<58, 0, (outs), (ins memrix:$src), diff --git a/test/CodeGen/PowerPC/blockaddress.ll b/test/CodeGen/PowerPC/blockaddress.ll new file mode 100644 index 00000000000..c1981e21fff --- /dev/null +++ b/test/CodeGen/PowerPC/blockaddress.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s -code-model=small -march=ppc64 -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=SMALL +; RUN: llc < %s -code-model=medium -march=ppc64 -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=MEDIUM +; RUN: llc < %s -code-model=large -march=ppc64 -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=MEDIUM +; RUN: llc < %s -code-model=small -march=ppc64 -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s -check-prefix=SMALL +; RUN: llc < %s -code-model=medium -march=ppc64 -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s -check-prefix=MEDIUM +; RUN: llc < %s -code-model=large -march=ppc64 -mtriple=powerpc64le-unknown-linux-gnu | FileCheck %s -check-prefix=MEDIUM + +define i8* @test() { +entry: + br label %here + +here: ; preds = %entry +; MEDIUM: .Ltmp[[TMP0:[0-9]+]]: +; MEDIUM: addis [[R0:[0-9]+]], 2, .LC[[LC0:[0-9]+]]@toc@ha +; MEDIUM: ld 3, .LC[[LC0]]@toc@l([[R0]]) +; MEDIUM: blr +; MEDIUM: .LC[[LC0]]: +; MEDIUM: .tc .Ltmp[[TMP0]][TC],.Ltmp[[TMP0]] +; SMALL: .Ltmp[[TMP0:[0-9]+]]: +; SMALL: ld 3, .LC[[LC0:[0-9]+]]@toc(2) +; SMALL: blr +; SMALL: .LC[[LC0]]: +; SMALL: .tc .Ltmp[[TMP0]][TC],.Ltmp[[TMP0]] + ret i8* blockaddress(@test, %here) +} +