Skip to content

Commit e537db7

Browse files
jakobbotschtomeksowi
authored andcommitted
JIT: Use new ABI classifiers for GenTreeCall arguments (dotnet#103537)
Switch `AddFinalArgsAndDetermineABIInfo` to reuse the new-style ABI classifiers. Does not remove the old ABI information representation in `CallArg`, but keeps both for now. Co-authored-by: Tomasz Sowiński <tomeksowi@gmail.com>
1 parent c878ec6 commit e537db7

File tree

9 files changed

+198
-978
lines changed

9 files changed

+198
-978
lines changed

src/coreclr/jit/abi.cpp

+25-6
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ ABIPassingInformation::ABIPassingInformation(Compiler* comp, unsigned numSegment
206206

207207
if (numSegments > 1)
208208
{
209-
Segments = new (comp, CMK_ABI) ABIPassingSegment[numSegments];
209+
m_segments = new (comp, CMK_ABI) ABIPassingSegment[numSegments];
210210
}
211211
}
212212

@@ -225,10 +225,10 @@ const ABIPassingSegment& ABIPassingInformation::Segment(unsigned index) const
225225
assert(index < NumSegments);
226226
if (NumSegments == 1)
227227
{
228-
return SingleSegment;
228+
return m_singleSegment;
229229
}
230230

231-
return Segments[index];
231+
return m_segments[index];
232232
}
233233

234234
//-----------------------------------------------------------------------------
@@ -265,6 +265,25 @@ bool ABIPassingInformation::HasAnyRegisterSegment() const
265265
return false;
266266
}
267267

268+
//-----------------------------------------------------------------------------
269+
// HasAnyFloatingRegisterSegment:
270+
// Check if any part of this value is passed in a floating-point register.
271+
//
272+
// Return Value:
273+
// True if so.
274+
//
275+
bool ABIPassingInformation::HasAnyFloatingRegisterSegment() const
276+
{
277+
for (unsigned i = 0; i < NumSegments; i++)
278+
{
279+
if (Segment(i).IsPassedInRegister() && genIsValidFloatReg(Segment(i).GetRegister()))
280+
{
281+
return true;
282+
}
283+
}
284+
return false;
285+
}
286+
268287
//-----------------------------------------------------------------------------
269288
// HasAnyStackSegment:
270289
// Check if any part of this value is passed on the stack.
@@ -348,8 +367,8 @@ bool ABIPassingInformation::IsSplitAcrossRegistersAndStack() const
348367
ABIPassingInformation ABIPassingInformation::FromSegment(Compiler* comp, const ABIPassingSegment& segment)
349368
{
350369
ABIPassingInformation info;
351-
info.NumSegments = 1;
352-
info.SingleSegment = segment;
370+
info.NumSegments = 1;
371+
info.m_singleSegment = segment;
353372
return info;
354373
}
355374

@@ -371,7 +390,7 @@ ABIPassingInformation ABIPassingInformation::FromSegments(Compiler*
371390
{
372391
ABIPassingInformation info;
373392
info.NumSegments = 2;
374-
info.Segments = new (comp, CMK_ABI) ABIPassingSegment[2]{firstSegment, secondSegment};
393+
info.m_segments = new (comp, CMK_ABI) ABIPassingSegment[2]{firstSegment, secondSegment};
375394
return info;
376395
}
377396

src/coreclr/jit/abi.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
#pragma once
55

6+
class ClassLayout;
7+
enum class WellKnownArg : unsigned;
8+
69
class ABIPassingSegment
710
{
811
regNumber m_register = REG_NA;
@@ -42,8 +45,8 @@ struct ABIPassingInformation
4245
private:
4346
union
4447
{
45-
ABIPassingSegment* Segments;
46-
ABIPassingSegment SingleSegment;
48+
ABIPassingSegment* m_segments;
49+
ABIPassingSegment m_singleSegment;
4750
};
4851

4952
public:
@@ -72,6 +75,7 @@ struct ABIPassingInformation
7275
ABIPassingSegment& Segment(unsigned index);
7376

7477
bool HasAnyRegisterSegment() const;
78+
bool HasAnyFloatingRegisterSegment() const;
7579
bool HasAnyStackSegment() const;
7680
bool HasExactlyOneRegisterSegment() const;
7781
bool HasExactlyOneStackSegment() const;

src/coreclr/jit/gentree.cpp

+5-83
Original file line numberDiff line numberDiff line change
@@ -1258,87 +1258,6 @@ void CallArgABIInformation::SetHfaType(var_types type, unsigned hfaSlots)
12581258
}
12591259
}
12601260

