Lower constant pools and jump tables via TOC on PPC64/SVR4.
authorRoman Divacky <rdivacky@freebsd.org>
Fri, 24 Aug 2012 16:26:02 +0000 (16:26 +0000)
committerRoman Divacky <rdivacky@freebsd.org>
Fri, 24 Aug 2012 16:26:02 +0000 (16:26 +0000)
In collaboration with Adhemerval Zanella.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162562 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/MC/MCExpr.h
lib/MC/MCExpr.cpp
lib/Target/PowerPC/PPCAsmPrinter.cpp
lib/Target/PowerPC/PPCISelLowering.cpp
lib/Target/PowerPC/PPCInstr64Bit.td
test/CodeGen/PowerPC/ppc64-toc.ll [new file with mode: 0644]

index ad65cba78268bfb47ef1c33a0c785a1c787f6994..ee7b144d6c602637e90e9f2d6c4a8ddcf56ffc4c 100644 (file)
@@ -171,7 +171,8 @@ public:
     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
index 0eb7fcce684bc24ecfa06b644c79e6277cd615a6..2d1cadd87f6ed39a5dc0f4ee938d465e5615f218 100644 (file)
@@ -197,7 +197,8 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
   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";
index f76b89c803ab8c43a87aaf6b7ff20e6a3212dcc4..2803f80a77776d85175cf9edf2dad94b9da26acf 100644 (file)
@@ -345,23 +345,32 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
     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);
index 61d44c52d438a4caf3c06469c4a140a139019c40..c18ba69e71c11adeabd4f06264a1c07bd9ab10a2 100644 (file)
@@ -1204,6 +1204,14 @@ SDValue PPCTargetLowering::LowerConstantPool(SDValue Op,
   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 =
@@ -1217,6 +1225,14 @@ SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
   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);
index 39778a5dc1e134c9b66ee9063b28accef171c448..c2351ecfe23d3b1bc7d91bb7eaee1e23a5fd34cc 100644 (file)
@@ -624,6 +624,14 @@ def LDtoc: Pseudo<(outs G8RC:$rD), (ins tocentry:$disp, G8RC:$reg),
                   "",
                   [(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.
diff --git a/test/CodeGen/PowerPC/ppc64-toc.ll b/test/CodeGen/PowerPC/ppc64-toc.ll
new file mode 100644 (file)
index 0000000..f1326ba
--- /dev/null
@@ -0,0 +1,67 @@
+; 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