Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISC-V][LoongArch64] New passing info for floating-point structs #103945

Merged
merged 38 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
dcf2edb
Replace StructFloatFieldInfoFlags with FpStructInRegistersInfo which …
tomeksowi Jun 25, 2024
48caa9c
Replace StructFloatFieldInfoFlags with FpStruct::Flags in profiler
tomeksowi Jun 25, 2024
853bd99
Remove FpStructInRegistersInfo::FromOldFlags()
tomeksowi Jun 25, 2024
0e80ccf
Fix duplicating types in HandleInlineArray
tomeksowi Jun 25, 2024
3d139ac
Remove signedness from FpStruct::IntKind because most probably we won…
tomeksowi Jun 25, 2024
89cc148
Remove old StructFloatFieldInfoFlags calculating routine
tomeksowi Jun 25, 2024
c2984a2
Typo in TARGET_LOONGARCH64
tomeksowi Jun 25, 2024
a229831
Remove m_returnedFpFieldOffsets from ArgIterator
tomeksowi Jun 25, 2024
f2b38f8
Add missing ENREGISTERED_PARAMTYPE_MAXSIZE condition to C# version of…
tomeksowi Jun 25, 2024
5481693
Rename RISCV64PassStructInRegister to match settled casing for RiscV …
tomeksowi Jun 26, 2024
4250bf4
Update hardcoded flags for float and double in ArgIteratorTemplate::C…
tomeksowi Jun 26, 2024
0f03a88
Fix build on other platforms
tomeksowi Jun 26, 2024
f485362
Update LoongArch to use FpStructInRegistersInfo
tomeksowi Jun 26, 2024
9967e2e
Remove unused old flag masks
tomeksowi Jun 26, 2024
6bc28d1
LoongArch64 typo
tomeksowi Jun 27, 2024
33a6aee
Missing FpStruct namespace
tomeksowi Jun 27, 2024
1e951bd
Missing FpStruct namespace
tomeksowi Jun 27, 2024
fd49a25
Missing FpStruct namespace
tomeksowi Jun 27, 2024
214b94f
Use FpStruct namespace everywhere in JIT
tomeksowi Jun 27, 2024
e34a68d
Merge branch 'main' into fp-struct-info
tomeksowi Jul 1, 2024
08c6385
JIT review
tomeksowi Jul 2, 2024
f163a78
Merge branch 'main' into fp-struct-info
tomeksowi Jul 3, 2024
e23c0ab
Update StructFloatFieldInfoFlags description
tomeksowi Jul 3, 2024
ef5a6d4
Revert to hitherto instruction set order as it's not the point of thi…
tomeksowi Jul 3, 2024
100eced
Unify get{LoongArch,RiscV}64PassFpStructInRegistersInfo JIT interfaces
tomeksowi Jul 4, 2024
5c9e5ac
Use JIT_TO_EE_TRANSITION instead of _LEAF because MethodTable::GetFpS…
tomeksowi Jul 4, 2024
1d5ad91
Remove FpStruct::IntKind, we should have similar info in ClassLayout …
tomeksowi Jul 4, 2024
7b1587b
Change JIT interface to return a struct similar to CORINFO_SWIFT_LOWE…
tomeksowi Jul 8, 2024
e37e984
Change JIT to use new Swift-like getFpStructLowering
tomeksowi Jul 9, 2024
c7c88e0
Cache CORINFO_FPSTRUCT_LOWERING
tomeksowi Jul 9, 2024
5c478d7
Update LoongArch classifier to use CORINFO_FPSTRUCT_LOWERING
tomeksowi Jul 9, 2024
1f16783
Update StructFloatInfoFlags doc comment on C#
tomeksowi Jul 9, 2024
f064eb6
Move StructFloatFieldInfoFlags and FpStructInRegistersInfo out of the…
tomeksowi Jul 11, 2024
d4be92c
Merge LoongArch and RISC-V AOT calculation of FpStructInRegistersInfo…
tomeksowi Jul 11, 2024
823df8b
Don't zero-initialize CORINFO_FPSTRUCT_LOWERING
tomeksowi Jul 12, 2024
c209a55
Merge branch 'main' into fp-struct-info
tomeksowi Jul 25, 2024
8ddd349
Add note for CORINFO_FPSTRUCT_LOWERING::loweredElements type
tomeksowi Jul 25, 2024
9dc5ed5
object is lowercase
tomeksowi Jul 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 20 additions & 41 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,45 +307,6 @@ struct SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR
}
};

