[llvm] 415e821 - [PowerPC][AIX] Add toc-data support for 64-bit AIX small code model.
Sean Fertile via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 1 07:57:55 PST 2021
Author: Yousuf Ali
Date: 2021-12-01T10:56:21-05:00
New Revision: 415e821a5089d7b2a49cc8e1717702f46ffdae86
URL: https://github.com/llvm/llvm-project/commit/415e821a5089d7b2a49cc8e1717702f46ffdae86
DIFF: https://github.com/llvm/llvm-project/commit/415e821a5089d7b2a49cc8e1717702f46ffdae86.diff
LOG: [PowerPC][AIX] Add toc-data support for 64-bit AIX small code model.
The patch expands the existing 32-bit toc-data attribute support to 64-bit.
In both 32-bit and 64-bit it is supported for small code model only.
Differential Revision: https://reviews.llvm.org/D114654
Added:
Modified:
llvm/lib/Target/PowerPC/P10InstrResources.td
llvm/lib/Target/PowerPC/P9InstrResources.td
llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
llvm/lib/Target/PowerPC/PPCInstr64Bit.td
llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll
llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
llvm/test/CodeGen/PowerPC/toc-data.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/PowerPC/P10InstrResources.td b/llvm/lib/Target/PowerPC/P10InstrResources.td
index 5906564810864..f3ae0010ad8ef 100644
--- a/llvm/lib/Target/PowerPC/P10InstrResources.td
+++ b/llvm/lib/Target/PowerPC/P10InstrResources.td
@@ -1976,7 +1976,7 @@ def : InstRW<[P10W_SX, P10W_DISP_ANY],
ICBLQ,
ICBTLS,
ICCCI,
- LA,
+ LA, LA8,
LDMX,
MFDCR,
MFPMR,
@@ -2075,3 +2075,4 @@ def : InstRW<[P10W_vMU_7C, P10W_DISP_ANY, P10vMU_Read, P10vMU_Read, P10vMU_Read]
VMSUMUHM,
VMSUMUHS
)>;
+
diff --git a/llvm/lib/Target/PowerPC/P9InstrResources.td b/llvm/lib/Target/PowerPC/P9InstrResources.td
index 070a662179da7..f7c049951c54b 100644
--- a/llvm/lib/Target/PowerPC/P9InstrResources.td
+++ b/llvm/lib/Target/PowerPC/P9InstrResources.td
@@ -151,6 +151,7 @@ def : InstRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C],
(instregex "ADD(4|8)(TLS)?(_)?$"),
(instregex "NEG(8)?(O)?$"),
(instregex "ADDI(S)?toc(HA|L)(8)?$"),
+ (instregex "LA(8)?$"),
COPY,
MCRF,
MCRXRX,
@@ -165,7 +166,6 @@ def : InstRW<[P9_ALU_2C, IP_EXEC_1C, DISP_1C],
SRADI_32,
RLDIC,
RFEBB,
- LA,
TBEGIN,
TRECHKPT,
NOP,
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index a76963abb8e45..16e3b2b85c2e0 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -875,18 +875,19 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
EmitToStreamer(*OutStreamer, TmpInst);
return;
}
- case PPC::ADDItoc: {
+ case PPC::ADDItoc:
+ case PPC::ADDItoc8: {
assert(IsAIX && TM.getCodeModel() == CodeModel::Small &&
- "Operand only valid in AIX 32 bit mode");
+ "PseudoOp only valid for small code model AIX");
- // Transform %rN = ADDItoc @op1, %r2.
+ // Transform %rN = ADDItoc/8 @op1, %r2.
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this);
// Change the opcode to load address.
- TmpInst.setOpcode(PPC::LA);
+ TmpInst.setOpcode((!IsPPC64) ? (PPC::LA) : (PPC::LA8));
const MachineOperand &MO = MI->getOperand(1);
- assert(MO.isGlobal() && "Invalid operand for ADDItoc.");
+ assert(MO.isGlobal() && "Invalid operand for ADDItoc[8].");
// Map the operand to its corresponding MCSymbol.
const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 247faa8b46a84..a2664bcff4ab0 100644
--- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -510,14 +510,12 @@ static bool hasTocDataAttr(SDValue Val, unsigned PointerSize) {
return false;
// TODO: These asserts should be updated as more support for the toc data
- // transformation is added (64 bit, struct support, etc.).
+ // transformation is added (struct support, etc.).
- assert(PointerSize == 4 && "Only 32 Bit Codegen is currently supported by "
- "the toc data transformation.");
-
- assert(PointerSize >= GV->getAlign().valueOrOne().value() &&
- "GlobalVariables with an alignment requirement stricter then 4-bytes "
- "not supported by the toc data transformation.");
+ assert(
+ PointerSize >= GV->getAlign().valueOrOne().value() &&
+ "GlobalVariables with an alignment requirement stricter than TOC entry "
+ "size not supported by the toc data transformation.");
Type *GVType = GV->getValueType();
@@ -537,7 +535,7 @@ static bool hasTocDataAttr(SDValue Val, unsigned PointerSize) {
"supported by the toc data transformation.");
assert(GVType->getPrimitiveSizeInBits() <= PointerSize * 8 &&
- "A GlobalVariable with size larger than 32 bits is not currently "
+ "A GlobalVariable with size larger than a TOC entry is not currently "
"supported by the toc data transformation.");
if (GV->hasLocalLinkage() || GV->hasPrivateLinkage())
@@ -5791,41 +5789,57 @@ void PPCDAGToDAGISel::Select(SDNode *N) {
if (isAIXABI && CModel == CodeModel::Medium)
report_fatal_error("Medium code model is not supported on AIX.");
- // For 64-bit small code model, we allow SelectCodeCommon to handle this,
- // selecting one of LDtoc, LDtocJTI, LDtocCPT, and LDtocBA.
- if (isPPC64 && CModel == CodeModel::Small)
+ // For 64-bit ELF small code model, we allow SelectCodeCommon to handle
+ // this, selecting one of LDtoc, LDtocJTI, LDtocCPT, and LDtocBA. For AIX
+ // small code model, we need to check for a toc-data attribute.
+ if (isPPC64 && !isAIXABI && CModel == CodeModel::Small)
break;
+ auto replaceWith = [this, &dl](unsigned OpCode, SDNode *TocEntry,
+ EVT OperandTy) {
+ SDValue GA = TocEntry->getOperand(0);
+ SDValue TocBase = TocEntry->getOperand(1);
+ SDNode *MN = CurDAG->getMachineNode(OpCode, dl, OperandTy, GA, TocBase);
+ transferMemOperands(TocEntry, MN);
+ ReplaceNode(TocEntry, MN);
+ };
+
// Handle 32-bit small code model.
- if (!isPPC64) {
+ if (!isPPC64 && CModel == CodeModel::Small) {
// Transforms the ISD::TOC_ENTRY node to passed in Opcode, either
// PPC::ADDItoc, or PPC::LWZtoc
- auto replaceWith = [this, &dl](unsigned OpCode, SDNode *TocEntry) {
- SDValue GA = TocEntry->getOperand(0);
- SDValue TocBase = TocEntry->getOperand(1);
- SDNode *MN = CurDAG->getMachineNode(OpCode, dl, MVT::i32, GA, TocBase);
- transferMemOperands(TocEntry, MN);
- ReplaceNode(TocEntry, MN);
- };
-
if (isELFABI) {
assert(TM.isPositionIndependent() &&
"32-bit ELF can only have TOC entries in position independent"
" code.");
// 32-bit ELF always uses a small code model toc access.
- replaceWith(PPC::LWZtoc, N);
+ replaceWith(PPC::LWZtoc, N, MVT::i32);
return;
}
- if (isAIXABI && CModel == CodeModel::Small) {
- if (hasTocDataAttr(N->getOperand(0),
- CurDAG->getDataLayout().getPointerSize()))
- replaceWith(PPC::ADDItoc, N);
- else
- replaceWith(PPC::LWZtoc, N);
+ assert(isAIXABI && "ELF ABI already handled");
+
+ if (hasTocDataAttr(N->getOperand(0),
+ CurDAG->getDataLayout().getPointerSize())) {
+ replaceWith(PPC::ADDItoc, N, MVT::i32);
+ return;
+ }
+ replaceWith(PPC::LWZtoc, N, MVT::i32);
+ return;
+ }
+
+ if (isPPC64 && CModel == CodeModel::Small) {
+ assert(isAIXABI && "ELF ABI handled in common SelectCode");
+
+ if (hasTocDataAttr(N->getOperand(0),
+ CurDAG->getDataLayout().getPointerSize())) {
+ replaceWith(PPC::ADDItoc8, N, MVT::i64);
return;
}
+ // Break if it doesn't have toc data attribute. Proceed with common
+ // SelectCode.
+ break;
}
assert(CModel != CodeModel::Small && "All small code models handled.");
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 417a6ce7e522d..58af8037f59c1 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -773,6 +773,11 @@ def ADDIS8 : DForm_2<15, (outs g8rc:$rD), (ins g8rc_nox0:$rA, s17imm64:$imm),
"addis $rD, $rA, $imm", IIC_IntSimple,
[(set i64:$rD, (add i64:$rA, imm16ShiftedSExt:$imm))]>;
+def LA8 : DForm_2<14, (outs g8rc:$rD), (ins g8rc_nox0:$rA, s16imm64:$sym),
+ "la $rD, $sym($rA)", IIC_IntGeneral,
+ [(set i64:$rD, (add i64:$rA,
+ (PPClo tglobaladdr:$sym, 0)))]>;
+
let Defs = [CARRY] in {
def SUBFIC8: DForm_2< 8, (outs g8rc:$rD), (ins g8rc:$rA, s16imm64:$imm),
"subfic $rD, $rA, $imm", IIC_IntGeneral,
@@ -1435,6 +1440,13 @@ def ADDIStocHA8: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentr
def ADDItocL: PPCEmitTimePseudo<(outs g8rc:$rD), (ins g8rc_nox0:$reg, tocentry:$disp),
"#ADDItocL", []>, isPPC64;
}
+
+// Local Data Transform
+def ADDItoc8 : PPCEmitTimePseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc_nox0:$reg),
+ "#ADDItoc8",
+ [(set i64:$rD,
+ (PPCtoc_entry tglobaladdr:$disp, i64:$reg))]>, isPPC64;
+
let mayLoad = 1 in
def LDtocL: PPCEmitTimePseudo<(outs g8rc:$rD), (ins tocentry:$disp, g8rc_nox0:$reg),
"#LDtocL", []>, isPPC64;
diff --git a/llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll b/llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll
index adfdfc900ff6b..d5e7a0e0fe02c 100644
--- a/llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll
+++ b/llvm/test/CodeGen/PowerPC/basic-toc-data-extern.ll
@@ -1,7 +1,11 @@
; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s
; RUN: not --crash llc -filetype=obj -mtriple powerpc-ibm-aix-xcoff \
; RUN: -verify-machineinstrs < %s 2>&1 | \
-; RUN: FileCheck %s --check-prefix=OBJ
+; RUN: FileCheck %s --check-prefix=OBJ32
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s
+; RUN: not --crash llc -filetype=obj -mtriple powerpc64-ibm-aix-xcoff \
+; RUN: -verify-machineinstrs < %s 2>&1 | \
+; RUN: FileCheck %s --check-prefix=OBJ64
@i = external global i32, align 4 #0
@@ -15,6 +19,7 @@ define i32* @get() {
; CHECK: .toc
; CHECK-NEXT: .extern i[TD]
-; OBJ: LLVM ERROR: toc-data not yet supported when writing object files.
+; OBJ32: LLVM ERROR: toc-data not yet supported when writing object files.
+; OBJ64: LLVM ERROR: 64-bit XCOFF object files are not supported yet.
attributes #0 = { "toc-data" }
diff --git a/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll b/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
index 9f28b51496777..2f5d5bb5cdc9c 100644
--- a/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
+++ b/llvm/test/CodeGen/PowerPC/basic-toc-data-local-linkage.ll
@@ -1,5 +1,7 @@
; RUN: not --crash llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs \
; RUN: < %s 2>&1 | FileCheck %s
+; RUN: not --crash llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs \
+; RUN: < %s 2>&1 | FileCheck %s
@ilocal = internal global i32 0, align 4 #0
diff --git a/llvm/test/CodeGen/PowerPC/toc-data.ll b/llvm/test/CodeGen/PowerPC/toc-data.ll
index 7557d803db7c3..3f347fd222d8c 100644
--- a/llvm/test/CodeGen/PowerPC/toc-data.ll
+++ b/llvm/test/CodeGen/PowerPC/toc-data.ll
@@ -1,7 +1,10 @@
; REQUIRES: asserts
; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s \
-; RUN: -stop-before=ppc-ctr-loops-verify | FileCheck %s
-; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST
+; RUN: -stop-before=ppc-ctr-loops-verify | FileCheck %s --check-prefix CHECK32
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s \
+; RUN: -stop-before=ppc-ctr-loops-verify | FileCheck %s --check-prefix CHECK64
+; RUN: llc -mtriple powerpc-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST32
+; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -verify-machineinstrs < %s | FileCheck %s --check-prefix TEST64
@i = dso_local global i32 0, align 4 #0
@d = dso_local local_unnamed_addr global double 3.141590e+00, align 8
@@ -14,62 +17,128 @@ define dso_local void @write_int(i32 signext %in) {
store i32 %in, i32* @i, align 4
ret void
}
-; CHECK: name: write_int
-; CHECK: %[[SCRATCH:[0-9]+]]:gprc_and_gprc_nor0 = ADDItoc @i, $r2
-; CHECK-NEXT: STW %{{[0-9]+}}, 0, killed %[[SCRATCH]] :: (store (s32) into @i)
+; CHECK32: name: write_int
+; CHECK32: %[[SCRATCH:[0-9]+]]:gprc_and_gprc_nor0 = ADDItoc @i, $r2
+; CHECK32-NEXT: STW %{{[0-9]+}}, 0, killed %[[SCRATCH]] :: (store (s32) into @i)
+
+; TEST32: .write_int:
+; TEST32: la 4, i[TD](2)
+; TEST32-NEXT: stw 3, 0(4)
+
+; CHECK64: name: write_int
+; CHECK64: %[[SCRATCH:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItoc8 @i, $x2
+; CHECK64-NEXT: STW8 %{{[0-9]+}}, 0, killed %[[SCRATCH]] :: (store (s32) into @i)
+
+; TEST64: .write_int:
+; TEST64: la 4, i[TD](2)
+; TEST64-NEXT: stw 3, 0(4)
-; TEST: .write_int:
-; TEST: la 4, i[TD](2)
-; TEST-NEXT: stw 3, 0(4)
define dso_local i64 @read_ll() {
entry:
%0 = load i64, i64* @ll, align 8
ret i64 %0
}
-; CHECK: name: read_ll
-; CHECK: LWZtoc @ll, $r2 :: (load (s32) from got)
+; CHECK32: name: read_ll
+; CHECK32: LWZtoc @ll, $r2 :: (load (s32) from got)
+
+; TEST32: .read_ll:
+; TEST32: lwz 4, L..C0(2)
+; TEST32-NEXT: lwz 3, 0(4)
+; TEST32-NEXT: lwz 4, 4(4)
+
+; CHECK64: name: read_ll
+; CHECK64: LDtoc @ll, $x2 :: (load (s64) from got)
+
+; TEST64: .read_ll:
+; TEST64: ld 3, L..C0(2)
+; TEST64-NEXT: ld 3, 0(3)
-; TEST: .read_ll:
-; TEST: lwz 4, L..C0(2)
-; TEST-NEXT: lwz 3, 0(4)
-; TEST-NEXT: lwz 4, 4(4)
define dso_local float @read_float() {
entry:
%0 = load float, float* @f, align 4
ret float %0
}
-; CHECK: name: read_float
-; CHECK: %[[SCRATCH:[0-9]+]]:gprc_and_gprc_nor0 = ADDItoc @f, $r2
-; CHECK: %{{[0-9]+}}:f4rc = LFS 0, killed %[[SCRATCH]] :: (dereferenceable load (s32) from @f)
+; CHECK32: name: read_float
+; CHECK32: %[[SCRATCH:[0-9]+]]:gprc_and_gprc_nor0 = ADDItoc @f, $r2
+; CHECK32: %{{[0-9]+}}:f4rc = LFS 0, killed %[[SCRATCH]] :: (dereferenceable load (s32) from @f)
+
+; TEST32: .read_float:
+; TEST32: la 3, f[TD](2)
+; TEST32-NEXT: lfs 1, 0(3)
+
+; CHECK64: name: read_float
+; CHECK64: %[[SCRATCH:[0-9]+]]:g8rc_and_g8rc_nox0 = ADDItoc8 @f, $x2
+; CHECK64: %{{[0-9]+}}:f4rc = LFS 0, killed %[[SCRATCH]] :: (dereferenceable load (s32) from @f)
+
+; TEST64: .read_float:
+; TEST64: la 3, f[TD](2)
+; TEST64-NEXT: lfs 1, 0(3)
-; TEST: .read_float:
-; TEST: la 3, f[TD](2)
-; TEST-NEXT: lfs 1, 0(3)
define dso_local void @write_double(double %in) {
entry:
store double %in, double* @d, align 8
ret void
}
-; CHECK: name: write_double
-; CHECK: LWZtoc @d, $r2 :: (load (s32) from got)
+; CHECK32: name: write_double
+; CHECK32: LWZtoc @d, $r2 :: (load (s32) from got)
+
+; TEST32: .write_double
+; TEST32: lwz 3, L..C1(2)
+; TEST32-NEXT: stfd 1, 0(3)
+
+; CHECK64: name: write_double
+; CHECK64: LDtoc @d, $x2 :: (load (s64) from got)
+
+; TEST64: .write_double
+; TEST64: ld 3, L..C1(2)
+; TEST64-NEXT: stfd 1, 0(3)
-; TEST: .write_double
-; TEST: lwz 3, L..C1(2)
-; TEST-NEXT: stfd 1, 0(3)
define dso_local nonnull i32* @addr() {
entry:
ret i32* @i
}
-; CHECK: name: addr
-; CHECK: %[[SCRATCH:[0-9]+]]:gprc = ADDItoc @i, $r2
-; CHECK-NEXT: $r3 = COPY %[[SCRATCH]]
+; CHECK32: name: addr
+; CHECK32: %[[SCRATCH:[0-9]+]]:gprc = ADDItoc @i, $r2
+; CHECK32-NEXT: $r3 = COPY %[[SCRATCH]]
+
+; TEST32: .addr
+; TEST32: la 3, i[TD](2)
+
+; CHECK64: name: addr
+; CHECK64: %[[SCRATCH:[0-9]+]]:g8rc = ADDItoc8 @i, $x2
+; CHECK64-NEXT: $x3 = COPY %[[SCRATCH]]
+
+; TEST64: .addr
+; TEST64: la 3, i[TD](2)
-; TEST: .addr
-; TEST: la 3, i[TD](2)
+; TEST32: .toc
+; TEST32: .tc ll[TC],ll[RW]
+; TEST32-NOT: .csect ll[TD]
+; TEST32: .tc d[TC],d[RW]
+; TEST32-NOT: .csect d[TD],2
+; TEST32: .csect i[TD],2
+; TEST32-NEXT: .globl i[TD]
+; TEST32-NEXT: .align 2
+; TEST32-NOT: .tc i[TC],i[RW]
+; TEST32: .csect f[TD],2
+; TEST32-NEXT: .globl f[TD]
+; TEST32-NOT: .tc f[TD],f[RW]
+; TEST64: .toc
+; TEST64: .tc ll[TC],ll[RW]
+; TEST64-NOT: .csect ll[TD]
+; TEST64: .tc d[TC],d[RW]
+; TEST64-NOT: .csect d[TD],2
+; TEST64: .csect i[TD],2
+; TEST64-NEXT: .globl i[TD]
+; TEST64-NEXT: .align 2
+; TEST64-NOT: .tc i[TC],i[RW]
+; TEST64: .csect f[TD],2
+; TEST64-NEXT: .globl f[TD]
+; TEST64-NOT: .tc f[TD],f[RW]
attributes #0 = { "toc-data" }
More information about the llvm-commits
mailing list