[llvm] 415e821 - [PowerPC][AIX] Add toc-data support for 64-bit AIX small code model.

Sean Fertile via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 1 07:57:55 PST 2021


Author: Yousuf Ali
Date: 2021-12-01T10:56:21-05:00
New Revision: 415e821a5089d7b2a49cc8e1717702f46ffdae86

URL: https://github.com/llvm/llvm-project/commit/415e821a5089d7b2a49cc8e1717702f46ffdae86
DIFF: https://github.com/llvm/llvm-project/commit/415e821a5089d7b2a49cc8e1717702f46ffdae86.diff

LOG: [PowerPC][AIX] Add toc-data support for 64-bit AIX small code model.

The patch expands the existing 32-bit toc-data attribute support to 64-bit.
In both 32-bit and 64-bit it is supported for small code model only.

Differential Revision: https://reviews.llvm.org/D114654

Added: 
    

Modified: 
    llvm/lib/Target/PowerPC/P10InstrResources.td
    llvm/lib/Target/PowerPC/P9InstrResources.td
    llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
    llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
    llvm/lib/Target/PowerPC/PPCInstr64Bit.td
    llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll
    llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
    llvm/test/CodeGen/PowerPC/toc-data.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/PowerPC/P10InstrResources.td b/llvm/lib/Target/PowerPC/P10InstrResources.td
index 5906564810864..f3ae0010ad8ef 100644
--- a/llvm/lib/Target/PowerPC/P10InstrResources.td
+++ b/llvm/lib/Target/PowerPC/P10InstrResources.td
@@ -1976,7 +1976,7 @@ def : InstRW<[P10W_SX, P10W_DISP_ANY],
     ICBLQ,
     ICBTLS,
     ICCCI,
-    LA,
+    LA, LA8,
     LDMX,
     MFDCR,
     MFPMR,
@@ -2075,3 +2075,4 @@ def : InstRW<[P10W_vMU_7C, P10W_DISP_ANY, P10vMU_Read, P10vMU_Read, P10vMU_Read]
     VMSUMUHM,
     VMSUMUHS
 )>;
+

diff  --git a/llvm/lib/Target/PowerPC/P9InstrResources.td b/llvm/lib/Target/PowerPC/P9InstrResources.td
index 070a662179da7..f7c049951c54b 100644
--- a/llvm/lib/Target/PowerPC/P9InstrResources.td
+++ b/llvm/lib/Target/PowerPC/P9InstrResources.td
@@ -151,6 +151,7 @@ def : InstRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C],
     (instregex "ADD(4|8)(TLS)?(_)?$"),
     (instregex "NEG(8)?(O)?$"),
     (instregex "ADDI(S)?toc(HA|L)(8)?$"),
+    (instregex "LA(8)?$"),
     COPY,
     MCRF,
     MCRXRX,
@@ -165,7 +166,6 @@ def : InstRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C],
     SRADI_32,
     RLDIC,
     RFEBB,
-    LA,
     TBEGIN,
     TRECHKPT,
     NOP,

diff  --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index a76963abb8e45..16e3b2b85c2e0 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -875,18 +875,19 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
     EmitToStreamer(*OutStreamer, TmpInst);
     return;
   }
-  case PPC::ADDItoc: {
+  case PPC::ADDItoc:
+  case PPC::ADDItoc8: {
     assert(IsAIX && TM.getCodeModel() == CodeModel::Small &&
-           "Operand only valid in AIX 32 bit mode");
+           "PseudoOp only valid for small code model AIX");
 
-    // Transform %rN = ADDItoc @op1, %r2.
+    // Transform %rN = ADDItoc/8 @op1, %r2.
     LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
 
     // Change the opcode to load address.
-    TmpInst.setOpcode(PPC::LA);
+    TmpInst.setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));
 
     const MachineOperand &MO = MI->getOperand(1);
-    assert(MO.isGlobal() && "Invalid operand for ADDItoc.");
+    assert(MO.isGlobal() && "Invalid operand for ADDItoc[8].");
 
     // Map the operand to its corresponding MCSymbol.
     const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);

