From fb552a3aa9e77070591a8cb253314b56df7ae516 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 19 Jun 2024 11:25:55 +0200 Subject: [PATCH] JIT: Store one segment inline in ABIPassingInformation 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 4ef6f034dd0f8..b60142a856953 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 7b8baf1052784..28a37d86e3d70 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 080fe514f25e4..4f2adda2d3daa 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 2a1d7652ac541..da92699b6b235 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 25a7fd134a451..e25766249dc65 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 bf7dc8fb14d7a..687ac114e329f 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 89fd0433e346b..fddddf61b4101 100644 --- a/src/coreclr/jit/lsrabuild.cpp +++ b/src/coreclr/jit/lsrabuild.cpp @@ -2312,7 +2312,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 733b429675d09..a41a2485ef7f1 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 8f3a979d7862b..43c200fdd359b 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 675fd04230d53..3118621a240e9 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 f95663202456b..5473db7296ec5 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 caab31b18988a..3b8ee6e677cbb 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 4df767d8cbfcc..6adb2b7b91ea1 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