1261-
//---------------------------------------------------------------
1262-
// SetByteSize: Set information related to this argument's size and alignment.
1263-
//
1264-
// Arguments:
1265-
// byteSize - The size in bytes of the argument.
1266-
// byteAlignment - The alignment in bytes of the argument.
1267-
// isStruct - Whether this arg is a struct.
1268-
// isFloatHfa - Whether this is a float HFA.
1269-
//
1270-
// Remarks:
1271-
// This function will determine how the argument size needs to be rounded. On
1272-
// most ABIs all arguments are rounded to stack pointer size, but Apple arm64
1273-
// ABI is an exception as it allows packing some small arguments into the
1274-
// same stack slot.
1275-
//
1276-
void CallArgABIInformation::SetByteSize(unsigned byteSize, unsigned byteAlignment, bool isStruct, bool isFloatHfa)
1277-
{
1278-
unsigned roundedByteSize;
1279-
if (compAppleArm64Abi())
1280-
{
1281-
// Only struct types need extension or rounding to pointer size, but HFA<float> does not.
1282-
if (isStruct && !isFloatHfa)
1283-
{
1284-
roundedByteSize = roundUp(byteSize, TARGET_POINTER_SIZE);
1285-
}
1286-
else
1287-
{
1288-
roundedByteSize = byteSize;
1289-
}
1290-
}
1291-
else
1292-
{
1293-
roundedByteSize = roundUp(byteSize, TARGET_POINTER_SIZE);
1294-
}
1295-
1296-
#if !defined(TARGET_ARM)
1297-
// Arm32 could have a struct with 8 byte alignment
1298-
// which rounded size % 8 is not 0.
1299-
assert(byteAlignment != 0);
1300-
assert(roundedByteSize % byteAlignment == 0);
1301-
#endif // TARGET_ARM
1302-
1303-
ByteSize = roundedByteSize;
1304-
ByteAlignment = byteAlignment;
1305-
}
1306-
1307-
//---------------------------------------------------------------
1308-
// SetMultiRegsNumw: Set the registers for a multi-reg arg using 'sequential' registers.
1309-
//
1310-
// Remarks:
1311-
// This assumes that `NumRegs` and the first reg num has already been set and
1312-
// determines how many sequential registers are necessary to pass the
1313-
// argument.
1314-
// Note that on ARM the registers set may skip odd float registers if the arg
1315-
// is a HFA of doubles, since double and float registers overlap.
1316-
void CallArgABIInformation::SetMultiRegNums()
1317-
{
1318-
#if FEATURE_MULTIREG_ARGS && !defined(UNIX_AMD64_ABI) && !defined(TARGET_LOONGARCH64) && !defined(TARGET_RISCV64)
1319-
if (NumRegs == 1)
1320-
{
1321-
return;
1322-
}
1323-
1324-
regNumber argReg = GetRegNum(0);
1325-
#ifdef TARGET_ARM
1326-
unsigned int regSize = (GetHfaType() == TYP_DOUBLE) ? 2 : 1;
1327-
#else
1328-
unsigned int regSize = 1;
1329-
#endif
1330-
1331-
if (NumRegs > MAX_ARG_REG_COUNT)
1332-
NO_WAY("Multireg argument exceeds the maximum length");
1333-
1334-
for (unsigned int regIndex = 1; regIndex < NumRegs; regIndex++)
1335-
{
1336-
argReg = (regNumber)(argReg + regSize);
1337-
SetRegNum(regIndex, argReg);
1338-
}
1339-
#endif // FEATURE_MULTIREG_ARGS && !defined(UNIX_AMD64_ABI) && !defined(TARGET_LOONGARCH64) && !defined(TARGET_RISCV64)
1340-
}
1341-
13421261
//---------------------------------------------------------------
13431262
// GetStackByteSize: Get the number of stack bytes used to pass this argument.
13441263
//
@@ -1468,7 +1387,7 @@ void CallArg::CheckIsStruct()
14681387
CallArgs::CallArgs()
14691388
: m_head(nullptr)
14701389
, m_lateHead(nullptr)
1471-
, m_nextStackByteOffset(0)
1390+
, m_argsStackSize(0)
14721391
#ifdef UNIX_X86_ABI
14731392
, m_stkSizeBytes(0)
14741393
, m_padStkAlign(0)
@@ -9817,7 +9736,7 @@ void CallArgs::InternalCopyFrom(Compiler* comp, CallArgs* other, CopyNodeFunc co
98179736
{
98189737
assert((m_head == nullptr) && (m_lateHead == nullptr));
98199738

9820-
m_nextStackByteOffset = other->m_nextStackByteOffset;
9739+
m_argsStackSize = other->m_argsStackSize;
98219740
m_hasThisPointer = other->m_hasThisPointer;
98229741
m_hasRetBuffer = other->m_hasRetBuffer;
98239742
m_isVarArgs = other->m_isVarArgs;
@@ -9845,6 +9764,7 @@ void CallArgs::InternalCopyFrom(Compiler* comp, CallArgs* other, CopyNodeFunc co
98459764
carg->m_isTmp = arg.m_isTmp;
98469765
carg->m_processed = arg.m_processed;
98479766
carg->AbiInfo = arg.AbiInfo;
9767+
carg->NewAbiInfo = arg.NewAbiInfo;
98489768
*tail = carg;
98499769
tail = &carg->m_next;
98509770
}
@@ -13174,6 +13094,8 @@ const char* Compiler::gtGetWellKnownArgNameForArgMsg(WellKnownArg arg)
1317413094
return "swift error";
1317513095
case WellKnownArg::SwiftSelf:
1317613096
return "swift self";
13097+
case WellKnownArg::X86TailCallSpecialArg:
13098+
return "tail call";
1317713099
default:
1317813100
return nullptr;
1317913101
}

src/coreclr/jit/gentree.h

+4-15
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1818
#define _GENTREE_H_
1919
/*****************************************************************************/
2020

21+
#include "abi.h"
2122
#include "vartype.h" // For "var_types"
2223
#include "target.h" // For "regNumber"
2324
#include "ssaconfig.h" // For "SsaConfig::RESERVED_SSA_NUM"
@@ -4480,6 +4481,7 @@ enum class WellKnownArg : unsigned
44804481
DispatchIndirectCallTarget,
44814482
SwiftError,
44824483
SwiftSelf,
4484+
X86TailCallSpecialArg,
44834485
};
44844486