diff  --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 247faa8b46a84..a2664bcff4ab0 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -510,14 +510,12 @@ static bool hasTocDataAttr(SDValue Val, unsigned PointerSize) {
     return false;
 
   // TODO: These asserts should be updated as more support for the toc data
-  // transformation is added (64 bit, struct support, etc.).
+  // transformation is added (struct support, etc.).
 
-  assert(PointerSize == 4 && "Only 32 Bit Codegen is currently supported by "
-                             "the toc data transformation.");
-
-  assert(PointerSize >= GV->getAlign().valueOrOne().value() &&
-         "GlobalVariables with an alignment requirement stricter then 4-bytes "
-         "not supported by the toc data transformation.");
+  assert(
+      PointerSize >= GV->getAlign().valueOrOne().value() &&
+      "GlobalVariables with an alignment requirement stricter than TOC entry "
+      "size not supported by the toc data transformation.");
 
   Type *GVType = GV->getValueType();
 
@@ -537,7 +535,7 @@ static bool hasTocDataAttr(SDValue Val, unsigned PointerSize) {
                        "supported by the toc data transformation.");
 
   assert(GVType->getPrimitiveSizeInBits() <= PointerSize * 8 &&
-         "A GlobalVariable with size larger than 32 bits is not currently "
+         "A GlobalVariable with size larger than a TOC entry is not currently "
          "supported by the toc data transformation.");
 
   if (GV->hasLocalLinkage() || GV->hasPrivateLinkage())
@@ -5791,41 +5789,57 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
     if (isAIXABI && CModel == CodeModel::Medium)
       report_fatal_error("Medium code model is not supported on AIX.");
 
-    // For 64-bit small code model, we allow SelectCodeCommon to handle this,
-    // selecting one of LDtoc, LDtocJTI, LDtocCPT, and LDtocBA.
-    if (isPPC64 && CModel == CodeModel::Small)
+    // For 64-bit ELF small code model, we allow SelectCodeCommon to handle
+    // this, selecting one of LDtoc, LDtocJTI, LDtocCPT, and LDtocBA. For AIX
+    // small code model, we need to check for a toc-data attribute.
+    if (isPPC64 && !isAIXABI && CModel == CodeModel::Small)
       break;
 
+    auto replaceWith = [this, &dl](unsigned OpCode, SDNode *TocEntry,
+                                   EVT OperandTy) {
+      SDValue GA = TocEntry->getOperand(0);
+      SDValue TocBase = TocEntry->getOperand(1);
+      SDNode *MN = CurDAG->getMachineNode(OpCode, dl, OperandTy, GA, TocBase);
+      transferMemOperands(TocEntry, MN);
+      ReplaceNode(TocEntry, MN);
+    };
+
     // Handle 32-bit small code model.
-    if (!isPPC64) {
+    if (!isPPC64 && CModel == CodeModel::Small) {
       // Transforms the ISD::TOC_ENTRY node to passed in Opcode, either
       // PPC::ADDItoc, or PPC::LWZtoc
-      auto replaceWith = [this, &dl](unsigned OpCode, SDNode *TocEntry) {
-        SDValue GA = TocEntry->getOperand(0);
-        SDValue TocBase = TocEntry->getOperand(1);
-        SDNode *MN = CurDAG->getMachineNode(OpCode, dl, MVT::i32, GA, TocBase);
-        transferMemOperands(TocEntry, MN);
-        ReplaceNode(TocEntry, MN);
-      };
-
       if (isELFABI) {
         assert(TM.isPositionIndependent() &&
                "32-bit ELF can only have TOC entries in position independent"
                " code.");
         // 32-bit ELF always uses a small code model toc access.
-        replaceWith(PPC::LWZtoc, N);
+        replaceWith(PPC::LWZtoc, N, MVT::i32);
         return;
       }
 
-      if (isAIXABI && CModel == CodeModel::Small) {
-        if (hasTocDataAttr(N->getOperand(0),
-                           CurDAG->getDataLayout().getPointerSize()))
-          replaceWith(PPC::ADDItoc, N);
-        else
-          replaceWith(PPC::LWZtoc, N);
+      assert(isAIXABI && "ELF ABI already handled");
+
+      if (hasTocDataAttr(N->getOperand(0),
+                         CurDAG->getDataLayout().getPointerSize())) {
+        replaceWith(PPC::ADDItoc, N, MVT::i32);
+        return;
+      }
 
+      replaceWith(PPC::LWZtoc, N, MVT::i32);
+      return;
+    }
+
+    if (isPPC64 && CModel == CodeModel::Small) {
+      assert(isAIXABI && "ELF ABI handled in common SelectCode");
+
+      if (hasTocDataAttr(N->getOperand(0),
+                         CurDAG->getDataLayout().getPointerSize())) {
+        replaceWith(PPC::ADDItoc8, N, MVT::i64);
         return;
       }
+      // Break if it doesn't have toc data attribute. Proceed with common
+      // SelectCode.
+      break;
     }
 
     assert(CModel != CodeModel::Small && "All small code models handled.");

diff  --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 417a6ce7e522d..58af8037f59c1 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -773,6 +773,11 @@ def ADDIS8 : DForm_2<15, (outs g8rc:$rD), (ins g8rc_nox0:$rA, s17imm64:$imm),
                      "addis $rD, $rA, $imm", IIC_IntSimple,
                      [(set i64:$rD, (add i64:$rA, imm16ShiftedSExt:$imm))]>;
 
+def LA8     : DForm_2<14, (outs g8rc:$rD), (ins g8rc_nox0:$rA, s16imm64:$sym),
+                     "la $rD, $sym($rA)", IIC_IntGeneral,
+                     [(set i64:$rD, (add i64:$rA,
+                                    (PPClo tglobaladdr:$sym, 0)))]>;
+
 let Defs = [CARRY] in {
 def SUBFIC8: DForm_2< 8, (outs g8rc:$rD), (ins g8rc:$rA, s16imm64:$imm),
                      "subfic $rD, $rA, $imm", IIC_IntGeneral,
@@ -1435,6 +1440,13 @@ def ADDIStocHA8: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentr
 def ADDItocL: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentry:$disp),
                      "#ADDItocL", []>, isPPC64;
 }
+
+// Local Data Transform
+def ADDItoc8 : PPCEmitTimePseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc_nox0:$reg),
+                   "#ADDItoc8",
+                   [(set i64:$rD,
+                     (PPCtoc_entry tglobaladdr:$disp, i64:$reg))]>, isPPC64;
+
 let mayLoad = 1 in
 def LDtocL: PPCEmitTimePseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc_nox0:$reg),
                    "#LDtocL", []>, isPPC64;

diff  --git a/llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll b/llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll
index adfdfc900ff6b..d5e7a0e0fe02c 100644
--- a/llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll
+++ b/llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll
@@ -1,7 +1,11 @@
 ; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s
 ; RUN: not --crash llc -filetype=obj -mtriple powerpc-ibm-aix-xcoff  \
 ; RUN:                 -verify-machineinstrs < %s 2>&1 | \
-; RUN:   FileCheck %s --check-prefix=OBJ
+; RUN:   FileCheck %s --check-prefix=OBJ32
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s
+; RUN: not --crash llc -filetype=obj -mtriple powerpc64-ibm-aix-xcoff  \
+; RUN:                 -verify-machineinstrs < %s 2>&1 | \
+; RUN:   FileCheck %s --check-prefix=OBJ64
 
 @i = external global i32, align 4  #0
 
@@ -15,6 +19,7 @@ define i32* @get() {
 ; CHECK:        .toc
 ; CHECK-NEXT:   .extern i[TD]
 
-; OBJ: LLVM ERROR:  toc-data not yet supported when writing object files.
+; OBJ32: LLVM ERROR:  toc-data not yet supported when writing object files.
+; OBJ64: LLVM ERROR:  64-bit XCOFF object files are not supported yet.
 
 attributes #0 = { "toc-data" }

diff  --git a/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll b/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
index 9f28b51496777..2f5d5bb5cdc9c 100644
--- a/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
+++ b/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
@@ -1,5 +1,7 @@
 ; RUN: not --crash llc  -mtriple powerpc-ibm-aix-xcoff  -verify-machineinstrs \
 ; RUN:     < %s 2>&1 | FileCheck %s
+; RUN: not --crash llc  -mtriple powerpc64-ibm-aix-xcoff  -verify-machineinstrs \
+; RUN:     < %s 2>&1 | FileCheck %s
 
 @ilocal = internal global i32 0, align 4 #0
 

diff  --git a/llvm/test/CodeGen/PowerPC/toc-data.ll b/llvm/test/CodeGen/PowerPC/toc-data.ll
index 7557d803db7c3..3f347fd222d8c 100644
--- a/llvm/test/CodeGen/PowerPC/toc-data.ll
+++ b/llvm/test/CodeGen/PowerPC/toc-data.ll
@@ -1,7 +1,10 @@
 ; REQUIRES: asserts
 ; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s \
-; RUN:     -stop-before=ppc-ctr-loops-verify | FileCheck %s
-; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST
+; RUN:     -stop-before=ppc-ctr-loops-verify | FileCheck %s --check-prefix CHECK32
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s \
+; RUN:     -stop-before=ppc-ctr-loops-verify | FileCheck %s --check-prefix CHECK64
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST32
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST64
 
 @i = dso_local global i32 0, align 4 #0
 @d = dso_local local_unnamed_addr global double 3.141590e+00, align 8
@@ -14,62 +17,128 @@ define dso_local void @write_int(i32 signext %in) {
     store i32 %in, i32* @i, align 4
     ret void
 }
-; CHECK: name:            write_int
-; CHECK:      %[[SCRATCH:[0-9]+]]:gprc_and_gprc_nor0 = ADDItoc @i, $r2
-; CHECK-NEXT: STW %{{[0-9]+}}, 0, killed %[[SCRATCH]] :: (store (s32) into @i)
+; CHECK32: name:            write_int
+; CHECK32:      %[[SCRATCH:[0-9]+]]:gprc_and_gprc_nor0 = ADDItoc @i, $r2
+; CHECK32-NEXT: STW %{{[0-9]+}}, 0, killed %[[SCRATCH]] :: (store (s32) into @i)
+
+; TEST32:         .write_int:
+; TEST32:           la 4, i[TD](2)
+; TEST32-NEXT:      stw 3, 0(4)
+
+; CHECK64: name:            write_int
+; CHECK64:      %[[SCRATCH:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItoc8 @i, $x2
+; CHECK64-NEXT: STW8 %{{[0-9]+}}, 0, killed %[[SCRATCH]] :: (store (s32) into @i)
+
+; TEST64:         .write_int:
+; TEST64:           la 4, i[TD](2)
+; TEST64-NEXT:      stw 3, 0(4)
 
-; TEST:         .write_int:
-; TEST:           la 4, i[TD](2)
-; TEST-NEXT:      stw 3, 0(4)
 
 define dso_local i64 @read_ll() {
   entry:
     %0 = load i64, i64* @ll, align 8
     ret i64 %0
 }
-; CHECK: name:            read_ll
-; CHECK: LWZtoc @ll, $r2 :: (load (s32) from got)
+; CHECK32: name:            read_ll
+; CHECK32: LWZtoc @ll, $r2 :: (load (s32) from got)
+
+; TEST32:       .read_ll:
+; TEST32:         lwz 4, L..C0(2)
+; TEST32-NEXT:    lwz 3, 0(4)
+; TEST32-NEXT:    lwz 4, 4(4)
+
+; CHECK64: name:            read_ll
+; CHECK64: LDtoc @ll, $x2 :: (load (s64) from got)
+
+; TEST64:       .read_ll:
+; TEST64:         ld 3, L..C0(2)
+; TEST64-NEXT:    ld 3, 0(3)
 
-; TEST:       .read_ll:
-; TEST:         lwz 4, L..C0(2)
-; TEST-NEXT:    lwz 3, 0(4)
-; TEST-NEXT:    lwz 4, 4(4)
 
 define dso_local float @read_float() {
   entry:
     %0 = load float, float* @f, align 4
     ret float %0
 }
-; CHECK: name:            read_float
-; CHECK: %[[SCRATCH:[0-9]+]]:gprc_and_gprc_nor0 = ADDItoc @f, $r2
-; CHECK: %{{[0-9]+}}:f4rc = LFS 0, killed %[[SCRATCH]] :: (dereferenceable load (s32) from @f)
+; CHECK32: name:            read_float
+; CHECK32: %[[SCRATCH:[0-9]+]]:gprc_and_gprc_nor0 = ADDItoc @f, $r2
+; CHECK32: %{{[0-9]+}}:f4rc = LFS 0, killed %[[SCRATCH]] :: (dereferenceable load (s32) from @f)
+
+; TEST32:       .read_float:
+; TEST32:         la 3, f[TD](2)
+; TEST32-NEXT:    lfs 1, 0(3)
+
+; CHECK64: name:            read_float
+; CHECK64: %[[SCRATCH:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItoc8 @f, $x2
+; CHECK64: %{{[0-9]+}}:f4rc = LFS 0, killed %[[SCRATCH]] :: (dereferenceable load (s32) from @f)
+
+; TEST64:       .read_float:
+; TEST64:         la 3, f[TD](2)
+; TEST64-NEXT:    lfs 1, 0(3)
 
-; TEST:       .read_float:
-; TEST:         la 3, f[TD](2)
-; TEST-NEXT:    lfs 1, 0(3)
 
 define dso_local void @write_double(double %in) {
   entry:
     store double %in, double* @d, align 8
     ret void
 }
-; CHECK: name:            write_double
-; CHECK: LWZtoc @d, $r2 :: (load (s32) from got)
+; CHECK32: name:            write_double
+; CHECK32: LWZtoc @d, $r2 :: (load (s32) from got)
+
+; TEST32:       .write_double
+; TEST32:         lwz 3, L..C1(2)
+; TEST32-NEXT:    stfd 1, 0(3)
+
+; CHECK64: name:            write_double
+; CHECK64: LDtoc @d, $x2 :: (load (s64) from got)
+
+; TEST64:       .write_double
+; TEST64:         ld 3, L..C1(2)
+; TEST64-NEXT:    stfd 1, 0(3)
 
-; TEST:       .write_double
-; TEST:         lwz 3, L..C1(2)
-; TEST-NEXT:    stfd 1, 0(3)
 
 define dso_local nonnull i32* @addr() {
   entry:
     ret i32* @i
 }
-; CHECK: name:            addr
-; CHECK:       %[[SCRATCH:[0-9]+]]:gprc = ADDItoc @i, $r2
-; CHECK-NEXT:  $r3 = COPY %[[SCRATCH]]
+; CHECK32: name:            addr
+; CHECK32:       %[[SCRATCH:[0-9]+]]:gprc = ADDItoc @i, $r2
+; CHECK32-NEXT:  $r3 = COPY %[[SCRATCH]]
+
+; TEST32:       .addr
+; TEST32:         la 3, i[TD](2)
+
+; CHECK64: name:            addr
+; CHECK64:       %[[SCRATCH:[0-9]+]]:g8rc = ADDItoc8 @i, $x2
+; CHECK64-NEXT:  $x3 = COPY %[[SCRATCH]]
+
+; TEST64:       .addr
+; TEST64:         la 3, i[TD](2)
 
-; TEST:       .addr
-; TEST:         la 3, i[TD](2)
+; TEST32:         .toc
+; TEST32:           .tc ll[TC],ll[RW]
+; TEST32-NOT:       .csect ll[TD]
+; TEST32:           .tc d[TC],d[RW]
+; TEST32-NOT:       .csect d[TD],2
+; TEST32:           .csect i[TD],2
+; TEST32-NEXT:      .globl  i[TD]
+; TEST32-NEXT:      .align  2
+; TEST32-NOT:       .tc i[TC],i[RW]
+; TEST32:           .csect f[TD],2
+; TEST32-NEXT:      .globl f[TD]
+; TEST32-NOT:       .tc f[TD],f[RW]
 
+; TEST64:         .toc
+; TEST64:           .tc ll[TC],ll[RW]
+; TEST64-NOT:       .csect ll[TD]
+; TEST64:           .tc d[TC],d[RW]
+; TEST64-NOT:       .csect d[TD],2
+; TEST64:           .csect i[TD],2
+; TEST64-NEXT:      .globl  i[TD]
+; TEST64-NEXT:      .align  2
+; TEST64-NOT:       .tc i[TC],i[RW]
+; TEST64:           .csect f[TD],2
+; TEST64-NEXT:      .globl f[TD]
+; TEST64-NOT:       .tc f[TD],f[RW]
 
 attributes #0 = { "toc-data" }


        


More information about the llvm-commits mailing list