[clang] [llvm] [PowerPC][AIX] 64-bit large code-model support for toc-data (PR #90619)
Zaara Syeda via llvm-commits
llvm-commits at lists.llvm.org
Mon May 13 14:39:58 PDT 2024
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 <syzaara at 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 at u(2)
+; TEST64LARGE-NEXT: ld 3, L..C0 at 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 at 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 at u(2)
+; TEST64LARGE-NEXT: ld 3, L..C1 at 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 <syzaara at 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);
}
More information about the llvm-commits
mailing list