44854487
#ifdef DEBUG
@@ -4492,12 +4494,10 @@ struct CallArgABIInformation
44924494
: NumRegs(0)
44934495
, ByteOffset(0)
44944496
, ByteSize(0)
4495-
, ByteAlignment(0)
44964497
#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
44974498
, StructFloatFieldType()
44984499
#endif
44994500
, ArgType(TYP_UNDEF)
4500-
, IsBackFilled(false)
45014501
, PassedByRef(false)
45024502
#if FEATURE_ARG_SPLIT
45034503
, m_isSplit(false)
@@ -4523,7 +4523,6 @@ struct CallArgABIInformation
45234523
unsigned NumRegs;
45244524
unsigned ByteOffset;
45254525
unsigned ByteSize;
4526-
unsigned ByteAlignment;
45274526
#if defined(UNIX_AMD64_ABI)
45284527
// Unix amd64 will split floating point types and integer types in structs
45294528
// between floating point and general purpose registers. Keep track of that
@@ -4541,9 +4540,6 @@ struct CallArgABIInformation
45414540
// that type. Note that if a struct is passed by reference, this will still
45424541
// be the struct type.
45434542
var_types ArgType : 5;
4544-
// True when the argument fills a register slot skipped due to alignment
4545-
// requirements of previous arguments.
4546-
bool IsBackFilled : 1;
45474543
// True iff the argument is passed by reference.
45484544
bool PassedByRef : 1;
45494545

@@ -4641,18 +4637,11 @@ struct CallArgABIInformation
46414637
#endif // TARGET_LOONGARCH64 || TARGET_RISCV64
46424638
}
46434639

4644-
void SetByteSize(unsigned byteSize, unsigned byteAlignment, bool isStruct, bool isFloatHfa);
4645-
46464640
// Get the number of bytes that this argument is occupying on the stack,
46474641
// including padding up to the target pointer size for platforms
46484642
// where a stack argument can't take less.
46494643
unsigned GetStackByteSize() const;
46504644

4651-
// Set the register numbers for a multireg argument.
4652-
// There's nothing to do on x64/Ux because the structDesc has already been used to set the
4653-
// register numbers.
4654-
void SetMultiRegNums();
4655-
46564645
// Return number of stack slots that this argument is taking.
46574646
// This value is not meaningful on Apple arm64 where multiple arguments can
46584647
// be passed in the same stack slot.
@@ -4755,6 +4744,7 @@ class CallArg
47554744

47564745
public:
47574746
CallArgABIInformation AbiInfo;
4747+
ABIPassingInformation NewAbiInfo;
47584748

