diff options
author | Zaara Syeda <syzaara@ca.ibm.com> | 2024-05-21 14:00:24 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-21 14:00:24 -0400 |
commit | 194e7cc7aabe2ffb153ca66527ffb6b500fa4c50 (patch) | |
tree | 91d2d62b0316fd62cd75bf70d01044363eb39dd8 | |
parent | 2805e6faad7795ed0846010e3e7ad41460030758 (diff) | |
download | llvm-194e7cc7aabe2ffb153ca66527ffb6b500fa4c50.zip llvm-194e7cc7aabe2ffb153ca66527ffb6b500fa4c50.tar.gz llvm-194e7cc7aabe2ffb153ca66527ffb6b500fa4c50.tar.bz2 |
[PowerPC][AIX] 64-bit large code-model support for toc-data (#90619)
This patch adds support for toc-data for 64-bit large code-model on AIX.
The sequence ADDIStocHA8/ADDItocL8 is used to access the data directly
from the TOC.
When emitting the instruction ADDIStocHA8, we check if the symbol has
toc-data attribute before creating a toc entry for it. When emitting the
instruction ADDItocL8, we use the LA8 instruction to load the address.
-rw-r--r-- | clang/include/clang/Basic/DiagnosticDriverKinds.td | 3 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/AIX.cpp | 8 | ||||
-rw-r--r-- | clang/test/Driver/tocdata-cc1.c | 17 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrInfo.td | 2 | ||||
-rw-r--r-- | llvm/test/CodeGen/PowerPC/toc-data.ll | 67 |
8 files changed, 104 insertions, 44 deletions
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 9d97a75..50d3b42 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -599,9 +599,6 @@ def warn_drv_unsupported_gpopt : Warning< "ignoring '-mgpopt' option as it cannot be used with %select{|the implicit" " usage of }0-mabicalls">, InGroup<UnsupportedGPOpt>; -def warn_drv_unsupported_tocdata: Warning< - "ignoring '-mtocdata' as it is only supported for -mcmodel=small">, - InGroup<OptionIgnored>; def warn_drv_unsupported_sdata : Warning< "ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64">, InGroup<OptionIgnored>; diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp index 85825e1..381d72e 100644 --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -479,14 +479,6 @@ static void addTocDataOptions(const llvm::opt::ArgList &Args, return false; }(); - // Currently only supported for small code model. - if (TOCDataGloballyinEffect && - (Args.getLastArgValue(options::OPT_mcmodel_EQ) == "large" || - Args.getLastArgValue(options::OPT_mcmodel_EQ) == "medium")) { - D.Diag(clang::diag::warn_drv_unsupported_tocdata); - return; - } - enum TOCDataSetting { AddressInTOC = 0, // Address of the symbol stored in the TOC. DataInTOC = 1 // Symbol defined in the TOC. diff --git a/clang/test/Driver/tocdata-cc1.c b/clang/test/Driver/tocdata-cc1.c index fe0d97e..e00383d 100644 --- a/clang/test/Driver/tocdata-cc1.c +++ b/clang/test/Driver/tocdata-cc1.c @@ -1,16 +1,13 @@ // RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-TOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck %s // RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-TOC %s -// CHECK-NOTOC: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small -// CHECK-NOTOC-NOT: "-cc1"{{.*}}" "-mtocdata" -// CHECK-TOC: "-cc1"{{.*}}" "-mtocdata" -// CHECK-TOC-NOT: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small +// RUN: | FileCheck %s +// CHECK: "-cc1"{{.*}}" "-mtocdata" diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index ac48dc5..72e8215 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1157,12 +1157,12 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO); - // If the symbol isn't toc-data then use the TOC on AIX. // Map the global address operand to be a reference to the TOC entry we // will synthesize later. 'TOCEntry' is a label used to reference the // storage allocated in the TOC which contains the address of 'MOSymbol'. - // If the toc-data attribute is used, the TOC entry contains the data - // rather than the address of the MOSymbol. + // If the symbol does not have the toc-data attribute, then we create the + // TOC entry on AIX. If the toc-data attribute is used, the TOC entry + // contains the data rather than the address of the MOSymbol. if (![](const MachineOperand &MO) { if (!MO.isGlobal()) return false; @@ -1170,7 +1170,6 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal()); if (!GV) return false; - return GV->hasAttribute("toc-data"); }(MO)) { MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); @@ -1301,8 +1300,10 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { unsigned Op = MI->getOpcode(); - // Change the opcode to load address for tocdata - TmpInst.setOpcode(Op == PPC::ADDItocL8 ? PPC::ADDI8 : PPC::LA); + // Change the opcode to load address for toc-data. + // ADDItocL is only used for 32-bit toc-data on AIX and will always use LA. + TmpInst.setOpcode(Op == PPC::ADDItocL8 ? (IsAIX ? PPC::LA8 : PPC::ADDI8) + : PPC::LA); const MachineOperand &MO = MI->getOperand(2); assert((Op == PPC::ADDItocL8) @@ -1316,8 +1317,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { const MCExpr *Exp = MCSymbolRefExpr::create( MOSymbol, - Op == PPC::ADDItocL8 ? MCSymbolRefExpr::VK_PPC_TOC_LO - : MCSymbolRefExpr::VK_PPC_L, + IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext); TmpInst.getOperand(2) = MCOperand::createExpr(Exp); diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 6862155..26560dc 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -6143,23 +6143,22 @@ void PPCDAGToDAGISel::Select(SDNode *N) { " ELF/AIX or 32-bit AIX in the following."); // Transforms the ISD::TOC_ENTRY node for 32-bit AIX large code model mode, - // or 64-bit medium (ELF-only), or large (ELF and AIX) code model code that - // does not conain TOC data symbols. - // We generate two instructions as described below. The first source - // operand is a symbol reference. If it must be referenced via the toc - // according to Subtarget, we generate: + // 64-bit medium (ELF-only), or 64-bit large (ELF and AIX) code model code + // that does not contain TOC data symbols. We generate two instructions as + // described below. The first source operand is a symbol reference. If it + // must be referenced via the TOC according to Subtarget, we generate: // [32-bit AIX] // LWZtocL(@sym, ADDIStocHA(%r2, @sym)) // [64-bit ELF/AIX] // LDtocL(@sym, ADDIStocHA8(%x2, @sym)) - // Otherwise we generate: + // Otherwise for medium code model ELF we generate: // ADDItocL8(ADDIStocHA8(%x2, @sym), @sym) - // For large code model with TOC data symbols we generate: + // And finally for AIX with toc-data we generate: // [32-bit AIX] // ADDItocL(ADDIStocHA(%x2, @sym), @sym) // [64-bit AIX] - // Currently not supported. + // ADDItocL8(ADDIStocHA8(%x2, @sym), @sym) SDValue GA = N->getOperand(0); SDValue TOCbase = N->getOperand(1); @@ -6171,12 +6170,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) { // On AIX, if the symbol has the toc-data attribute it will be defined // in the TOC entry, so we use an ADDItocL/ADDItocL8. if (isAIXABI && hasTocDataAttr(GA)) { - if (isPPC64) - report_fatal_error( - "64-bit large code model toc-data not yet supported"); - - ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL, dl, VT, - SDValue(Tmp, 0), GA)); + ReplaceNode( + N, CurDAG->getMachineNode(isPPC64 ? PPC::ADDItocL8 : PPC::ADDItocL, + dl, VT, SDValue(Tmp, 0), GA)); return; } @@ -6191,6 +6187,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) { return; } + assert(isPPC64 && "TOC_ENTRY already handled for 32-bit."); // Build the address relative to the TOC-pointer. ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL8, dl, MVT::i64, SDValue(Tmp, 0), GA)); @@ -7777,6 +7774,10 @@ void PPCDAGToDAGISel::PeepholePPC64() { Flags = PPCII::MO_TLSLD_LO; break; case PPC::ADDItocL8: + // Skip the following peephole optimizations for ADDItocL8 on AIX which + // is used for toc-data access. + if (Subtarget->isAIXABI()) + continue; Flags = PPCII::MO_TOC_LO; break; } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 9e56de7..85bbfab 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -4438,6 +4438,12 @@ bool PPCInstrInfo::isDefMIElgibleForForwarding(MachineInstr &DefMI, if (Opc != PPC::ADDItocL8 && Opc != PPC::ADDI && Opc != PPC::ADDI8) return false; + // Skip the optimization of transformTo[NewImm|Imm]FormFedByAdd for ADDItocL8 + // on AIX which is used for toc-data access. TODO: Follow up to see if it can + // apply for AIX toc-data as well. + if (Opc == PPC::ADDItocL8 && Subtarget.isAIX()) + return false; + assert(DefMI.getNumOperands() >= 3 && "Add inst must have at least three operands"); RegMO = &DefMI.getOperand(1); diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 7929a78..e3d6d2f 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -3346,7 +3346,7 @@ def ADDIStocHA : PPCEmitTimePseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, tocentr "#ADDIStocHA", [(set i32:$rD, (PPCtoc_entry i32:$reg, tglobaladdr:$disp))]>; -// TOC Data Transform AIX +// TOC Data Transform on AIX def ADDItoc : PPCEmitTimePseudo<(outs gprc:$rD), (ins tocentry32:$disp, gprc:$reg), "#ADDItoc", [(set i32:$rD, diff --git a/llvm/test/CodeGen/PowerPC/toc-data.ll b/llvm/test/CodeGen/PowerPC/toc-data.ll index 7f7afe7..1a10780 100644 --- a/llvm/test/CodeGen/PowerPC/toc-data.ll +++ b/llvm/test/CodeGen/PowerPC/toc-data.ll @@ -16,6 +16,10 @@ ; RUN: -stop-before=ppc-vsx-copy | FileCheck %s --check-prefix CHECK32LARGE ; RUN: llc -mtriple powerpc-ibm-aix-xcoff -code-model=large -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST32LARGE +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=large -verify-machineinstrs < %s \ +; RUN: -stop-before=ppc-vsx-copy | FileCheck %s --check-prefix CHECK64LARGE +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=large -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST64LARGE + ; Global variables i and f have the toc-data attribute. ; In the following functions, those writing to or reading from ; variables i and f should use the toc-data access pattern. @@ -63,6 +67,17 @@ define dso_local void @write_int(i32 signext %in) { ; TEST32LARGE-NEXT: la 4, i[TD]@l(4) ; TEST32LARGE-NEXT: stw 3, 0(4) + +; CHECK64LARGE: name: write_int +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @i +; CHECK64LARGE-NEXT: %[[SCRATCH2:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItocL8 killed %[[SCRATCH1]], @i +; CHECK64LARGE-NEXT: STW8 %{{[0-9]+}}, 0, killed %[[SCRATCH2]] :: (store (s32) into @i) + +; TEST64LARGE: .write_int: +; TEST64LARGE: addis 4, i[TD]@u(2) +; TEST64LARGE-NEXT: la 4, i[TD]@l(4) +; TEST64LARGE-NEXT: stw 3, 0(4) + define dso_local i64 @read_ll() { entry: %0 = load i64, ptr @ll, align 8 @@ -98,6 +113,15 @@ define dso_local i64 @read_ll() { ; TEST32LARGE-NEXT: lwz 3, 0(4) ; TEST32LARGE-NEXT: lwz 4, 4(4) +; CHECK64LARGE: name: read_ll +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @ll +; CHECK64LARGE: LDtocL @ll, killed %[[SCRATCH1]] :: (load (s64) from got) + +; TEST64LARGE: .read_ll: +; TEST64LARGE: addis 3, L..C0@u(2) +; TEST64LARGE-NEXT: ld 3, L..C0@l(3) +; TEST64LARGE-NEXT: ld 3, 0(3) + define dso_local float @read_float() { entry: %0 = load float, ptr @f, align 4 @@ -134,6 +158,18 @@ define dso_local float @read_float() { ; TEST32LARGE-NEXT: la 3, f[TD]@l(3) ; TEST32LARGE-NEXT: lfs 1, 0(3) + +; CHECK64LARGE: name: read_float +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @f +; CHECK64LARGE-NEXT: %[[SCRATCH2:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItocL8 killed %[[SCRATCH1]], @f +; CHECK64LARGE-NEXT: LFS 0, killed %[[SCRATCH2]] :: (dereferenceable load (s32) from @f) + + +; TEST64LARGE: .read_float: +; TEST64LARGE: addis 3, f[TD]@u(2) +; TEST64LARGE-NEXT: la 3, f[TD]@l(3) +; TEST64LARGE-NEXT: lfs 1, 0(3) + define dso_local void @write_double(double %in) { entry: store double %in, ptr @d, align 8 @@ -167,6 +203,15 @@ define dso_local void @write_double(double %in) { ; TEST32LARGE-NEXT: lwz 3, L..C1@l(3) ; TEST32LARGE-NEXT: stfd 1, 0(3) +; CHECK64LARGE: name: write_double +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @d +; CHECK64LARGE: LDtocL @d, killed %[[SCRATCH1]] :: (load (s64) from got) + +; TEST64LARGE: .write_double: +; TEST64LARGE: addis 3, L..C1@u(2) +; TEST64LARGE-NEXT: ld 3, L..C1@l(3) +; TEST64LARGE-NEXT: stfd 1, 0(3) + define dso_local nonnull ptr @addr() { entry: ret ptr @i @@ -237,4 +282,26 @@ define dso_local nonnull ptr @addr() { ; TEST32LARGE-NEXT: .globl f[TD] ; TEST32LARGE-NOT: .tc f[TE],f[RW] +; CHECK64LARGE: name: addr +; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @i +; CHECK64LARGE-NEXT: %[[SCRATCH2:[0-9]+]]:g8rc = ADDItocL8 killed %[[SCRATCH1]], @i +; CHECK64LARGE-NEXT: $x3 = COPY %[[SCRATCH2]] + +; TEST64LARGE: .addr: +; TEST64LARGE: addis 3, i[TD]@u(2) +; TEST64LARGE: la 3, i[TD]@l(3) + +; TEST64LARGE: .toc +; TEST64LARGE: .tc ll[TE],ll[RW] +; TEST64LARGE-NOT: .csect ll[TD] +; TEST64LARGE: .tc d[TE],d[RW] +; TEST64LARGE-NOT: .csect d[TD],2 +; TEST64LARGE: .csect i[TD],2 +; TEST64LARGE-NEXT: .globl i[TD] +; TEST64LARGE-NEXT: .align 2 +; TEST64LARGE-NOT: .tc i[TE],i[RW] +; TEST64LARGE: .csect f[TD],2 +; TEST64LARGE-NEXT: .globl f[TD] +; TEST64LARGE-NOT: .tc f[TE],f[RW] + attributes #0 = { "toc-data" } |