// StructFloadFieldInfoFlags: used on LoongArch64 architecture by `getLoongArch64PassStructInRegisterFlags` and
// `getRISCV64PassStructInRegisterFlags` API to convey struct argument passing information.
//
// `STRUCT_NO_FLOAT_FIELD` means structs are not passed using the float register(s).
//
// Otherwise, and only for structs with no more than two fields and a total struct size no larger
// than two pointers:
//
// The lowest four bits denote the floating-point info:
// bit 0: `1` means there is only one float or double field within the struct.
// bit 1: `1` means only the first field is floating-point type.
// bit 2: `1` means only the second field is floating-point type.
// bit 3: `1` means the two fields are both floating-point type.
// The bits[5:4] denoting whether the field size is 8-bytes:
// bit 4: `1` means the first field's size is 8.
// bit 5: `1` means the second field's size is 8.
//
// Note that bit 0 and 3 cannot both be set.
enum StructFloatFieldInfoFlags
{
STRUCT_NO_FLOAT_FIELD = 0x0,
STRUCT_FLOAT_FIELD_ONLY_ONE = 0x1,
STRUCT_FLOAT_FIELD_ONLY_TWO = 0x8,
STRUCT_FLOAT_FIELD_FIRST = 0x2,
STRUCT_FLOAT_FIELD_SECOND = 0x4,
STRUCT_FIRST_FIELD_SIZE_IS8 = 0x10,
STRUCT_SECOND_FIELD_SIZE_IS8 = 0x20,

STRUCT_FIRST_FIELD_DOUBLE = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FIRST_FIELD_SIZE_IS8),
STRUCT_SECOND_FIELD_DOUBLE = (STRUCT_FLOAT_FIELD_SECOND | STRUCT_SECOND_FIELD_SIZE_IS8),
STRUCT_FIELD_TWO_DOUBLES = (STRUCT_FIRST_FIELD_SIZE_IS8 | STRUCT_SECOND_FIELD_SIZE_IS8 | STRUCT_FLOAT_FIELD_ONLY_TWO),

STRUCT_MERGE_FIRST_SECOND = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_TWO),
STRUCT_MERGE_FIRST_SECOND_8 = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_SECOND_FIELD_SIZE_IS8),

STRUCT_HAS_FLOAT_FIELDS_MASK = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_SECOND | STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FLOAT_FIELD_ONLY_ONE),
STRUCT_HAS_8BYTES_FIELDS_MASK = (STRUCT_FIRST_FIELD_SIZE_IS8 | STRUCT_SECOND_FIELD_SIZE_IS8),
};

#include "corinfoinstructionset.h"

// CorInfoHelpFunc defines the set of helpers (accessed via the ICorDynamicInfo::getHelperFtn())
Expand Down Expand Up @@ -1940,6 +1901,23 @@ struct CORINFO_SWIFT_LOWERING
size_t numLoweredElements;
};

#define MAX_FPSTRUCT_LOWERED_ELEMENTS 2