47594749
CallArg(const NewCallArg& arg)
47604750
: CallArg()
@@ -4817,7 +4807,7 @@ class CallArgs
48174807
CallArg* m_head;
48184808
CallArg* m_lateHead;
48194809

4820-
unsigned m_nextStackByteOffset;
4810+
unsigned m_argsStackSize;
48214811
#ifdef UNIX_X86_ABI
48224812
// Number of stack bytes pushed before we start pushing these arguments.
48234813
unsigned m_stkSizeBytes;
@@ -4846,7 +4836,6 @@ class CallArgs
48464836
void AddedWellKnownArg(WellKnownArg arg);
48474837
void RemovedWellKnownArg(WellKnownArg arg);
48484838
regNumber GetCustomRegister(Compiler* comp, CorInfoCallConvExtension cc, WellKnownArg arg);
4849-
void SplitArg(CallArg* arg, unsigned numRegs, unsigned numSlots);
48504839
void SortArgs(Compiler* comp, GenTreeCall* call, CallArg** sortedArgs);
48514840

48524841
public:

src/coreclr/jit/lclvars.cpp

+2-6
Original file line numberDiff line numberDiff line change
@@ -1721,7 +1721,8 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc,
17211721
template <typename Classifier>
17221722
void Compiler::lvaClassifyParameterABI(Classifier& classifier)
17231723
{
1724-
lvaParameterPassingInfo = new (this, CMK_LvaTable) ABIPassingInformation[info.compArgsCount];
1724+
lvaParameterPassingInfo =
1725+
info.compArgsCount == 0 ? nullptr : new (this, CMK_LvaTable) ABIPassingInformation[info.compArgsCount];
17251726

17261727
for (unsigned i = 0; i < info.compArgsCount; i++)
17271728
{
@@ -1768,11 +1769,6 @@ void Compiler::lvaClassifyParameterABI(Classifier& classifier)
17681769
//
17691770
void Compiler::lvaClassifyParameterABI()
17701771
{
1771-
if (info.compArgsCount == 0)
1772-
{
1773-
return;
1774-
}
1775-
17761772
ClassifierInfo cInfo;
17771773
cInfo.CallConv = info.compCallConv;
17781774
cInfo.IsVarArgs = info.compIsVarArgs;

src/coreclr/jit/lower.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -3448,10 +3448,13 @@ void Lowering::LowerCFGCall(GenTreeCall* call)
34483448
call->gtArgs.PushLateBack(targetArg);
34493449

34503450
// Set up ABI information for this arg.
3451+
targetArg->NewAbiInfo =
3452+
ABIPassingInformation::FromSegment(comp, ABIPassingSegment::InRegister(REG_DISPATCH_INDIRECT_CALL_ADDR,
3453+
0, TARGET_POINTER_SIZE));
34513454
targetArg->AbiInfo.ArgType = callTarget->TypeGet();
34523455
targetArg->AbiInfo.SetRegNum(0, REG_DISPATCH_INDIRECT_CALL_ADDR);
3453-
targetArg->AbiInfo.NumRegs = 1;
3454-
targetArg->AbiInfo.SetByteSize(TARGET_POINTER_SIZE, TARGET_POINTER_SIZE, false, false);
3456+
targetArg->AbiInfo.NumRegs = 1;
3457+
targetArg->AbiInfo.ByteSize = TARGET_POINTER_SIZE;
34553458

34563459
// Lower the newly added args now that call is updated
34573460
LowerArg(call, targetArg, true /* late */);

src/coreclr/jit/lsrabuild.cpp

-7
Original file line numberDiff line numberDiff line change
@@ -602,14 +602,7 @@ RefPosition* LinearScan::newRefPosition(Interval* theInterval,
602602
regNumber physicalReg = genRegNumFromMask(mask, theInterval->registerType);
603603
RefPosition* pos = newRefPosition(physicalReg, theLocation, RefTypeFixedReg, nullptr, mask);
604604
assert(theInterval != nullptr);
605-
#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
606-
// The LoongArch64's ABI which the float args maybe passed by integer register
607-
// when no float register left but free integer register.
608-
assert((regType(theInterval->registerType) == FloatRegisterType) ||
609-
(allRegs(theInterval->registerType) & mask) != 0);
610-
#else
611605
assert((allRegs(theInterval->registerType) & mask) != 0);
612-
#endif
613606
}
614607

615608
RefPosition* newRP = newRefPositionRaw(theLocation, theTreeNode, theRefType);

0 commit comments

Comments
 (0)