Skip to content

Commit 3306996

Browse files
author
Zaara Syeda
committed
[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.
1 parent 4a5dffc commit 3306996

File tree

5 files changed

+96
-22
lines changed

5 files changed

+96
-22
lines changed

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,21 +1157,21 @@ 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.
1160+
// If the symbol does not have the toc-data attribute, then we create the
1161+
// TOC entry on AIX. If the toc-data attribute is used, the TOC entry
1162+
// contains the data rather than the address of the MOSymbol.
11611163
// Map the global address operand to be a reference to the TOC entry we
11621164
// will synthesize later. 'TOCEntry' is a label used to reference the
11631165
// 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.
11661166
if (![](const MachineOperand &MO) {
11671167
if (!MO.isGlobal())
11681168
return false;
11691169

1170-
const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal());
1171-
if (!GV)
1172-
return false;
1170+
if (const GlobalVariable *GV =
1171+
dyn_cast<GlobalVariable>(MO.getGlobal()))
1172+
return GV->hasAttribute("toc-data");
11731173

1174-
return GV->hasAttribute("toc-data");
1174+
return false;
11751175
}(MO)) {
11761176
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);
11771177
}
@@ -1301,8 +1301,9 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
13011301

13021302
unsigned Op = MI->getOpcode();
13031303

1304-
// Change the opcode to load address for tocdata
1305-
TmpInst.setOpcode(Op == PPC::ADDItocL8 ? PPC::ADDI8 : PPC::LA);
1304+
// Change the opcode to load address for toc data.
1305+
unsigned NewOp64 = IsAIX ? PPC::LA8 : PPC::ADDI8;
1306+
TmpInst.setOpcode(Op == PPC::ADDItocL8 ? NewOp64 : 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: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6143,10 +6143,10 @@ 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.
6146+
// 64-bit medium (ELF-only), or large (ELF and AIX) code model code that
6147+
// does not contain TOC data symbols.
61486148
// We generate two instructions as described below. The first source
6149-
// operand is a symbol reference. If it must be referenced via the toc
6149+
// operand is a symbol reference. If it must be referenced via the TOC
61506150
// according to Subtarget, we generate:
61516151
// [32-bit AIX]
61526152
// LWZtocL(@sym, ADDIStocHA(%r2, @sym))
@@ -6159,7 +6159,7 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
61596159
// [32-bit AIX]
61606160
// ADDItocL(ADDIStocHA(%x2, @sym), @sym)
61616161
// [64-bit AIX]
6162-
// Currently not supported.
6162+
// ADDItocL8(ADDIStocHA8(%x2, @sym), @sym)
61636163

61646164
SDValue GA = N->getOperand(0);
61656165
SDValue TOCbase = N->getOperand(1);
@@ -6171,12 +6171,9 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
61716171
// On AIX, if the symbol has the toc-data attribute it will be defined
61726172
// in the TOC entry, so we use an ADDItocL/ADDItocL8.
61736173
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));
6174+
ReplaceNode(
6175+
N, CurDAG->getMachineNode(isPPC64 ? PPC::ADDItocL8 : PPC::ADDItocL,
6176+
dl, VT, SDValue(Tmp, 0), GA));
61806177
return;
61816178
}
61826179

@@ -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)