Skip to content

[PowerPC][AIX] 64-bit large code-model support for toc-data #90619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
8 changes: 0 additions & 8 deletions clang/lib/Driver/ToolChains/AIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Contributor

@diggerlin diggerlin May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do the patch also support "medium" ? but in the description of the patch , it is "64-bit large code-model" , and do you want to add medium test case?

Copy link
Collaborator

@chenzheng1030 chenzheng1030 May 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AIX does not have medium model. when specifying it, it will be mapped to large.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, according to https://reviews.llvm.org/D106371, medium will be large.

return;
}

enum TOCDataSetting {
AddressInTOC = 0, // Address of the symbol stored in the TOC.
DataInTOC = 1 // Symbol defined in the TOC.
Expand Down
17 changes: 7 additions & 10 deletions clang/test/Driver/tocdata-cc1.c
Original file line number Diff line number Diff line change
@@ -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"
16 changes: 8 additions & 8 deletions llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1157,20 +1157,19 @@ 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;

const GlobalVariable *GV = dyn_cast<GlobalVariable>(MO.getGlobal());
if (!GV)
return false;

return GV->hasAttribute("toc-data");
}(MO)) {
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down
29 changes: 15 additions & 14 deletions llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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));
Copy link
Collaborator

@chenzheng1030 chenzheng1030 May 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I suggest to add an assert like assert(isPPC64 && ...) before line 6188 which assumes 32-bit linux/aix are already handled, so it uses ADDItocL8 directly.

return;
}

Expand All @@ -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));
Expand Down Expand Up @@ -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())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curiously , why skip the peephole for the ADDItocL8 in AIX?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a follow on patch for adding this peephole optimization: #76488 since earlier patches related to this were reverted as the code needed some refactoring.
See: https://reviews.llvm.org/D101470 and https://reviews.llvm.org/D155957

continue;
Flags = PPCII::MO_TOC_LO;
break;
}
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/PowerPC/PPCInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
67 changes: 67 additions & 0 deletions llvm/test/CodeGen/PowerPC/toc-data.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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" }
Loading