// Lowering information on fields of a struct passed by hardware floating-point calling convention on RISC-V and LoongArch
struct CORINFO_FPSTRUCT_LOWERING
{
// Whether the struct should be passed by integer calling convention (cannot be passed by FP calling convention).
bool byIntegerCallConv;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my edification, what's the calling convention of struct { object o; float a; }?

Is it passed using this special lowering or using integer call conv?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to floating-point calling convention (special lowering). Object is a pointer, which for the convention is simply an integer field.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the Object field from my example be reported as CORINFO_TYPE_CLASS in this struct then? It does not look right that it is reported as int.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we agreed that JIT doesn't need to know IntKind (it was used to tell ordinary integers from GC refs), because it can probe for GC refs from the layout it knows already.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently JIT only needs to know from CORINFO_FPSTRUCT_LOWERING whether the type is floating or integer and the type size. GC info is taken from class layout.

I'd like to merge as is if it's not a problem, this PR blocks #104237 and subsequent changes stemming from #101796. If it turns out that the integer type needs to be more precisely specified for some reason, we can always amend it and FpStructInRegistersInfo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping. Can this be merged?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add a comment that the types returned in loweredElements only represent the size and not the actual type?

(An alternative would be to change loweredElements to uint32_t loweredElementsSizes[] to make it obvious that the API just returns the size and not the actual type.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comment. The alternative would need another bool array for floating vs. integer and would stray from CORINFO_SWIFT_LOWERING if the need to handle ABI lowering in shared code ever comes up.

// Types of lowered struct fields.
// Note: the integer field is denoted with a signed type reflecting size only so e.g. ushort is reported
// as CORINFO_TYPE_SHORT and object or string is reported as CORINFO_TYPE_LONG.
CorInfoType loweredElements[MAX_FPSTRUCT_LOWERED_ELEMENTS];
// Offsets of lowered struct fields.
uint32_t offsets[MAX_FPSTRUCT_LOWERED_ELEMENTS];
// Number of lowered struct fields.
size_t numLoweredElements;
};

#define SIZEOF__CORINFO_Object TARGET_POINTER_SIZE /* methTable */

#define CORINFO_Array_MaxLength 0x7FFFFFC7
Expand Down Expand Up @@ -3065,8 +3043,9 @@ class ICorStaticInfo
// Classifies a swift structure into primitives or an implicit byref for ABI purposes.
virtual void getSwiftLowering(CORINFO_CLASS_HANDLE structHnd, CORINFO_SWIFT_LOWERING* pLowering) = 0;

virtual uint32_t getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) = 0;
virtual uint32_t getRISCV64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) = 0;
// Returns lowering info for fields of a RISC-V/LoongArch struct passed in registers according to
// hardware floating-point calling convention.
virtual void getFpStructLowering(CORINFO_CLASS_HANDLE structHnd, CORINFO_FPSTRUCT_LOWERING* pLowering) = 0;
};

