diff options
author | Zarko Todorovski <64787215+ZarkoT@users.noreply.github.com> | 2024-06-05 12:19:16 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-05 12:19:16 -0400 |
commit | 0295c2ada4d9964a2b6289c905e320bd42461f99 (patch) | |
tree | d654166ec7505e193b218cad7f5ed107ba8f5cb6 /llvm/lib/Target/PowerPC | |
parent | 6150e84cfc87d118f8cd2794e40dd021c8779e9d (diff) | |
download | llvm-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.cpp | 48 |
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, |