Skip to content

Commit 194e7cc

Browse files
authored
[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.
1 parent 2805e6f commit 194e7cc

File tree

8 files changed

+104
-44
lines changed

8 files changed

+104
-44
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -599,9 +599,6 @@ def warn_drv_unsupported_gpopt : Warning<
599599
"ignoring '-mgpopt' option as it cannot be used with %select{|the implicit"
600600
" usage of }0-mabicalls">,
601601
InGroup<UnsupportedGPOpt>;
602-
def warn_drv_unsupported_tocdata: Warning<
603-
"ignoring '-mtocdata' as it is only supported for -mcmodel=small">,
604-
InGroup<OptionIgnored>;
605602
def warn_drv_unsupported_sdata : Warning<
606603
"ignoring '-msmall-data-limit=' with -mcmodel=large for -fpic or RV64">,
607604
InGroup<OptionIgnored>;

clang/lib/Driver/ToolChains/AIX.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -479,14 +479,6 @@ static void addTocDataOptions(const llvm::opt::ArgList &Args,
479479
return false;
480480
}();
481481

482-
// Currently only supported for small code model.
483-
if (TOCDataGloballyinEffect &&
484-
(Args.getLastArgValue(options::OPT_mcmodel_EQ) == "large" ||
485-
Args.getLastArgValue(options::OPT_mcmodel_EQ) == "medium")) {
486-
D.Diag(clang::diag::warn_drv_unsupported_tocdata);
487-
return;
488-
}
489-
490482
enum TOCDataSetting {
491483
AddressInTOC = 0, // Address of the symbol stored in the TOC.
492484
DataInTOC = 1 // Symbol defined in the TOC.

clang/test/Driver/tocdata-cc1.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
// RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \
2-
// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s
2+
// RUN: | FileCheck %s
33
// RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \
4-
// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s
4+
// RUN: | FileCheck %s
55
// RUN: %clang -### --target=powerpc-ibm-aix-xcoff -mtocdata %s 2>&1 \
6-
// RUN: | FileCheck -check-prefix=CHECK-TOC %s
6+
// RUN: | FileCheck %s
77
// RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=medium -mtocdata %s 2>&1 \
8-
// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s
8+
// RUN: | FileCheck %s
99
// RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mcmodel=large -mtocdata %s 2>&1 \
10-
// RUN: | FileCheck -check-prefix=CHECK-NOTOC %s
10+
// RUN: | FileCheck %s
1111
// RUN: %clang -### --target=powerpc64-ibm-aix-xcoff -mtocdata %s 2>&1 \
12-
// RUN: | FileCheck -check-prefix=CHECK-TOC %s
13-
// CHECK-NOTOC: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small
14-
// CHECK-NOTOC-NOT: "-cc1"{{.*}}" "-mtocdata"
15-
// CHECK-TOC: "-cc1"{{.*}}" "-mtocdata"
16-
// CHECK-TOC-NOT: warning: ignoring '-mtocdata' as it is only supported for -mcmodel=small
12+
// RUN: | FileCheck %s
13+
// CHECK: "-cc1"{{.*}}" "-mtocdata"

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,20 +1157,19 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
11571157

11581158
MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO);
11591159

1160-
// If the symbol isn't toc-data then use the TOC on AIX.
11611160
// Map the global address operand to be a reference to the TOC entry we
11621161
// will synthesize later. 'TOCEntry' is a label used to reference the
11631162
// storage allocated in the TOC which contains the address of 'MOSymbol'.
1164-
// If the toc-data attribute is used, the TOC entry contains the data
1165-
// rather than the address of the MOSymbol.
1163+
// If the symbol does not have the toc-data attribute, then we create the
1164+
// TOC entry on AIX. If the toc-data attribute is used, the TOC entry
1165+
// contains the data rather than the address of the MOSymbol.
11661166
if (![](const MachineOperand &MO) {
11671167
if (!MO.isGlobal())
11681168
return false;
11691169

11701170
const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal());
11711171
if (!GV)
11721172
return false;
1173-
11741173
return GV->hasAttribute("toc-data");
11751174
}(MO)) {
11761175
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);
@@ -1301,8 +1300,10 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
13011300