/*****************************************************************************
Expand Down
8 changes: 3 additions & 5 deletions src/coreclr/inc/icorjitinfoimpl_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,11 +520,9 @@ void getSwiftLowering(
CORINFO_CLASS_HANDLE structHnd,
CORINFO_SWIFT_LOWERING* pLowering) override;

uint32_t getLoongArch64PassStructInRegisterFlags(
CORINFO_CLASS_HANDLE structHnd) override;

uint32_t getRISCV64PassStructInRegisterFlags(
CORINFO_CLASS_HANDLE structHnd) override;
void getFpStructLowering(
CORINFO_CLASS_HANDLE structHnd,
CORINFO_FPSTRUCT_LOWERING* pLowering) override;

uint32_t getThreadTLSIndex(
void** ppIndirection) override;
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

constexpr GUID JITEEVersionIdentifier = { /* 488a17ce-26c9-4ad0-a7b7-79bf320ea4d1 */
0x488a17ce,
0x26c9,
0x4ad0,
{0xa7, 0xb7, 0x79, 0xbf, 0x32, 0x0e, 0xa4, 0xd1}
constexpr GUID JITEEVersionIdentifier = { /* e770e8ad-50d5-4511-a435-a3ed3a847a47 */
0xe770e8ad,
0x50d5,
0x4511,
{0xa4, 0x35, 0xa3, 0xed, 0x3a, 0x84, 0x7a, 0x47}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/jit/ICorJitInfo_names_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@ DEF_CLR_API(getMethodNameFromMetadata)
DEF_CLR_API(getMethodHash)
DEF_CLR_API(getSystemVAmd64PassStructInRegisterDescriptor)
DEF_CLR_API(getSwiftLowering)
DEF_CLR_API(getLoongArch64PassStructInRegisterFlags)
DEF_CLR_API(getRISCV64PassStructInRegisterFlags)
DEF_CLR_API(getFpStructLowering)
DEF_CLR_API(getThreadTLSIndex)
DEF_CLR_API(getAddrOfCaptureThreadGlobal)
DEF_CLR_API(getHelperFtn)
Expand Down
21 changes: 6 additions & 15 deletions src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1238,22 +1238,13 @@ void WrapICorJitInfo::getSwiftLowering(
API_LEAVE(getSwiftLowering);
}

uint32_t WrapICorJitInfo::getLoongArch64PassStructInRegisterFlags(
CORINFO_CLASS_HANDLE structHnd)
{
API_ENTER(getLoongArch64PassStructInRegisterFlags);
uint32_t temp = wrapHnd->getLoongArch64PassStructInRegisterFlags(structHnd);
API_LEAVE(getLoongArch64PassStructInRegisterFlags);
return temp;
}

uint32_t WrapICorJitInfo::getRISCV64PassStructInRegisterFlags(
CORINFO_CLASS_HANDLE structHnd)
void WrapICorJitInfo::getFpStructLowering(
CORINFO_CLASS_HANDLE structHnd,
CORINFO_FPSTRUCT_LOWERING* pLowering)
{
API_ENTER(getRISCV64PassStructInRegisterFlags);
uint32_t temp = wrapHnd->getRISCV64PassStructInRegisterFlags(structHnd);
API_LEAVE(getRISCV64PassStructInRegisterFlags);
return temp;
API_ENTER(getFpStructLowering);
wrapHnd->getFpStructLowering(structHnd, pLowering);
API_LEAVE(getFpStructLowering);
}

uint32_t WrapICorJitInfo::getThreadTLSIndex(
Expand Down
12 changes: 6 additions & 6 deletions src/coreclr/jit/buildstring.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#define STRINGIFY(L) #L
#define MAKESTRING(M, L) M(L)
#define STRINGIZE(X) MAKESTRING(STRINGIFY, X)
#include "utils.h"

#if defined(__clang__)
#define BUILD_COMPILER \
"Clang " STRINGIZE(__clang_major__) "." STRINGIZE(__clang_minor__) "." STRINGIZE(__clang_patchlevel__)
"Clang " STRINGIFY(__clang_major__) "." STRINGIFY(__clang_minor__) "." STRINGIFY(__clang_patchlevel__)
tomeksowi marked this conversation as resolved.
Show resolved Hide resolved
#elif defined(_MSC_VER)
#define BUILD_COMPILER "MSVC " STRINGIZE(_MSC_FULL_VER)
#define BUILD_COMPILER "MSVC " STRINGIFY(_MSC_FULL_VER)
#elif defined(__GNUC__)
#define BUILD_COMPILER "GCC " STRINGIZE(__GNUC__) "." STRINGIZE(__GNUC_MINOR__) "." STRINGIZE(__GNUC_PATCHLEVEL__)
#define BUILD_COMPILER "GCC " STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) "." STRINGIFY(__GNUC_PATCHLEVEL__)
#else
#define BUILD_COMPILER "Unknown"
#endif
Expand All @@ -26,6 +24,8 @@
#define TARGET_ARCH_STRING "arm64"
#elif defined(TARGET_LOONGARCH64)
#define TARGET_ARCH_STRING "loongarch64"
#elif defined(TARGET_RISCV64)
#define TARGET_ARCH_STRING "riscv64"
#else
#define TARGET_ARCH_STRING "Unknown"
#endif
Expand Down
93 changes: 65 additions & 28 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -927,37 +927,24 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd,
howToReturnStruct = SPK_ByReference;
useType = TYP_UNKNOWN;
}
#elif defined(TARGET_LOONGARCH64)
#elif defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
if (structSize <= (TARGET_POINTER_SIZE * 2))
{
uint32_t floatFieldFlags = info.compCompHnd->getLoongArch64PassStructInRegisterFlags(clsHnd);

if ((floatFieldFlags & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0)
{
howToReturnStruct = SPK_PrimitiveType;
useType = (structSize > 4) ? TYP_DOUBLE : TYP_FLOAT;
}
else if (floatFieldFlags & (STRUCT_HAS_FLOAT_FIELDS_MASK ^ STRUCT_FLOAT_FIELD_ONLY_ONE))
{
howToReturnStruct = SPK_ByValue;
useType = TYP_STRUCT;
}
}

#elif defined(TARGET_RISCV64)
if (structSize <= (TARGET_POINTER_SIZE * 2))
{
uint32_t floatFieldFlags = info.compCompHnd->getRISCV64PassStructInRegisterFlags(clsHnd);

if ((floatFieldFlags & STRUCT_FLOAT_FIELD_ONLY_ONE) != 0)
{
howToReturnStruct = SPK_PrimitiveType;
useType = (structSize > 4) ? TYP_DOUBLE : TYP_FLOAT;
}
else if (floatFieldFlags & (STRUCT_HAS_FLOAT_FIELDS_MASK ^ STRUCT_FLOAT_FIELD_ONLY_ONE))
const CORINFO_FPSTRUCT_LOWERING* lowering = GetFpStructLowering(clsHnd);
if (!lowering->byIntegerCallConv)
{
howToReturnStruct = SPK_ByValue;
useType = TYP_STRUCT;
if (lowering->numLoweredElements == 1)
{
useType = JITtype2varType(lowering->loweredElements[0]);
assert(varTypeIsFloating(useType));
howToReturnStruct = SPK_PrimitiveType;
}
else
{
assert(lowering->numLoweredElements == 2);
howToReturnStruct = SPK_ByValue;
useType = TYP_STRUCT;
}
}
}

Expand Down Expand Up @@ -1998,6 +1985,9 @@ void Compiler::compInit(ArenaAllocator* pAlloc,
#ifdef SWIFT_SUPPORT
m_swiftLoweringCache = nullptr;
#endif
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
m_fpStructLoweringCache = nullptr;
#endif

// check that HelperCallProperties are initialized

Expand Down Expand Up @@ -8301,6 +8291,53 @@ void Compiler::GetStructTypeOffset(
GetStructTypeOffset(structDesc, type0, type1, offset0, offset1);
}

#elif defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
//------------------------------------------------------------------------
// GetFpStructLowering: Gets the information on passing of a struct according to hardware floating-point
// calling convention, i.e. the types and offsets of struct fields lowered for passing.
//
// Arguments:
// structHandle - type handle
//
// Return value:
// Lowering info for the struct fields
const CORINFO_FPSTRUCT_LOWERING* Compiler::GetFpStructLowering(CORINFO_CLASS_HANDLE structHandle)
{
if (m_fpStructLoweringCache == nullptr)
m_fpStructLoweringCache = new (this, CMK_CallArgs) FpStructLoweringMap(getAllocator(CMK_CallArgs));

CORINFO_FPSTRUCT_LOWERING* lowering;
if (!m_fpStructLoweringCache->Lookup(structHandle, &lowering))
{
lowering = new (this, CMK_CallArgs) CORINFO_FPSTRUCT_LOWERING;
info.compCompHnd->getFpStructLowering(structHandle, lowering);
m_fpStructLoweringCache->Set(structHandle, lowering);
#ifdef DEBUG
if (verbose)
{
printf("**** getFpStructInRegistersInfo(0x%x (%s, %u bytes)) =>\n", dspPtr(structHandle),
eeGetClassName(structHandle), info.compCompHnd->getClassSize(structHandle));

if (lowering->byIntegerCallConv)
{
printf(" pass by integer calling convention\n");
}
else
{
printf(" may be passed by floating-point calling convention (%zu fields):\n",
lowering->numLoweredElements);
for (size_t i = 0; i < lowering->numLoweredElements; ++i)
{
const char* type = varTypeName(JITtype2varType(lowering->loweredElements[i]));
printf(" * field[%zu]: type %s at offset %u\n", i, type, lowering->offsets[i]);
}
}
}
#endif // DEBUG
}
return lowering;
}

#endif // defined(UNIX_AMD64_ABI)

/*****************************************************************************/
Expand Down
19 changes: 8 additions & 11 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,17 +561,9 @@ class LclVarDsc
unsigned char lvIsLastUseCopyOmissionCandidate : 1;
#endif // FEATURE_IMPLICIT_BYREFS

#if defined(TARGET_LOONGARCH64)
unsigned char lvIs4Field1 : 1; // Set if the 1st field is int or float within struct for LA-ABI64.
unsigned char lvIs4Field2 : 1; // Set if the 2nd field is int or float within struct for LA-ABI64.
unsigned char lvIsSplit : 1; // Set if the argument is splited.
#endif // defined(TARGET_LOONGARCH64)

#if defined(TARGET_RISCV64)
unsigned char lvIs4Field1 : 1; // Set if the 1st field is int or float within struct for RISCV64.
unsigned char lvIs4Field2 : 1; // Set if the 2nd field is int or float within struct for RISCV64.
unsigned char lvIsSplit : 1; // Set if the argument is splited.
#endif // defined(TARGET_RISCV64)
#if defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
unsigned char lvIsSplit : 1; // Set if the argument is split across last integer register and stack.
#endif // defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)

unsigned char lvSingleDef : 1; // variable has a single def. Used to identify ref type locals that can get type
// updates
Expand Down Expand Up @@ -11492,6 +11484,11 @@ class Compiler
void GetStructTypeOffset(
CORINFO_CLASS_HANDLE typeHnd, var_types* type0, var_types* type1, uint8_t* offset0, uint8_t* offset1);

#elif defined(TARGET_RISCV64) || defined(TARGET_LOONGARCH64)
typedef JitHashTable<CORINFO_CLASS_HANDLE, JitPtrKeyFuncs<struct CORINFO_CLASS_STRUCT_>, CORINFO_FPSTRUCT_LOWERING*>
FpStructLoweringMap;
FpStructLoweringMap* m_fpStructLoweringCache;
const CORINFO_FPSTRUCT_LOWERING* GetFpStructLowering(CORINFO_CLASS_HANDLE structHandle);
#endif // defined(UNIX_AMD64_ABI)

void fgMorphMultiregStructArgs(GenTreeCall* call);
Expand Down
46 changes: 19 additions & 27 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29532,37 +29532,29 @@ void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp,

#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
assert((structSize >= TARGET_POINTER_SIZE) && (structSize <= (2 * TARGET_POINTER_SIZE)));

#ifdef TARGET_LOONGARCH64
uint32_t floatFieldFlags = comp->info.compCompHnd->getLoongArch64PassStructInRegisterFlags(retClsHnd);
#else
uint32_t floatFieldFlags = comp->info.compCompHnd->getRISCV64PassStructInRegisterFlags(retClsHnd);
#endif
BYTE gcPtrs[2] = {TYPE_GC_NONE, TYPE_GC_NONE};
comp->info.compCompHnd->getClassGClayout(retClsHnd, &gcPtrs[0]);

if (floatFieldFlags & STRUCT_FLOAT_FIELD_ONLY_TWO)
{
comp->compFloatingPointUsed = true;
assert((structSize > 8) == ((floatFieldFlags & STRUCT_HAS_8BYTES_FIELDS_MASK) > 0));
m_regType[0] = (floatFieldFlags & STRUCT_FIRST_FIELD_SIZE_IS8) ? TYP_DOUBLE : TYP_FLOAT;
m_regType[1] = (floatFieldFlags & STRUCT_SECOND_FIELD_SIZE_IS8) ? TYP_DOUBLE : TYP_FLOAT;
}
else if (floatFieldFlags & STRUCT_FLOAT_FIELD_FIRST)
{
comp->compFloatingPointUsed = true;
assert((structSize > 8) == ((floatFieldFlags & STRUCT_HAS_8BYTES_FIELDS_MASK) > 0));
m_regType[0] = (floatFieldFlags & STRUCT_FIRST_FIELD_SIZE_IS8) ? TYP_DOUBLE : TYP_FLOAT;
m_regType[1] =
(floatFieldFlags & STRUCT_SECOND_FIELD_SIZE_IS8) ? comp->getJitGCType(gcPtrs[1]) : TYP_INT;
}
else if (floatFieldFlags & STRUCT_FLOAT_FIELD_SECOND)
const CORINFO_FPSTRUCT_LOWERING* lowering = comp->GetFpStructLowering(retClsHnd);
if (!lowering->byIntegerCallConv)
{
comp->compFloatingPointUsed = true;
assert((structSize > 8) == ((floatFieldFlags & STRUCT_HAS_8BYTES_FIELDS_MASK) > 0));
m_regType[0] =
(floatFieldFlags & STRUCT_FIRST_FIELD_SIZE_IS8) ? comp->getJitGCType(gcPtrs[0]) : TYP_INT;
m_regType[1] = (floatFieldFlags & STRUCT_SECOND_FIELD_SIZE_IS8) ? TYP_DOUBLE : TYP_FLOAT;
assert(lowering->numLoweredElements == MAX_RET_REG_COUNT);
var_types types[MAX_RET_REG_COUNT] = {JITtype2varType(lowering->loweredElements[0]),
JITtype2varType(lowering->loweredElements[1])};
assert(varTypeIsFloating(types[0]) || varTypeIsFloating(types[1]));
assert((structSize > 8) == ((genTypeSize(types[0]) == 8) || (genTypeSize(types[1]) == 8)));
for (unsigned i = 0; i < MAX_RET_REG_COUNT; ++i)
{
if (varTypeIsFloating(types[i]))
{
m_regType[i] = types[i];
}
else
{
assert(varTypeIsIntegralOrI(types[i]));
m_regType[i] = (genTypeSize(types[i]) == 8) ? comp->getJitGCType(gcPtrs[i]) : TYP_INT;
}
}
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -4544,7 +4544,7 @@ struct CallArgABIInformation
SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR StructDesc;
#endif // UNIX_AMD64_ABI
#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
// For LoongArch64's ABI, the struct which has float field(s) and no more than two fields
// For LoongArch64's and RISC-V 64's ABI, the struct which has float field(s) and no more than two fields
// may be passed by float register(s).
// e.g `struct {int a; float b;}` passed by an integer register and a float register.
var_types StructFloatFieldType[2];
Expand Down
Loading
Loading