https://github.com/syzaara updated https://github.com/llvm/llvm-project/pull/90619
>From 70a6bc5bb5d5d43a3e87b7cc597682d6647166fc Mon Sep 17 00:00:00 2001 From: Zaara Syeda <syza...@cpap8104.rtp.raleigh.ibm.com> Date: Tue, 30 Apr 2024 10:22:26 -0400 Subject: [PATCH 1/2] [PowerPC] 64-bit large code-model support for toc-data This patch adds support for toc-data for 64-bit large code-model. 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. --- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 22 +++---- llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 33 +++++----- llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 6 ++ llvm/lib/Target/PowerPC/PPCInstrInfo.td | 2 +- llvm/test/CodeGen/PowerPC/toc-data.ll | 67 +++++++++++++++++++++ 5 files changed, 101 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 51b79dc2b04b4..14dc4d1249a88 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1148,21 +1148,21 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO); - // If the symbol isn't toc-data then use the TOC on AIX. + // 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. // 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 (![](const MachineOperand &MO) { if (!MO.isGlobal()) return false; - const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal()); - if (!GV) - return false; + if (const GlobalVariable *GV = + dyn_cast<GlobalVariable>(MO.getGlobal())) + return GV->hasAttribute("toc-data"); - return GV->hasAttribute("toc-data"); + return false; }(MO)) { MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); } @@ -1292,8 +1292,9 @@ 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. + unsigned NewOp64 = IsAIX ? PPC::LA8 : PPC::ADDI8; + TmpInst.setOpcode(Op == PPC::ADDItocL8 ? NewOp64 : PPC::LA); const MachineOperand &MO = MI->getOperand(2); assert((Op == PPC::ADDItocL8) @@ -1307,8 +1308,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 2f647daa4bcb5..c9b3cb58ca583 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -6141,24 +6141,23 @@ void PPCDAGToDAGISel::Select(SDNode *N) { assert((isPPC64 || (isAIXABI && !isPPC64)) && "We are dealing with 64-bit" " 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 non - // toc-data symbols. + // Transforms the ISD::TOC_ENTRY node for 32-bit AIX large code model mode, + // 64-bit medium (ELF-only), or 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 toc-referenced according to - // Subtarget, we generate: + // 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: // ADDItocL8(ADDIStocHA8(%x2, @sym), @sym) - - // For large code model toc-data symbols we generate: + // For large code model with TOC data symbols 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); @@ -6167,16 +6166,12 @@ void PPCDAGToDAGISel::Select(SDNode *N) { SDNode *Tmp = CurDAG->getMachineNode( isPPC64 ? PPC::ADDIStocHA8 : PPC::ADDIStocHA, dl, VT, TOCbase, GA); - // On AIX if the symbol has the toc-data attribute it will be defined - // in the TOC entry, so we use an ADDItocL similar to the medium code - // model ELF abi. + // 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; } @@ -7780,6 +7775,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 9e56de732c587..85bbfabf5d3c9 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 7929a781dbda8..e3d6d2f094f2e 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 7f7afe76cfcde..1a10780954529 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" } >From 0decd752d2aec1f09354e27d9a0dfe568a1e2d3d Mon Sep 17 00:00:00 2001 From: Zaara Syeda <syza...@cpap8104.rtp.raleigh.ibm.com> Date: Mon, 13 May 2024 17:39:22 -0400 Subject: [PATCH 2/2] Address review comments and remove mcmodel warning for mtocdata --- .../include/clang/Basic/DiagnosticDriverKinds.td | 3 --- clang/lib/Driver/ToolChains/AIX.cpp | 8 -------- clang/test/Driver/tocdata-cc1.c | 11 ++++------- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 15 +++++++-------- 4 files changed, 11 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index ed3fd9b1c4a55..eb054a13d077d 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -596,9 +596,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 aab98506adb96..381d72e045b95 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).equals("large") || - Args.getLastArgValue(options::OPT_mcmodel_EQ).equals("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 fe0d97ea02db1..0d56623916860 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 -check-prefix=CHECK-TOC %s // RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck -check-prefix=CHECK-TOC %s // RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mtocdata %s 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-TOC %s // RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck -check-prefix=CHECK-TOC %s // RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \ -// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s +// RUN: | FileCheck -check-prefix=CHECK-TOC %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 diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 14dc4d1249a88..0b5aa04198a20 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1148,21 +1148,20 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO); - // 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. // 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 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; - if (const GlobalVariable *GV = - dyn_cast<GlobalVariable>(MO.getGlobal())) - return GV->hasAttribute("toc-data"); - - return false; + const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal()); + if (!GV) + return false; + return GV->hasAttribute("toc-data"); }(MO)) { MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits