From 0498939936926e2f2aa9bedd0257ad4e4eca8e4a Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 19 Jun 2024 18:07:23 +0200 Subject: [PATCH] JIT: Store one segment inline in ABIPassingInformation (#103690) By far the most common case on all platforms is that an argument takes up one segment to describe its passing behavior, so we can avoid additional allocations by storing one segment inline. --- src/coreclr/jit/abi.cpp | 110 ++++++++++++++++++++++---- src/coreclr/jit/abi.h | 24 ++++-- src/coreclr/jit/codegenarmarch.cpp | 2 +- src/coreclr/jit/codegencommon.cpp | 14 ++-- src/coreclr/jit/codegenxarch.cpp | 2 +- src/coreclr/jit/lclvars.cpp | 20 ++--- src/coreclr/jit/lsrabuild.cpp | 2 +- src/coreclr/jit/morph.cpp | 4 +- src/coreclr/jit/targetamd64.cpp | 5 +- src/coreclr/jit/targetarm.cpp | 20 ++--- src/coreclr/jit/targetarm64.cpp | 24 +++--- src/coreclr/jit/targetloongarch64.cpp | 15 ++-- src/coreclr/jit/targetriscv64.cpp | 7 +- 13 files changed, 169 insertions(+), 80 deletions(-) diff --git a/src/coreclr/jit/abi.cpp b/src/coreclr/jit/abi.cpp index 4ef6f034dd0f87..b60142a8569530 100644 --- a/src/coreclr/jit/abi.cpp +++ b/src/coreclr/jit/abi.cpp @@ -187,6 +187,65 @@ ABIPassingSegment ABIPassingSegment::OnStack(unsigned stackOffset, unsigned offs return segment; } +//----------------------------------------------------------------------------- +// ABIPassingInformation: +// Construct an instance with the specified number of segments allocated in +// the backing storage. +// +// Parameters: +// comp - Compiler instance +// numSegments - Number of segments +// +// Remarks: +// The segments are expected to be filled out by the caller after the +// allocation; they are not zeroed out by the allocation. +// +ABIPassingInformation::ABIPassingInformation(Compiler* comp, unsigned numSegments) +{ + NumSegments = numSegments; + + if (numSegments > 1) + { + Segments = new (comp, CMK_ABI) ABIPassingSegment[numSegments]; + } +} + +//----------------------------------------------------------------------------- +// Segment: +// Access a segment by the specified index. +// +// Parameters: +// index - The index of the segment +// +// Returns: +// Reference to segment. +// +const ABIPassingSegment& ABIPassingInformation::Segment(unsigned index) const +{ + assert(index < NumSegments); + if (NumSegments == 1) + { + return SingleSegment; + } + + return Segments[index]; +} + +//----------------------------------------------------------------------------- +// Segment: +// Access a segment by the specified index. +// +// Parameters: +// index - The index of the segment +// +// Returns: +// Reference to segment. +// +ABIPassingSegment& ABIPassingInformation::Segment(unsigned index) +{ + return const_cast(static_cast(*this).Segment(index)); +} + //----------------------------------------------------------------------------- // HasAnyRegisterSegment: // Check if any part of this value is passed in a register. @@ -198,7 +257,7 @@ bool ABIPassingInformation::HasAnyRegisterSegment() const { for (unsigned i = 0; i < NumSegments; i++) { - if (Segments[i].IsPassedInRegister()) + if (Segment(i).IsPassedInRegister()) { return true; } @@ -217,7 +276,7 @@ bool ABIPassingInformation::HasAnyStackSegment() const { for (unsigned i = 0; i < NumSegments; i++) { - if (Segments[i].IsPassedOnStack()) + if (Segment(i).IsPassedOnStack()) { return true; } @@ -234,7 +293,7 @@ bool ABIPassingInformation::HasAnyStackSegment() const // bool ABIPassingInformation::HasExactlyOneRegisterSegment() const { - return (NumSegments == 1) && Segments[0].IsPassedInRegister(); + return (NumSegments == 1) && Segment(0).IsPassedInRegister(); } //----------------------------------------------------------------------------- @@ -246,7 +305,7 @@ bool ABIPassingInformation::HasExactlyOneRegisterSegment() const // bool ABIPassingInformation::HasExactlyOneStackSegment() const { - return (NumSegments == 1) && Segments[0].IsPassedOnStack(); + return (NumSegments == 1) && Segment(0).IsPassedOnStack(); } //----------------------------------------------------------------------------- @@ -264,10 +323,10 @@ bool ABIPassingInformation::IsSplitAcrossRegistersAndStack() const return false; } - bool isFirstInReg = Segments[0].IsPassedInRegister(); + bool isFirstInReg = Segment(0).IsPassedInRegister(); for (unsigned i = 1; i < NumSegments; i++) { - if (isFirstInReg != Segments[i].IsPassedInRegister()) + if (isFirstInReg != Segment(i).IsPassedInRegister()) { return true; } @@ -288,7 +347,32 @@ bool ABIPassingInformation::IsSplitAcrossRegistersAndStack() const // ABIPassingInformation ABIPassingInformation::FromSegment(Compiler* comp, const ABIPassingSegment& segment) { - return {1, new (comp, CMK_ABI) ABIPassingSegment(segment)}; + ABIPassingInformation info; + info.NumSegments = 1; + info.SingleSegment = segment; + return info; +} + +//----------------------------------------------------------------------------- +// FromSegments: +// Create ABIPassingInformation from two segments. +// +// Parameters: +// comp - Compiler instance +// firstSegment - The first segment that represents the passing information +// secondSegment - The second segment that represents the passing information +// +// Return Value: +// An instance of ABIPassingInformation. +// +ABIPassingInformation ABIPassingInformation::FromSegments(Compiler* comp, + const ABIPassingSegment& firstSegment, + const ABIPassingSegment& secondSegment) +{ + ABIPassingInformation info; + info.NumSegments = 2; + info.Segments = new (comp, CMK_ABI) ABIPassingSegment[2]{firstSegment, secondSegment}; + return info; } #ifdef DEBUG @@ -310,9 +394,9 @@ void ABIPassingInformation::Dump() const printf(" [%u] ", i); } - const ABIPassingSegment& seg = Segments[i]; + const ABIPassingSegment& seg = Segment(i); - if (Segments[i].IsPassedInRegister()) + if (seg.IsPassedInRegister()) { printf("[%02u..%02u) reg %s\n", seg.Offset, seg.Offset + seg.Size, getRegName(seg.GetRegister())); } @@ -418,7 +502,7 @@ ABIPassingInformation SwiftABIClassifier::Classify(Compiler* comp, for (unsigned j = 0; j < elemInfo.NumSegments; j++) { - ABIPassingSegment newSegment = elemInfo.Segments[j]; + ABIPassingSegment newSegment = elemInfo.Segment(j); newSegment.Offset += lowering->offsets[i]; // Adjust the tail size if necessary; the lowered sequence can // pass the tail as a larger type than the tail size. @@ -427,12 +511,10 @@ ABIPassingInformation SwiftABIClassifier::Classify(Compiler* comp, } } - ABIPassingInformation result; - result.NumSegments = static_cast(segments.Height()); - result.Segments = new (comp, CMK_ABI) ABIPassingSegment[result.NumSegments]; + ABIPassingInformation result(comp, static_cast(segments.Height())); for (int i = 0; i < segments.Height(); i++) { - result.Segments[i] = segments.Bottom(i); + result.Segment(i) = segments.Bottom(i); } return result; diff --git a/src/coreclr/jit/abi.h b/src/coreclr/jit/abi.h index 7b8baf1052784e..28a37d86e3d702 100644 --- a/src/coreclr/jit/abi.h +++ b/src/coreclr/jit/abi.h @@ -39,6 +39,14 @@ class ABIPassingSegment struct ABIPassingInformation { +private: + union + { + ABIPassingSegment* Segments; + ABIPassingSegment SingleSegment; + }; + +public: // The number of segments used to pass the value. Examples: // - On SysV x64, structs can be passed in two registers, resulting in two // register segments @@ -51,15 +59,18 @@ struct ABIPassingInformation // - On loongarch64/riscv64, structs can be passed in two registers or // can be split out over register and stack, giving // multiple register segments and a struct segment. - unsigned NumSegments; - ABIPassingSegment* Segments; + unsigned NumSegments; - ABIPassingInformation(unsigned numSegments = 0, ABIPassingSegment* segments = nullptr) - : NumSegments(numSegments) - , Segments(segments) + ABIPassingInformation() + : NumSegments(0) { } + ABIPassingInformation(Compiler* comp, unsigned numSegments); + + const ABIPassingSegment& Segment(unsigned index) const; + ABIPassingSegment& Segment(unsigned index); + bool HasAnyRegisterSegment() const; bool HasAnyStackSegment() const; bool HasExactlyOneRegisterSegment() const; @@ -67,6 +78,9 @@ struct ABIPassingInformation bool IsSplitAcrossRegistersAndStack() const; static ABIPassingInformation FromSegment(Compiler* comp, const ABIPassingSegment& segment); + static ABIPassingInformation FromSegments(Compiler* comp, + const ABIPassingSegment& firstSegment, + const ABIPassingSegment& secondSegment); #ifdef WINDOWS_AMD64_ABI static bool GetShadowSpaceCallerOffsetForReg(regNumber reg, int* offset); diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index 080fe514f25e4c..4f2adda2d3daa0 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -3802,7 +3802,7 @@ void CodeGen::genJmpPlaceVarArgs() const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(varNum); for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& segment = abiInfo.Segments[i]; + const ABIPassingSegment& segment = abiInfo.Segment(i); if (segment.IsPassedInRegister()) { potentialArgs &= ~segment.GetRegisterMask(); diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index ddada03b91944b..240a7d97276421 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -3202,7 +3202,7 @@ void CodeGen::genSpillOrAddRegisterParam(unsigned lclNum, RegGraph* graph) const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(paramLclNum); for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& seg = abiInfo.Segments[i]; + const ABIPassingSegment& seg = abiInfo.Segment(i); if (!seg.IsPassedInRegister() || ((paramRegs & genRegMask(seg.GetRegister())) == 0)) { continue; @@ -3325,7 +3325,7 @@ void CodeGen::genHomeRegisterParams(regNumber initReg, bool* initRegStillZeroed) const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& seg = abiInfo.Segments[i]; + const ABIPassingSegment& seg = abiInfo.Segment(i); if (seg.IsPassedInRegister() && ((paramRegs & genRegMask(seg.GetRegister())) != 0)) { var_types storeType = genParamStackType(lclDsc, seg); @@ -4373,7 +4373,7 @@ void CodeGen::genHomeSwiftStructParameters(bool handleStack) for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& seg = abiInfo.Segments[i]; + const ABIPassingSegment& seg = abiInfo.Segment(i); if (seg.IsPassedOnStack() != handleStack) { continue; @@ -4434,9 +4434,9 @@ void CodeGen::genHomeStackPartOfSplitParameter(regNumber initReg, bool* initRegS JITDUMP("Homing stack part of split parameter V%02u\n", lclNum); assert(abiInfo.NumSegments == 2); - assert(abiInfo.Segments[0].GetRegister() == REG_ARG_LAST); - assert(abiInfo.Segments[1].GetStackOffset() == 0); - const ABIPassingSegment& seg = abiInfo.Segments[1]; + assert(abiInfo.Segment(0).GetRegister() == REG_ARG_LAST); + assert(abiInfo.Segment(1).GetStackOffset() == 0); + const ABIPassingSegment& seg = abiInfo.Segment(1); genHomeStackSegment(lclNum, seg, initReg, initRegStillZeroed); @@ -7514,7 +7514,7 @@ void CodeGen::genJmpPlaceArgs(GenTree* jmp) const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(varNum); for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& segment = abiInfo.Segments[i]; + const ABIPassingSegment& segment = abiInfo.Segment(i); if (segment.IsPassedOnStack()) { continue; diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 25a7fd134a4513..e25766249dc653 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -6565,7 +6565,7 @@ void CodeGen::genJmpPlaceVarArgs() const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(varNum); for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& segment = abiInfo.Segments[i]; + const ABIPassingSegment& segment = abiInfo.Segment(i); if (segment.IsPassedOnStack()) { continue; diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index bf7dc8fb14d7a8..687ac114e329f0 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -1809,10 +1809,10 @@ void Compiler::lvaClassifyParameterABI() else { assert(abiInfo.NumSegments == 1); - if (abiInfo.Segments[0].IsPassedInRegister()) + if (abiInfo.Segment(0).IsPassedInRegister()) { dsc->lvIsRegArg = true; - dsc->SetArgReg(abiInfo.Segments[0].GetRegister()); + dsc->SetArgReg(abiInfo.Segment(0).GetRegister()); dsc->SetOtherArgReg(REG_NA); } else @@ -1820,13 +1820,13 @@ void Compiler::lvaClassifyParameterABI() dsc->lvIsRegArg = false; dsc->SetArgReg(REG_STK); dsc->SetOtherArgReg(REG_NA); - dsc->SetStackOffset(abiInfo.Segments[0].GetStackOffset()); + dsc->SetStackOffset(abiInfo.Segment(0).GetStackOffset()); } } for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& segment = abiInfo.Segments[i]; + const ABIPassingSegment& segment = abiInfo.Segment(i); if (segment.IsPassedInRegister()) { argRegs |= segment.GetRegisterMask(); @@ -1887,7 +1887,7 @@ void Compiler::lvaClassifyParameterABI() for (unsigned i = 0; i < numSegmentsToCompare; i++) { - const ABIPassingSegment& expected = abiInfo.Segments[i]; + const ABIPassingSegment& expected = abiInfo.Segment(i); regNumber reg = REG_NA; if (i == 0) { @@ -1934,19 +1934,19 @@ void Compiler::lvaClassifyParameterABI() if (lvaIsImplicitByRefLocal(lclNum)) { - assert((abiInfo.NumSegments == 1) && (abiInfo.Segments[0].Size == TARGET_POINTER_SIZE)); + assert((abiInfo.NumSegments == 1) && (abiInfo.Segment(0).Size == TARGET_POINTER_SIZE)); } else { for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& segment = abiInfo.Segments[i]; + const ABIPassingSegment& segment = abiInfo.Segment(i); assert(segment.Size > 0); assert(segment.Offset + segment.Size <= lvaLclExactSize(lclNum)); if (i > 0) { - assert(segment.Offset > abiInfo.Segments[i - 1].Offset); + assert(segment.Offset > abiInfo.Segment(i - 1).Offset); } for (unsigned j = 0; j < abiInfo.NumSegments; j++) @@ -1956,7 +1956,7 @@ void Compiler::lvaClassifyParameterABI() continue; } - const ABIPassingSegment& otherSegment = abiInfo.Segments[j]; + const ABIPassingSegment& otherSegment = abiInfo.Segment(j); assert((segment.Offset + segment.Size <= otherSegment.Offset) || (segment.Offset >= otherSegment.Offset + otherSegment.Size)); } @@ -6054,7 +6054,7 @@ bool Compiler::lvaGetRelativeOffsetToCallerAllocatedSpaceForParameter(unsigned l for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& segment = abiInfo.Segments[i]; + const ABIPassingSegment& segment = abiInfo.Segment(i); if (!segment.IsPassedOnStack()) { #if defined(WINDOWS_AMD64_ABI) diff --git a/src/coreclr/jit/lsrabuild.cpp b/src/coreclr/jit/lsrabuild.cpp index 5e0473ca906a4c..590991651b8cb2 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -2302,7 +2302,7 @@ void LinearScan::buildIntervals() const ABIPassingInformation& abiInfo = compiler->lvaGetParameterABIInfo(lclNum); for (unsigned i = 0; i < abiInfo.NumSegments; i++) { - const ABIPassingSegment& seg = abiInfo.Segments[i]; + const ABIPassingSegment& seg = abiInfo.Segment(i); if (seg.IsPassedInRegister()) { RegState* regState = genIsValidFloatReg(seg.GetRegister()) ? floatRegState : intRegState; diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 53f3e166df8851..bc17dd818760db 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -4598,8 +4598,8 @@ GenTree* Compiler::fgMorphExpandStackArgForVarArgs(GenTreeLclVarCommon* lclNode) assert(abiInfo.HasExactlyOneStackSegment()); GenTree* argsBaseAddr = gtNewLclvNode(lvaVarargsBaseOfStkArgs, TYP_I_IMPL); - ssize_t offset = (ssize_t)abiInfo.Segments[0].GetStackOffset() - lclNode->GetLclOffs(); - assert(abiInfo.Segments[0].GetStackOffset() == + ssize_t offset = (ssize_t)abiInfo.Segment(0).GetStackOffset() - lclNode->GetLclOffs(); + assert(abiInfo.Segment(0).GetStackOffset() == (varDsc->GetStackOffset() - codeGen->intRegState.rsCalleeRegArgCount * REGSIZE_BYTES)); GenTree* offsetNode = gtNewIconNode(offset, TYP_I_IMPL); GenTree* argAddr = gtNewOperNode(GT_SUB, TYP_I_IMPL, argsBaseAddr, offsetNode); diff --git a/src/coreclr/jit/targetamd64.cpp b/src/coreclr/jit/targetamd64.cpp index 8f3a979d7862bd..43c200fdd359bd 100644 --- a/src/coreclr/jit/targetamd64.cpp +++ b/src/coreclr/jit/targetamd64.cpp @@ -105,13 +105,12 @@ ABIPassingInformation SysVX64Classifier::Classify(Compiler* comp, { if (varTypeIsStruct(type)) { - info.NumSegments = structDesc.eightByteCount; - info.Segments = new (comp, CMK_ABI) ABIPassingSegment[structDesc.eightByteCount]; + info = ABIPassingInformation(comp, structDesc.eightByteCount); for (unsigned i = 0; i < structDesc.eightByteCount; i++) { regNumber reg = structDesc.IsIntegralSlot(i) ? m_intRegs.Dequeue() : m_floatRegs.Dequeue(); - info.Segments[i] = + info.Segment(i) = ABIPassingSegment::InRegister(reg, structDesc.eightByteOffsets[i], structDesc.eightByteSizes[i]); } } diff --git a/src/coreclr/jit/targetarm.cpp b/src/coreclr/jit/targetarm.cpp index 675fd04230d531..3118621a240e92 100644 --- a/src/coreclr/jit/targetarm.cpp +++ b/src/coreclr/jit/targetarm.cpp @@ -98,14 +98,12 @@ ABIPassingInformation Arm32Classifier::Classify(Compiler* comp, numInRegs = 0; } - ABIPassingInformation info; - info.NumSegments = numInRegs + (anyOnStack ? 1 : 0); - info.Segments = new (comp, CMK_ABI) ABIPassingSegment[info.NumSegments]; + ABIPassingInformation info(comp, numInRegs + (anyOnStack ? 1 : 0)); for (unsigned i = 0; i < numInRegs; i++) { unsigned endOffs = min((i + 1) * 4, size); - info.Segments[i] = + info.Segment(i) = ABIPassingSegment::InRegister(static_cast(static_cast(REG_R0) + m_nextIntReg + i), i * 4, endOffs - (i * 4)); } @@ -114,9 +112,9 @@ ABIPassingInformation Arm32Classifier::Classify(Compiler* comp, if (anyOnStack) { - m_stackArgSize = roundUp(m_stackArgSize, alignment); - unsigned stackSize = size - (numInRegs * 4); - info.Segments[numInRegs] = ABIPassingSegment::OnStack(m_stackArgSize, numInRegs * 4, stackSize); + m_stackArgSize = roundUp(m_stackArgSize, alignment); + unsigned stackSize = size - (numInRegs * 4); + info.Segment(numInRegs) = ABIPassingSegment::OnStack(m_stackArgSize, numInRegs * 4, stackSize); m_stackArgSize += roundUp(stackSize, 4); // As soon as any int arg goes on stack we cannot put anything else in @@ -181,14 +179,12 @@ ABIPassingInformation Arm32Classifier::ClassifyFloat(Compiler* comp, var_types t assert((m_floatRegs & usedRegsMask) == usedRegsMask); m_floatRegs ^= usedRegsMask; - ABIPassingInformation info; - info.NumSegments = numElems; - info.Segments = new (comp, CMK_ABI) ABIPassingSegment[numElems]; - unsigned numRegsPerElem = type == TYP_FLOAT ? 1 : 2; + ABIPassingInformation info(comp, numElems); + unsigned numRegsPerElem = type == TYP_FLOAT ? 1 : 2; for (unsigned i = 0; i < numElems; i++) { regNumber reg = static_cast(static_cast(REG_F0) + startRegIndex + i * numRegsPerElem); - info.Segments[i] = ABIPassingSegment::InRegister(reg, i * genTypeSize(type), genTypeSize(type)); + info.Segment(i) = ABIPassingSegment::InRegister(reg, i * genTypeSize(type), genTypeSize(type)); } return info; diff --git a/src/coreclr/jit/targetarm64.cpp b/src/coreclr/jit/targetarm64.cpp index f95663202456b8..5473db7296ec5e 100644 --- a/src/coreclr/jit/targetarm64.cpp +++ b/src/coreclr/jit/targetarm64.cpp @@ -76,12 +76,11 @@ ABIPassingInformation Arm64Classifier::Classify(Compiler* comp, ABIPassingInformation info; if (m_floatRegs.Count() >= slots) { - info.NumSegments = slots; - info.Segments = new (comp, CMK_ABI) ABIPassingSegment[slots]; + info = ABIPassingInformation(comp, slots); for (unsigned i = 0; i < slots; i++) { - info.Segments[i] = ABIPassingSegment::InRegister(m_floatRegs.Dequeue(), i * elemSize, elemSize); + info.Segment(i) = ABIPassingSegment::InRegister(m_floatRegs.Dequeue(), i * elemSize, elemSize); } } else @@ -132,11 +131,13 @@ ABIPassingInformation Arm64Classifier::Classify(Compiler* comp, // case. Normally a struct that does not fit in registers will always // be passed on stack. assert(compFeatureArgSplit()); - info.NumSegments = 2; - info.Segments = new (comp, CMK_ABI) ABIPassingSegment[2]; - info.Segments[0] = ABIPassingSegment::InRegister(m_intRegs.Dequeue(), 0, TARGET_POINTER_SIZE); - info.Segments[1] = ABIPassingSegment::OnStack(m_stackArgSize, TARGET_POINTER_SIZE, - structLayout->GetSize() - TARGET_POINTER_SIZE); + info = ABIPassingInformation::FromSegments(comp, + ABIPassingSegment::InRegister(m_intRegs.Dequeue(), 0, + TARGET_POINTER_SIZE), + ABIPassingSegment::OnStack(m_stackArgSize, TARGET_POINTER_SIZE, + structLayout->GetSize() - + TARGET_POINTER_SIZE)); + m_stackArgSize += TARGET_POINTER_SIZE; } else @@ -152,15 +153,14 @@ ABIPassingInformation Arm64Classifier::Classify(Compiler* comp, if (regs->Count() >= slots) { - info.NumSegments = slots; - info.Segments = new (comp, CMK_ABI) ABIPassingSegment[slots]; + info = ABIPassingInformation(comp, slots); unsigned slotSize = min(passedSize, (unsigned)TARGET_POINTER_SIZE); - info.Segments[0] = ABIPassingSegment::InRegister(regs->Dequeue(), 0, slotSize); + info.Segment(0) = ABIPassingSegment::InRegister(regs->Dequeue(), 0, slotSize); if (slots == 2) { assert(varTypeIsStruct(type)); unsigned tailSize = structLayout->GetSize() - slotSize; - info.Segments[1] = ABIPassingSegment::InRegister(regs->Dequeue(), slotSize, tailSize); + info.Segment(1) = ABIPassingSegment::InRegister(regs->Dequeue(), slotSize, tailSize); } } else diff --git a/src/coreclr/jit/targetloongarch64.cpp b/src/coreclr/jit/targetloongarch64.cpp index caab31b18988a3..3b8ee6e677cbba 100644 --- a/src/coreclr/jit/targetloongarch64.cpp +++ b/src/coreclr/jit/targetloongarch64.cpp @@ -173,15 +173,14 @@ ABIPassingInformation LoongArch64Classifier::Classify(Compiler* comp, ABIPassingInformation info; if (canPassArgInRegisters) { - info.NumSegments = slots; - info.Segments = new (comp, CMK_ABI) ABIPassingSegment[slots]; + info = ABIPassingInformation(comp, slots); if (argRegTypeInStruct1 != TYP_UNKNOWN) { RegisterQueue* regs = varTypeIsFloating(argRegTypeInStruct1) ? &m_floatRegs : &m_intRegs; assert(regs->Count() > 0); passedSize = genTypeSize(argRegTypeInStruct1); - info.Segments[0] = ABIPassingSegment::InRegister(regs->Dequeue(), 0, passedSize); + info.Segments(0) = ABIPassingSegment::InRegister(regs->Dequeue(), 0, passedSize); if (argRegTypeInStruct2 != TYP_UNKNOWN) { @@ -190,15 +189,15 @@ ABIPassingInformation LoongArch64Classifier::Classify(Compiler* comp, regs = varTypeIsFloating(argRegTypeInStruct2) ? &m_floatRegs : &m_intRegs; assert(regs->Count() > 0); - passedSize = max(passedSize, slotSize); - info.Segments[1] = ABIPassingSegment::InRegister(regs->Dequeue(), passedSize, slotSize); + passedSize = max(passedSize, slotSize); + info.Segment(1) = ABIPassingSegment::InRegister(regs->Dequeue(), passedSize, slotSize); } } else { RegisterQueue* regs = varTypeIsFloating(type) ? &m_floatRegs : &m_intRegs; unsigned slotSize = min(passedSize, (unsigned)TARGET_POINTER_SIZE); - info.Segments[0] = ABIPassingSegment::InRegister(regs->Dequeue(), 0, slotSize); + info.Segment(0) = ABIPassingSegment::InRegister(regs->Dequeue(), 0, slotSize); if (slots == 2) { assert(varTypeIsStruct(type)); @@ -206,13 +205,13 @@ ABIPassingInformation LoongArch64Classifier::Classify(Compiler* comp, unsigned tailSize = passedSize - slotSize; if (m_intRegs.Count() > 0) { - info.Segments[1] = ABIPassingSegment::InRegister(m_intRegs.Dequeue(), slotSize, tailSize); + info.Segment(1) = ABIPassingSegment::InRegister(m_intRegs.Dequeue(), slotSize, tailSize); } else { assert(m_intRegs.Count() == 0); assert(m_stackArgSize == 0); - info.Segments[1] = ABIPassingSegment::OnStack(0, TARGET_POINTER_SIZE, tailSize); + info.Segment(1) = ABIPassingSegment::OnStack(0, TARGET_POINTER_SIZE, tailSize); m_stackArgSize += TARGET_POINTER_SIZE; } } diff --git a/src/coreclr/jit/targetriscv64.cpp b/src/coreclr/jit/targetriscv64.cpp index 4df767d8cbfcc2..6adb2b7b91ea1b 100644 --- a/src/coreclr/jit/targetriscv64.cpp +++ b/src/coreclr/jit/targetriscv64.cpp @@ -130,9 +130,8 @@ ABIPassingInformation RiscV64Classifier::Classify(Compiler* comp, regNumber firstReg = (isFirstFloat ? m_floatRegs : m_intRegs).Dequeue(); regNumber secondReg = (isSecondFloat ? m_floatRegs : m_intRegs).Dequeue(); - return {2, new (comp, CMK_ABI) - ABIPassingSegment[2]{ABIPassingSegment::InRegister(firstReg, 0, firstSize), - ABIPassingSegment::InRegister(secondReg, offset, secondSize)}}; + return ABIPassingInformation::FromSegments(comp, ABIPassingSegment::InRegister(firstReg, 0, firstSize), + ABIPassingSegment::InRegister(secondReg, offset, secondSize)); } } else @@ -164,7 +163,7 @@ ABIPassingInformation RiscV64Classifier::Classify(Compiler* comp, (m_intRegs.Count() > 0) ? ABIPassingSegment::InRegister(m_intRegs.Dequeue(), TARGET_POINTER_SIZE, tailSize) : passOnStack(TARGET_POINTER_SIZE, tailSize); - return {2, new (comp, CMK_ABI) ABIPassingSegment[2]{head, tail}}; + return ABIPassingInformation::FromSegments(comp, head, tail); } } else