VK_ARM_GOTTPOFF,
VK_ARM_TARGET1,
- VK_PPC_TOC,
+ VK_PPC_TOC, // TOC base
+ VK_PPC_TOC_ENTRY, // TOC entry
VK_PPC_DARWIN_HA16, // ha16(symbol)
VK_PPC_DARWIN_LO16, // lo16(symbol)
VK_PPC_GAS_HA16, // symbol@ha
case VK_ARM_GOTTPOFF: return "(gottpoff)";
case VK_ARM_TLSGD: return "(tlsgd)";
case VK_ARM_TARGET1: return "(target1)";
- case VK_PPC_TOC: return "toc";
+ case VK_PPC_TOC: return "tocbase";
+ case VK_PPC_TOC_ENTRY: return "toc";
case VK_PPC_DARWIN_HA16: return "ha16";
case VK_PPC_DARWIN_LO16: return "lo16";
case VK_PPC_GAS_HA16: return "ha";
OutStreamer.EmitLabel(PICBase);
return;
}
+ case PPC::LDtocJTI:
+ case PPC::LDtocCPT:
case PPC::LDtoc: {
// Transform %X3 = LDtoc <ga:@min1>, %X2
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
-
+
// Change the opcode to LD, and the global address operand to be a
// reference to the TOC entry we will synthesize later.
TmpInst.setOpcode(PPC::LD);
const MachineOperand &MO = MI->getOperand(1);
- assert(MO.isGlobal());
-
- // Map symbol -> label of TOC entry.
- MCSymbol *&TOCEntry = TOC[Mang->getSymbol(MO.getGlobal())];
+
+ // Map symbol -> label of TOC entry
+ assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());
+ MCSymbol *MOSymbol = 0;
+ if (MO.isGlobal())
+ MOSymbol = Mang->getSymbol(MO.getGlobal());
+ else if (MO.isCPI())
+ MOSymbol = GetCPISymbol(MO.getIndex());
+ else if (MO.isJTI())
+ MOSymbol = GetJTISymbol(MO.getIndex());
+ MCSymbol *&TOCEntry = TOC[MOSymbol];
if (TOCEntry == 0)
TOCEntry = GetTempSymbol("C", TOCLabelID++);
-
+
const MCExpr *Exp =
- MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC,
+ MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC_ENTRY,
OutContext);
TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
OutStreamer.EmitInstruction(TmpInst);
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
const Constant *C = CP->getConstVal();
+ // 64-bit SVR4 ABI code is always position-independent.
+ // The actual address of the GlobalValue is stored in the TOC.
+ if (PPCSubTarget.isSVR4ABI() && PPCSubTarget.isPPC64()) {
+ SDValue GA = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0);
+ return DAG.getNode(PPCISD::TOC_ENTRY, CP->getDebugLoc(), MVT::i64, GA,
+ DAG.getRegister(PPC::X2, MVT::i64));
+ }
+
unsigned MOHiFlag, MOLoFlag;
bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag);
SDValue CPIHi =
EVT PtrVT = Op.getValueType();
JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
+ // 64-bit SVR4 ABI code is always position-independent.
+ // The actual address of the GlobalValue is stored in the TOC.
+ if (PPCSubTarget.isSVR4ABI() && PPCSubTarget.isPPC64()) {
+ SDValue GA = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
+ return DAG.getNode(PPCISD::TOC_ENTRY, JT->getDebugLoc(), MVT::i64, GA,
+ DAG.getRegister(PPC::X2, MVT::i64));
+ }
+
unsigned MOHiFlag, MOLoFlag;
bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag);
SDValue JTIHi = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, MOHiFlag);
"",
[(set G8RC:$rD,
(PPCtoc_entry tglobaladdr:$disp, G8RC:$reg))]>, isPPC64;
+def LDtocJTI: Pseudo<(outs G8RC:$rD), (ins tocentry:$disp, G8RC:$reg),
+ "",
+ [(set G8RC:$rD,
+ (PPCtoc_entry tjumptable:$disp, G8RC:$reg))]>, isPPC64;
+def LDtocCPT: Pseudo<(outs G8RC:$rD), (ins tocentry:$disp, G8RC:$reg),
+ "",
+ [(set G8RC:$rD,
+ (PPCtoc_entry tconstpool:$disp, G8RC:$reg))]>, isPPC64;
let hasSideEffects = 1 in {
let RST = 2, DS_RA = 0 in // FIXME: Should be a pseudo.
--- /dev/null
+; RUN: llc < %s | FileCheck %s\r
+target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64"\r
+target triple = "powerpc64-unknown-linux-gnu"\r
+\r
+@double_array = global [32 x double] zeroinitializer, align 8\r
+@number64 = global i64 10, align 8\r
+@internal_static_var.x = internal unnamed_addr global i64 0, align 8\r
+\r
+define i64 @access_int64(i64 %a) nounwind readonly {\r
+entry:\r
+; CHECK: access_int64:\r
+; CHECK-NEXT: .align 3\r
+; CHECK-NEXT: .quad .L.access_int64\r
+; CHECK-NEXT: .quad .TOC.@tocbase\r
+; CHECK-NEXT: .text\r
+ %0 = load i64* @number64, align 8\r
+; CHECK: ld {{[0-9]+}}, .LC{{[0-9]+}}@toc(2)\r
+ %cmp = icmp eq i64 %0, %a\r
+ %conv1 = zext i1 %cmp to i64 \r
+ ret i64 %conv1\r
+}\r
+\r
+define i64 @internal_static_var(i64 %a) nounwind {\r
+entry:\r
+; CHECK: internal_static_var:\r
+; CHECK: ld {{[0-9]+}}, .LC{{[0-9]+}}@toc(2)\r
+ %0 = load i64* @internal_static_var.x, align 8\r
+ %cmp = icmp eq i64 %0, %a\r
+ %conv1 = zext i1 %cmp to i64 \r
+ ret i64 %conv1 \r
+}\r
+\r
+define i32 @access_double(double %a) nounwind readnone {\r
+entry:\r
+; CHECK: access_double:\r
+; CHECK: ld {{[0-9]+}}, .LC{{[0-9]+}}@toc(2)\r
+ %cmp = fcmp oeq double %a, 2.000000e+00\r
+ %conv = zext i1 %cmp to i32 \r
+ ret i32 %conv\r
+}\r
+\r
+\r
+define i32 @access_double_array(double %a, i32 %i) nounwind readonly {\r
+entry:\r
+; CHECK: access_double_array:\r
+ %idxprom = sext i32 %i to i64\r
+ %arrayidx = getelementptr inbounds [32 x double]* @double_array, i64 0, i64 %idxprom\r
+ %0 = load double* %arrayidx, align 8\r
+; CHECK: ld {{[0-9]+}}, .LC{{[0-9]+}}@toc(2)\r
+ %cmp = fcmp oeq double %0, %a\r
+ %conv = zext i1 %cmp to i32\r
+ ret i32 %conv\r
+}\r
+\r
+; Check the creation of 4 .tc entries:\r
+; * int64_t global 'number64'\r
+; * double constant 2.0\r
+; * double array 'double_array'\r
+; * static int64_t 'x' accessed within '@internal_static_var'\r
+; CHECK: .LC{{[0-9]+}}:\r
+; CHECK-NEXT: .tc {{[\._a-zA-Z0-9]+}}[TC],{{[\._a-zA-Z0-9]+}}\r
+; CHECK-NEXT: .LC{{[0-9]+}}:\r
+; CHECK-NEXT: .tc {{[\._a-zA-Z0-9]+}}[TC],{{[\._a-zA-Z0-9]+}}\r
+; CHECK-NEXT: .LC{{[0-9]+}}:\r
+; CHECK-NEXT: .tc {{[\._a-zA-Z0-9]+}}[TC],{{[\._a-zA-Z0-9]+}}\r
+; CHECK-NEXT: .LC{{[0-9]+}}:\r
+; CHECK-NEXT: .tc {{[\._a-zA-Z0-9]+}}[TC],{{[\._a-zA-Z0-9]+}}\r