13021301
unsigned Op = MI->getOpcode();
13031302

1304-
// Change the opcode to load address for tocdata
1305-
TmpInst.setOpcode(Op == PPC::ADDItocL8 ? PPC::ADDI8 : PPC::LA);
1303+
// Change the opcode to load address for toc-data.
1304+
// ADDItocL is only used for 32-bit toc-data on AIX and will always use LA.
1305+
TmpInst.setOpcode(Op == PPC::ADDItocL8 ? (IsAIX ? PPC::LA8 : PPC::ADDI8)
1306+
: PPC::LA);
13061307

13071308
const MachineOperand &MO = MI->getOperand(2);
13081309
assert((Op == PPC::ADDItocL8)
@@ -1316,8 +1317,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
13161317

13171318
const MCExpr *Exp = MCSymbolRefExpr::create(
13181319
MOSymbol,
1319-
Op == PPC::ADDItocL8 ? MCSymbolRefExpr::VK_PPC_TOC_LO
1320-
: MCSymbolRefExpr::VK_PPC_L,
1320+
IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO,
13211321
OutContext);
13221322

13231323
TmpInst.getOperand(2) = MCOperand::createExpr(Exp);

llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6143,23 +6143,22 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
61436143
" ELF/AIX or 32-bit AIX in the following.");
61446144

61456145
// Transforms the ISD::TOC_ENTRY node for 32-bit AIX large code model mode,
6146-
// or 64-bit medium (ELF-only), or large (ELF and AIX) code model code that
6147-
// does not conain TOC data symbols.
6148-
// We generate two instructions as described below. The first source
6149-
// operand is a symbol reference. If it must be referenced via the toc
6150-
// according to Subtarget, we generate:
6146+
// 64-bit medium (ELF-only), or 64-bit large (ELF and AIX) code model code
6147+
// that does not contain TOC data symbols. We generate two instructions as
6148+
// described below. The first source operand is a symbol reference. If it
6149+
// must be referenced via the TOC according to Subtarget, we generate:
61516150
// [32-bit AIX]
61526151
// LWZtocL(@sym, ADDIStocHA(%r2, @sym))
61536152
// [64-bit ELF/AIX]
61546153
// LDtocL(@sym, ADDIStocHA8(%x2, @sym))
6155-
// Otherwise we generate:
6154+
// Otherwise for medium code model ELF we generate:
61566155
// ADDItocL8(ADDIStocHA8(%x2, @sym), @sym)
61576156

6158-
// For large code model with TOC data symbols we generate:
6157+
// And finally for AIX with toc-data we generate:
61596158
// [32-bit AIX]
61606159
// ADDItocL(ADDIStocHA(%x2, @sym), @sym)
61616160
// [64-bit AIX]
6162-
// Currently not supported.
6161+
// ADDItocL8(ADDIStocHA8(%x2, @sym), @sym)
61636162

61646163
SDValue GA = N->getOperand(0);
61656164
SDValue TOCbase = N->getOperand(1);
@@ -6171,12 +6170,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
61716170
// On AIX, if the symbol has the toc-data attribute it will be defined
61726171
// in the TOC entry, so we use an ADDItocL/ADDItocL8.
61736172
if (isAIXABI && hasTocDataAttr(GA)) {
6174-
if (isPPC64)
6175-
report_fatal_error(
6176-
"64-bit large code model toc-data not yet supported");
6177-
6178-
ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL, dl, VT,
6179-
SDValue(Tmp, 0), GA));
6173+
ReplaceNode(
6174+
N, CurDAG->getMachineNode(isPPC64 ? PPC::ADDItocL8 : PPC::ADDItocL,
6175+
dl, VT, SDValue(Tmp, 0), GA));
61806176
return;
61816177
}
61826178

@@ -6191,6 +6187,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
61916187
return;
61926188
}
61936189

