aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/PowerPC
diff options
context:
space:
mode:
authorZarko Todorovski <64787215+ZarkoT@users.noreply.github.com>2024-06-05 12:19:16 -0400
committerGitHub <noreply@github.com>2024-06-05 12:19:16 -0400
commit0295c2ada4d9964a2b6289c905e320bd42461f99 (patch)
treed654166ec7505e193b218cad7f5ed107ba8f5cb6 /llvm/lib/Target/PowerPC
parent6150e84cfc87d118f8cd2794e40dd021c8779e9d (diff)
downloadllvm-0295c2ada4d9964a2b6289c905e320bd42461f99.zip
llvm-0295c2ada4d9964a2b6289c905e320bd42461f99.tar.gz
llvm-0295c2ada4d9964a2b6289c905e320bd42461f99.tar.bz2
[PowerPC][AIX] Support ByVals with greater alignment then pointer size (#93341)
Implementation is NOT compatible with IBM XL C 16.1 and earlier but is compatible with GCC. It handles all ByVals with greater alignment then pointer width the same way IBM XL C handles Byvals that have vector members. For overaligned objects that do not contain vectors IBM XL C does not align them properly if they are passed in the GPR argument registers. This patch was originally written by Sean Fertile @mandlebug. Previously on Phabricator https://reviews.llvm.org/D105659
Diffstat (limited to 'llvm/lib/Target/PowerPC')
-rw-r--r--llvm/lib/Target/PowerPC/PPCISelLowering.cpp48
1 files changed, 30 insertions, 18 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index a0e91f4..12e33dd 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -6855,7 +6855,9 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
const PPCSubtarget &Subtarget = static_cast<const PPCSubtarget &>(
State.getMachineFunction().getSubtarget());
const bool IsPPC64 = Subtarget.isPPC64();
- const Align PtrAlign = IsPPC64 ? Align(8) : Align(4);
+ const unsigned PtrSize = IsPPC64 ? 8 : 4;
+ const Align PtrAlign(PtrSize);
+ const Align StackAlign(16);
const MVT RegVT = IsPPC64 ? MVT::i64 : MVT::i32;
if (ValVT == MVT::f128)
@@ -6876,12 +6878,16 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
PPC::V6, PPC::V7, PPC::V8, PPC::V9,
PPC::V10, PPC::V11, PPC::V12, PPC::V13};
+ const ArrayRef<MCPhysReg> GPRs = IsPPC64 ? GPR_64 : GPR_32;
+
if (ArgFlags.isByVal()) {
- if (ArgFlags.getNonZeroByValAlign() > PtrAlign)
+ const Align ByValAlign(ArgFlags.getNonZeroByValAlign());
+ if (ByValAlign > StackAlign)
report_fatal_error("Pass-by-value arguments with alignment greater than "
- "register width are not supported.");
+ "16 are not supported.");
const unsigned ByValSize = ArgFlags.getByValSize();
+ const Align ObjAlign = ByValAlign > PtrAlign ? ByValAlign : PtrAlign;
// An empty aggregate parameter takes up no storage and no registers,
// but needs a MemLoc for a stack slot for the formal arguments side.
@@ -6891,11 +6897,23 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
return false;
}
- const unsigned StackSize = alignTo(ByValSize, PtrAlign);
- unsigned Offset = State.AllocateStack(StackSize, PtrAlign);
- for (const unsigned E = Offset + StackSize; Offset < E;
- Offset += PtrAlign.value()) {
- if (unsigned Reg = State.AllocateReg(IsPPC64 ? GPR_64 : GPR_32))
+ // Shadow allocate any registers that are not properly aligned.
+ unsigned NextReg = State.getFirstUnallocated(GPRs);
+ while (NextReg != GPRs.size() &&
+ !isGPRShadowAligned(GPRs[NextReg], ObjAlign)) {
+ // Shadow allocate next registers since its aligment is not strict enough.
+ unsigned Reg = State.AllocateReg(GPRs);
+ // Allocate the stack space shadowed by said register.
+ State.AllocateStack(PtrSize, PtrAlign);
+ assert(Reg && "Alocating register unexpectedly failed.");
+ (void)Reg;
+ NextReg = State.getFirstUnallocated(GPRs);
+ }
+
+ const unsigned StackSize = alignTo(ByValSize, ObjAlign);
+ unsigned Offset = State.AllocateStack(StackSize, ObjAlign);
+ for (const unsigned E = Offset + StackSize; Offset < E; Offset += PtrSize) {
+ if (unsigned Reg = State.AllocateReg(GPRs))
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, RegVT, LocInfo));
else {
State.addLoc(CCValAssign::getMem(ValNo, MVT::INVALID_SIMPLE_VALUE_TYPE,
@@ -6917,12 +6935,12 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
[[fallthrough]];
case MVT::i1:
case MVT::i32: {
- const unsigned Offset = State.AllocateStack(PtrAlign.value(), PtrAlign);
+ const unsigned Offset = State.AllocateStack(PtrSize, PtrAlign);
// AIX integer arguments are always passed in register width.
if (ValVT.getFixedSizeInBits() < RegVT.getFixedSizeInBits())
LocInfo = ArgFlags.isSExt() ? CCValAssign::LocInfo::SExt
: CCValAssign::LocInfo::ZExt;
- if (unsigned Reg = State.AllocateReg(IsPPC64 ? GPR_64 : GPR_32))
+ if (unsigned Reg = State.AllocateReg(GPRs))
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, RegVT, LocInfo));
else
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, RegVT, LocInfo));
@@ -6942,8 +6960,8 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
State.addLoc(CCValAssign::getReg(ValNo, ValVT, FReg, LocVT, LocInfo));
// Reserve and initialize GPRs or initialize the PSA as required.
- for (unsigned I = 0; I < StoreSize; I += PtrAlign.value()) {
- if (unsigned Reg = State.AllocateReg(IsPPC64 ? GPR_64 : GPR_32)) {
+ for (unsigned I = 0; I < StoreSize; I += PtrSize) {
+ if (unsigned Reg = State.AllocateReg(GPRs)) {
assert(FReg && "An FPR should be available when a GPR is reserved.");
if (State.isVarArg()) {
// Successfully reserved GPRs are only initialized for vararg calls.
@@ -6995,9 +7013,6 @@ static bool CC_AIX(unsigned ValNo, MVT ValVT, MVT LocVT,
return false;
}
- const unsigned PtrSize = IsPPC64 ? 8 : 4;
- ArrayRef<MCPhysReg> GPRs = IsPPC64 ? GPR_64 : GPR_32;
-
unsigned NextRegIndex = State.getFirstUnallocated(GPRs);
// Burn any underaligned registers and their shadowed stack space until
// we reach the required alignment.
@@ -7347,9 +7362,6 @@ SDValue PPCTargetLowering::LowerFormalArguments_AIX(
const MCPhysReg ArgReg = VA.getLocReg();
const PPCFrameLowering *FL = Subtarget.getFrameLowering();
- if (Flags.getNonZeroByValAlign() > PtrByteSize)
- report_fatal_error("Over aligned byvals not supported yet.");
-
const unsigned StackSize = alignTo(Flags.getByValSize(), PtrByteSize);
const int FI = MF.getFrameInfo().CreateFixedObject(
StackSize, mapArgRegToOffsetAIX(ArgReg, FL), /* IsImmutable */ false,