Skip to content

Commit e6c5bb4

Browse files
authored
JIT: Use precise multireg arg check for old promotion (#112883)
`lvaIsMultiregStruct` does not account for whether the argument was _actually_ passed in multiple regs, it just checks if the type is a type that could sometimes be passed in multiple registers. Change this to a precise check.
1 parent 22fc451 commit e6c5bb4

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

src/coreclr/jit/compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4435,6 +4435,7 @@ class Compiler
44354435
void PromoteStructVar(unsigned lclNum);
44364436
void SortStructFields();
44374437
bool IsArmHfaParameter(unsigned lclNum);
4438+
bool IsSysVMultiRegType(ClassLayout* layout);
44384439

44394440
var_types TryPromoteValueClassAsPrimitive(CORINFO_TYPE_LAYOUT_NODE* treeNodes, size_t maxTreeNodes, size_t index);
44404441
void AdvanceSubTree(CORINFO_TYPE_LAYOUT_NODE* treeNodes, size_t maxTreeNodes, size_t* index);

src/coreclr/jit/lclvars.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2634,6 +2634,28 @@ bool Compiler::StructPromotionHelper::IsArmHfaParameter(unsigned lclNum)
26342634
return hfaType != CORINFO_HFA_ELEM_NONE;
26352635
}
26362636

2637+
//--------------------------------------------------------------------------------------------
2638+
// IsSysVMultiRegType - Check if a type is one that could be passed in 2
2639+
// registers in some cases.
2640+
// This is a quirk to match old promotion behavior.
2641+
//
2642+
// Arguments:
2643+
// lclNum - The local
2644+
//
2645+
// Return value:
2646+
// True if it sometimes may be passed in two registers.
2647+
//
2648+
bool Compiler::StructPromotionHelper::IsSysVMultiRegType(ClassLayout* layout)
2649+
{
2650+
#ifdef UNIX_AMD64_ABI
2651+
SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
2652+
compiler->eeGetSystemVAmd64PassStructInRegisterDescriptor(layout->GetClassHandle(), &structDesc);
2653+
return structDesc.passedInRegisters && (structDesc.eightByteCount == 2);
2654+
#else
2655+
return false;
2656+
#endif
2657+
}
2658+
26372659
//--------------------------------------------------------------------------------------------
26382660
// ShouldPromoteStructVar - Should a struct var be promoted if it can be promoted?
26392661
// This routine mainly performs profitability checks. Right now it also has
@@ -2693,10 +2715,10 @@ bool Compiler::StructPromotionHelper::ShouldPromoteStructVar(unsigned lclNum)
26932715
#if FEATURE_MULTIREG_STRUCT_PROMOTE
26942716
// Is this a variable holding a value with exactly two fields passed in
26952717
// multiple registers?
2696-
if (compiler->lvaIsMultiregStruct(varDsc, compiler->info.compIsVarArgs))
2718+
if (varDsc->lvIsMultiRegArg || IsSysVMultiRegType(varDsc->GetLayout()))
26972719
{
26982720
if ((structPromotionInfo.fieldCnt != 2) &&
2699-
!((structPromotionInfo.fieldCnt == 1) && varTypeIsSIMD(structPromotionInfo.fields[0].fldType)))
2721+
((structPromotionInfo.fieldCnt != 1) || !varTypeIsSIMD(structPromotionInfo.fields[0].fldType)))
27002722
{
27012723
JITDUMP("Not promoting multireg struct local V%02u, because lvIsParam is true, #fields != 2 and it's "
27022724
"not a single SIMD.\n",
@@ -2713,6 +2735,7 @@ bool Compiler::StructPromotionHelper::ShouldPromoteStructVar(unsigned lclNum)
27132735
}
27142736
else
27152737
#endif // !FEATURE_MULTIREG_STRUCT_PROMOTE
2738+
{
27162739

27172740
// TODO-PERF - Implement struct promotion for incoming single-register structs.
27182741
// Also the implementation of jmp uses the 4 byte move to store
@@ -2726,6 +2749,7 @@ bool Compiler::StructPromotionHelper::ShouldPromoteStructVar(unsigned lclNum)
27262749
lclNum, structPromotionInfo.fieldCnt);
27272750
shouldPromote = false;
27282751
}
2752+
}
27292753
}
27302754
else if ((lclNum == compiler->genReturnLocal) && (structPromotionInfo.fieldCnt > 1))
27312755
{

0 commit comments

Comments
 (0)