6190+
assert(isPPC64 && "TOC_ENTRY already handled for 32-bit.");
61946191
// Build the address relative to the TOC-pointer.
61956192
ReplaceNode(N, CurDAG->getMachineNode(PPC::ADDItocL8, dl, MVT::i64,
61966193
SDValue(Tmp, 0), GA));
@@ -7777,6 +7774,10 @@ void PPCDAGToDAGISel::PeepholePPC64() {
77777774
Flags = PPCII::MO_TLSLD_LO;
77787775
break;
77797776
case PPC::ADDItocL8:
7777+
// Skip the following peephole optimizations for ADDItocL8 on AIX which
7778+
// is used for toc-data access.
7779+
if (Subtarget->isAIXABI())
7780+
continue;
77807781
Flags = PPCII::MO_TOC_LO;
77817782
break;
77827783
}

llvm/lib/Target/PowerPC/PPCInstrInfo.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4438,6 +4438,12 @@ bool PPCInstrInfo::isDefMIElgibleForForwarding(MachineInstr &DefMI,
44384438
if (Opc != PPC::ADDItocL8 && Opc != PPC::ADDI && Opc != PPC::ADDI8)
44394439
return false;
44404440

4441+
// Skip the optimization of transformTo[NewImm|Imm]FormFedByAdd for ADDItocL8
4442+
// on AIX which is used for toc-data access. TODO: Follow up to see if it can
4443+
// apply for AIX toc-data as well.
4444+
if (Opc == PPC::ADDItocL8 && Subtarget.isAIX())
4445+
return false;
4446+
44414447
assert(DefMI.getNumOperands() >= 3 &&
44424448
"Add inst must have at least three operands");
44434449
RegMO = &DefMI.getOperand(1);

llvm/lib/Target/PowerPC/PPCInstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3346,7 +3346,7 @@ def ADDIStocHA : PPCEmitTimePseudo<(outs gprc:$rD), (ins gprc_nor0:$reg, tocentr
33463346
"#ADDIStocHA",
33473347
[(set i32:$rD,
33483348
(PPCtoc_entry i32:$reg, tglobaladdr:$disp))]>;
3349-
// TOC Data Transform AIX
3349+
// TOC Data Transform on AIX
33503350
def ADDItoc : PPCEmitTimePseudo<(outs gprc:$rD), (ins tocentry32:$disp, gprc:$reg),
33513351
"#ADDItoc",
33523352
[(set i32:$rD,

llvm/test/CodeGen/PowerPC/toc-data.ll

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
; RUN: -stop-before=ppc-vsx-copy | FileCheck %s --check-prefix CHECK32LARGE
1717
; RUN: llc -mtriple powerpc-ibm-aix-xcoff -code-model=large -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST32LARGE
1818

19+
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=large -verify-machineinstrs < %s \
20+
; RUN: -stop-before=ppc-vsx-copy | FileCheck %s --check-prefix CHECK64LARGE
21+
; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -code-model=large -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST64LARGE
22+
1923
; Global variables i and f have the toc-data attribute.
2024
; In the following functions, those writing to or reading from
2125
; variables i and f should use the toc-data access pattern.
@@ -63,6 +67,17 @@ define dso_local void @write_int(i32 signext %in) {
6367
; TEST32LARGE-NEXT: la 4, i[TD]@l(4)
6468
; TEST32LARGE-NEXT: stw 3, 0(4)
6569

70+
71+
; CHECK64LARGE: name: write_int
72+
; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @i
73+
; CHECK64LARGE-NEXT: %[[SCRATCH2:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItocL8 killed %[[SCRATCH1]], @i
74+
; CHECK64LARGE-NEXT: STW8 %{{[0-9]+}}, 0, killed %[[SCRATCH2]] :: (store (s32) into @i)
75+
76+
; TEST64LARGE: .write_int:
77+
; TEST64LARGE: addis 4, i[TD]@u(2)
78+
; TEST64LARGE-NEXT: la 4, i[TD]@l(4)
79+
; TEST64LARGE-NEXT: stw 3, 0(4)
80+
6681
define dso_local i64 @read_ll() {
6782
entry:
6883
%0 = load i64, ptr @ll, align 8
@@ -98,6 +113,15 @@ define dso_local i64 @read_ll() {
98113
; TEST32LARGE-NEXT: lwz 3, 0(4)
99114
; TEST32LARGE-NEXT: lwz 4, 4(4)
100115

116+
; CHECK64LARGE: name: read_ll
117+
; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @ll
118+
; CHECK64LARGE: LDtocL @ll, killed %[[SCRATCH1]] :: (load (s64) from got)
119+
120+
; TEST64LARGE: .read_ll:
121+
; TEST64LARGE: addis 3, L..C0@u(2)
122+
; TEST64LARGE-NEXT: ld 3, L..C0@l(3)
123+
; TEST64LARGE-NEXT: ld 3, 0(3)
124+
101125
define dso_local float @read_float() {
102126
entry:
103127
%0 = load float, ptr @f, align 4
@@ -134,6 +158,18 @@ define dso_local float @read_float() {
134158
; TEST32LARGE-NEXT: la 3, f[TD]@l(3)
135159
; TEST32LARGE-NEXT: lfs 1, 0(3)
136160

161+
162+
; CHECK64LARGE: name: read_float
163+
; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @f
164+
; CHECK64LARGE-NEXT: %[[SCRATCH2:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItocL8 killed %[[SCRATCH1]], @f
165+
; CHECK64LARGE-NEXT: LFS 0, killed %[[SCRATCH2]] :: (dereferenceable load (s32) from @f)
166+
167+
168+
; TEST64LARGE: .read_float:
169+
; TEST64LARGE: addis 3, f[TD]@u(2)
170+
; TEST64LARGE-NEXT: la 3, f[TD]@l(3)
171+
; TEST64LARGE-NEXT: lfs 1, 0(3)
172+
137173
define dso_local void @write_double(double %in) {
138174
entry:
139175
store double %in, ptr @d, align 8
@@ -167,6 +203,15 @@ define dso_local void @write_double(double %in) {
167203
; TEST32LARGE-NEXT: lwz 3, L..C1@l(3)
168204
; TEST32LARGE-NEXT: stfd 1, 0(3)
169205

206+
; CHECK64LARGE: name: write_double
207+
; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @d
208+
; CHECK64LARGE: LDtocL @d, killed %[[SCRATCH1]] :: (load (s64) from got)
209+
210+
; TEST64LARGE: .write_double:
211+
; TEST64LARGE: addis 3, L..C1@u(2)
212+
; TEST64LARGE-NEXT: ld 3, L..C1@l(3)
213+
; TEST64LARGE-NEXT: stfd 1, 0(3)
214+
170215
define dso_local nonnull ptr @addr() {
171216
entry:
172217
ret ptr @i
@@ -237,4 +282,26 @@ define dso_local nonnull ptr @addr() {
237282
; TEST32LARGE-NEXT: .globl f[TD]
238283
; TEST32LARGE-NOT: .tc f[TE],f[RW]
239284

285+
; CHECK64LARGE: name: addr
286+
; CHECK64LARGE: %[[SCRATCH1:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDIStocHA8 $x2, @i
287+
; CHECK64LARGE-NEXT: %[[SCRATCH2:[0-9]+]]:g8rc = ADDItocL8 killed %[[SCRATCH1]], @i
288+
; CHECK64LARGE-NEXT: $x3 = COPY %[[SCRATCH2]]
289+
290+
; TEST64LARGE: .addr:
291+
; TEST64LARGE: addis 3, i[TD]@u(2)
292+
; TEST64LARGE: la 3, i[TD]@l(3)
293+
294+
; TEST64LARGE: .toc
295+
; TEST64LARGE: .tc ll[TE],ll[RW]
296+
; TEST64LARGE-NOT: .csect ll[TD]
297+
; TEST64LARGE: .tc d[TE],d[RW]
298+
; TEST64LARGE-NOT: .csect d[TD],2
299+
; TEST64LARGE: .csect i[TD],2
300+
; TEST64LARGE-NEXT: .globl i[TD]
301+
; TEST64LARGE-NEXT: .align 2
302+
; TEST64LARGE-NOT: .tc i[TE],i[RW]
303+
; TEST64LARGE: .csect f[TD],2
304+
; TEST64LARGE-NEXT: .globl f[TD]
305+
; TEST64LARGE-NOT: .tc f[TE],f[RW]
306+
240307
attributes #0 = { "toc-data" }

0 commit comments

Comments
 (0)