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

Implement DivRem intrinsic for X86 #66551

Merged
merged 85 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
00da1f4
Add managed api for divrem
huoyaoyuan Mar 7, 2022
d679cca
Add NI definition of DivRem
huoyaoyuan Mar 7, 2022
4eba5c5
Fix DivRem to be static
huoyaoyuan Mar 11, 2022
6f8fbbf
Implement DivRem in clrjit
huoyaoyuan Mar 11, 2022
997d8a5
Add tests for DivRem
huoyaoyuan Mar 11, 2022
c0c3dd6
Adjust lsra and RMW
huoyaoyuan Mar 12, 2022
c08cee7
Use DivRem intrinsic in Math
huoyaoyuan Mar 12, 2022
1804350
Bring lower change from coreclr#37928
huoyaoyuan Mar 12, 2022
46c3f78
Fix signedness of DIV
huoyaoyuan Mar 13, 2022
2dbd2e9
Revert RMW change and fix reg allocation
huoyaoyuan Mar 13, 2022
1b6d09b
Fix import of X64 intrinsic
huoyaoyuan Mar 13, 2022
3ef3600
Fix static in PNSE version
huoyaoyuan Mar 13, 2022
acaf211
Fix accidential indent change
huoyaoyuan Mar 13, 2022
728440d
Apply format patch
huoyaoyuan Mar 13, 2022
4eace5d
op3 candidate should be different from op1 and op2
huoyaoyuan Mar 13, 2022
3182ed8
Add guard over AsHWIntrinsic
huoyaoyuan Mar 14, 2022
48c12a4
Disable DivRem intrinsic use for Mono
huoyaoyuan Mar 14, 2022
be5b33c
Fix LSRA and invalid assertion
huoyaoyuan Mar 15, 2022
d868194
Set RWM information correctly, although totally unused.
huoyaoyuan Mar 15, 2022
ff65608
Move multi-reg temp allocation to common helper
huoyaoyuan Mar 15, 2022
b31f896
Disable DivRem intrinsic test for Mono.
huoyaoyuan Mar 16, 2022
0bd1327
Fix typo of quotient
huoyaoyuan Mar 23, 2022
51959c0
Merge branch 'main'
huoyaoyuan May 20, 2022
8f1d9a2
Merge branch 'main' into divrem
huoyaoyuan Jun 8, 2022
f4aece2
Merge branch 'main'
huoyaoyuan Jul 15, 2022
75dda8d
Merge branch 'main' into divrem
huoyaoyuan Sep 18, 2022
43049a9
Use impAssignMultiRegTypeToVar
huoyaoyuan Sep 19, 2022
d485b61
Update #ifdef
huoyaoyuan Sep 19, 2022
aeb114a
Remove change in LowerBlockStore
huoyaoyuan Sep 19, 2022
aa57f26
Adjust assert and helper method
huoyaoyuan Sep 23, 2022
9345e57
Update CheckMultiRegLclVar
huoyaoyuan Sep 23, 2022
65c0af6
fix build errors
kunalspathak Sep 23, 2022
2bfa332
Merge branch 'main' into divrem
huoyaoyuan Sep 24, 2022
7b41fd6
Merge remote-tracking branch 'origin/main' into pr-66551
kunalspathak Nov 7, 2022
df922de
Fix some merge conflicts
kunalspathak Nov 7, 2022
924fc42
Fix some errors
kunalspathak Nov 7, 2022
1e7ff05
Fix GCC build error
kunalspathak Nov 8, 2022
62e6c59
jit format
kunalspathak Nov 8, 2022
a1b4802
Make the size depending on the struct
kunalspathak Nov 8, 2022
d547337
Merge remote-tracking branch 'origin/main' into divrem
kunalspathak Dec 5, 2022
8199acb
Fix the formatting of summary
kunalspathak Dec 6, 2022
ed12edb
Remove trailing spaces
kunalspathak Dec 7, 2022
532a8fd
Fix the tests to adopt new model
kunalspathak Dec 7, 2022
281c1b0
Fix MAX_RET_REG_COUNT -> MAX_MULTIREG_COUNT
kunalspathak Dec 8, 2022
97630a2
Exclude from mono run
kunalspathak Dec 9, 2022
491f82e
Add RequiresProcessIsolation
kunalspathak Dec 12, 2022
7487dfc
Merge remote-tracking branch 'origin/main' into divrem
kunalspathak Dec 28, 2022
7a862b2
Merge remote-tracking branch 'origin/main' into divrem
kunalspathak Jan 6, 2023
0fc11c9
Real fix for build break
kunalspathak Jan 7, 2023
8ab6023
Fix the test cases to adopt to the new system
kunalspathak Jan 11, 2023
8d67890
Disable for llvm-fullaot
kunalspathak Jan 12, 2023
0d85848
Also continue disabling for mono
kunalspathak Jan 12, 2023
1fd2b74
Merge remote-tracking branch 'origin/main' into divrem
kunalspathak Jan 12, 2023
18c9787
Disable the test in a different group
kunalspathak Jan 12, 2023
b63dea3
Merge remote-tracking branch 'origin/main' into divrem
kunalspathak Jan 13, 2023
1b0e670
fix merge conflict
kunalspathak Jan 13, 2023
7631033
format
kunalspathak Jan 13, 2023
c0be00a
fix another merge conflict error
kunalspathak Jan 14, 2023
83192b1
Merge remote-tracking branch 'origin/main' into divrem
kunalspathak Jan 17, 2023
b29e1b4
misc changes from review
kunalspathak Jan 17, 2023
82c38a3
fix the replay errors
kunalspathak Jan 18, 2023
61fabe2
jit format
kunalspathak Jan 18, 2023
eea804c
Add exclude list in mono/llvmfullaot
kunalspathak Jan 18, 2023
ebe8781
Review feedback and fix bug in CheckMultiRegLclVar
kunalspathak Jan 20, 2023
9dc8522
Pass registerCount
kunalspathak Jan 20, 2023
0093b79
review feedback
kunalspathak Jan 20, 2023
8260134
Remove the extra comments
kunalspathak Jan 24, 2023
320270a
Disable tests on mono llvmfullaot runs as well
akoeplinger Jan 24, 2023
a98dbde
Add missing case for upper save/restore
kunalspathak Jan 24, 2023
06f0460
Add missing RequiresProcessIsolation
kunalspathak Jan 25, 2023
1b3e851
Revert "Add missing case for upper save/restore"
kunalspathak Jan 25, 2023
9f192ac
Merge remote-tracking branch 'huoyaoyuan/divrem' into divrem
kunalspathak Jan 25, 2023
537f678
Remove RequiresProcessIsolation property
kunalspathak Jan 25, 2023
ca32b24
Merge branch 'main' into divrem
kunalspathak Feb 9, 2023
e1b5fb3
Replace ref with fakelibs
kunalspathak Feb 9, 2023
6589700
Add references of fakelib to test project
kunalspathak Feb 10, 2023
2a90b4b
Fix CompatibilitySuppressions.xml
kunalspathak Feb 10, 2023
aad300a
fix test builds
kunalspathak Feb 10, 2023
eb3272c
Remove unneeded extern/using
kunalspathak Feb 10, 2023
39ae98d
Revert "Replace ref with fakelibs"
kunalspathak Feb 13, 2023
f8473ec
Revert "Revert "Replace ref with fakelibs""
kunalspathak Feb 13, 2023
e00a8c1
Exclude DivRem.csproj
kunalspathak Feb 14, 2023
9e28279
Handle the case to delay-free op3 for op1/op2
kunalspathak Feb 14, 2023
2d4d8d9
Create the DivRem.RefOnly fake CoreLib as a reference assembly
kunalspathak Feb 14, 2023
b5e3dd3
Unify AddDelayFreeUses
kunalspathak Feb 15, 2023
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
21 changes: 21 additions & 0 deletions src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Internal.Console</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:System.Runtime.CompilerServices.ICastable</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>F:System.Resources.ResourceManager.BaseNameField</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>F:System.Resources.ResourceSet.Reader</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0014</DiagnosticId>
<Target>M:System.Runtime.InteropServices.Marshal.CreateWrapperOfType(System.Object,System.Type)-&gt;object?:[T:System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute]</Target>
</Suppression>
</Suppressions>
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3925,6 +3925,7 @@ class Compiler
GenTree* addRangeCheckIfNeeded(
NamedIntrinsic intrinsic, GenTree* immOp, bool mustExpand, int immLowerBound, int immUpperBound);
GenTree* addRangeCheckForHWIntrinsic(GenTree* immOp, int immLowerBound, int immUpperBound);

#endif // FEATURE_HW_INTRINSICS
GenTree* impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd,
CORINFO_SIG_INFO* sig,
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19090,6 +19090,8 @@ bool GenTree::isRMWHWIntrinsic(Compiler* comp)
case NI_FMA_MultiplySubtractNegated:
case NI_FMA_MultiplySubtractNegatedScalar:
case NI_FMA_MultiplySubtractScalar:
case NI_X86Base_DivRem:
case NI_X86Base_X64_DivRem:
{
return true;
}
Expand Down Expand Up @@ -23943,6 +23945,12 @@ ClassLayout* GenTreeHWIntrinsic::GetLayout(Compiler* compiler) const

switch (GetHWIntrinsicId())
{
#ifdef TARGET_XARCH
case NI_X86Base_DivRem:
tannergooding marked this conversation as resolved.
Show resolved Hide resolved
return compiler->typGetBlkLayout(genTypeSize(GetSimdBaseType()) * 2);
case NI_X86Base_X64_DivRem:
return compiler->typGetBlkLayout(16);
#endif // TARGET_XARCH
#ifdef TARGET_ARM64
case NI_AdvSimd_Arm64_LoadPairScalarVector64:
case NI_AdvSimd_Arm64_LoadPairScalarVector64NonTemporal:
Expand Down
24 changes: 13 additions & 11 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3683,8 +3683,8 @@ static const unsigned PACKED_GTF_SPILLED = 2;
//
inline GenTreeFlags GetMultiRegSpillFlagsByIdx(MultiRegSpillFlags flags, unsigned idx)
{
static_assert_no_msg(MAX_RET_REG_COUNT * 2 <= sizeof(unsigned char) * BITS_PER_BYTE);
assert(idx < MAX_RET_REG_COUNT);
static_assert_no_msg(MAX_MULTIREG_COUNT * 2 <= sizeof(unsigned char) * BITS_PER_BYTE);
assert(idx < MAX_MULTIREG_COUNT);

unsigned bits = flags >> (idx * 2); // It doesn't matter that we possibly leave other high bits here.
GenTreeFlags spillFlags = GTF_EMPTY;
Expand Down Expand Up @@ -3715,8 +3715,8 @@ inline GenTreeFlags GetMultiRegSpillFlagsByIdx(MultiRegSpillFlags flags, unsigne
//
inline MultiRegSpillFlags SetMultiRegSpillFlagsByIdx(MultiRegSpillFlags oldFlags, GenTreeFlags flagsToSet, unsigned idx)
{
static_assert_no_msg(MAX_RET_REG_COUNT * 2 <= sizeof(unsigned char) * BITS_PER_BYTE);
assert(idx < MAX_RET_REG_COUNT);
static_assert_no_msg(MAX_MULTIREG_COUNT * 2 <= sizeof(unsigned char) * BITS_PER_BYTE);
assert(idx < MAX_MULTIREG_COUNT);

MultiRegSpillFlags newFlags = oldFlags;
unsigned bits = 0;
Expand Down Expand Up @@ -8057,7 +8057,7 @@ struct GenTreeCopyOrReload : public GenTreeUnOp
// State required to support copy/reload of a multi-reg call node.
// The first register is always given by GetRegNum().
//
regNumberSmall gtOtherRegs[MAX_RET_REG_COUNT - 1];
regNumberSmall gtOtherRegs[MAX_MULTIREG_COUNT - 1];
#endif

//----------------------------------------------------------
Expand All @@ -8072,7 +8072,7 @@ struct GenTreeCopyOrReload : public GenTreeUnOp
void ClearOtherRegs()
{
#if FEATURE_MULTIREG_RET
for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
for (unsigned i = 0; i < MAX_MULTIREG_COUNT - 1; ++i)
{
gtOtherRegs[i] = REG_NA;
}
Expand All @@ -8090,7 +8090,7 @@ struct GenTreeCopyOrReload : public GenTreeUnOp
//
regNumber GetRegNumByIdx(unsigned idx) const
{
assert(idx < MAX_RET_REG_COUNT);
assert(idx < MAX_MULTIREG_COUNT);

if (idx == 0)
{
Expand All @@ -8116,7 +8116,7 @@ struct GenTreeCopyOrReload : public GenTreeUnOp
//
void SetRegNumByIdx(regNumber reg, unsigned idx)
{
assert(idx < MAX_RET_REG_COUNT);
assert(idx < MAX_MULTIREG_COUNT);

if (idx == 0)
{
Expand Down Expand Up @@ -8153,7 +8153,7 @@ struct GenTreeCopyOrReload : public GenTreeUnOp
assert(OperGet() == from->OperGet());

#ifdef UNIX_AMD64_ABI
for (unsigned i = 0; i < MAX_RET_REG_COUNT - 1; ++i)
for (unsigned i = 0; i < MAX_MULTIREG_COUNT - 1; ++i)
{
gtOtherRegs[i] = from->gtOtherRegs[i];
}
Expand All @@ -8170,7 +8170,7 @@ struct GenTreeCopyOrReload : public GenTreeUnOp
// but for COPY or RELOAD there is only a valid register for the register positions
// that must be copied or reloaded.
//
for (unsigned i = MAX_RET_REG_COUNT; i > 1; i--)
for (unsigned i = MAX_MULTIREG_COUNT; i > 1; i--)
{
if (gtOtherRegs[i - 2] != REG_NA)
{
Expand Down Expand Up @@ -9166,6 +9166,7 @@ inline var_types GenTree::GetRegTypeByIndex(int regIndex) const
#endif // !defined(TARGET_64BIT)
#endif // FEATURE_MULTIREG_RET

#ifdef FEATURE_HW_INTRINSICS
if (OperIsHWIntrinsic())
{
assert(TypeGet() == TYP_STRUCT);
Expand All @@ -9182,9 +9183,10 @@ inline var_types GenTree::GetRegTypeByIndex(int regIndex) const
#elif defined(TARGET_XARCH)
// At this time, the only multi-reg HW intrinsics all return the type of their
// arguments. If this changes, we will need a way to record or determine this.
return gtGetOp1()->TypeGet();
return AsHWIntrinsic()->Op(1)->TypeGet();
tannergooding marked this conversation as resolved.
Show resolved Hide resolved
#endif
}
#endif // FEATURE_HW_INTRINSICS

if (OperIsScalarLocal())
{
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/hwintrinsic.h
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,12 @@ struct HWIntrinsicInfo
return 2;
#endif

#ifdef TARGET_XARCH
case NI_X86Base_DivRem:
case NI_X86Base_X64_DivRem:
return 2;
#endif // TARGET_XARCH

default:
unreached();
}
Expand Down
37 changes: 37 additions & 0 deletions src/coreclr/jit/hwintrinsiccodegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,43 @@ void CodeGen::genX86BaseIntrinsic(GenTreeHWIntrinsic* node)
break;
}

case NI_X86Base_DivRem:
case NI_X86Base_X64_DivRem:
{
assert(node->GetOperandCount() == 3);

// SIMD base type is from signature and can distinguish signed and unsigned
var_types targetType = node->GetSimdBaseType();
GenTree* op1 = node->Op(1);
GenTree* op2 = node->Op(2);
GenTree* op3 = node->Op(3);
instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, targetType);

regNumber op1Reg = op1->GetRegNum();
regNumber op2Reg = op2->GetRegNum();
regNumber op3Reg = op3->GetRegNum();

emitAttr attr = emitTypeSize(targetType);
emitter* emit = GetEmitter();

// op1: EAX, op2: EDX, op3: free
kunalspathak marked this conversation as resolved.
Show resolved Hide resolved
assert(op1Reg != REG_EDX);
assert(op2Reg != REG_EAX);
if (op3->isUsedFromReg())
{
assert(op3Reg != REG_EDX);
assert(op3Reg != REG_EAX);
}

emit->emitIns_Mov(INS_mov, attr, REG_EAX, op1Reg, /* canSkip */ true);
emit->emitIns_Mov(INS_mov, attr, REG_EDX, op2Reg, /* canSkip */ true);

// emit the DIV/IDIV instruction
emit->emitInsBinary(ins, attr, node, op3);

break;
}

default:
unreached();
break;
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/hwintrinsiclistxarch.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ HARDWARE_INTRINSIC(Vector256, Xor,
HARDWARE_INTRINSIC(X86Base, BitScanForward, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsf, INS_bsf, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(X86Base, BitScanReverse, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsr, INS_bsr, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(X86Base, Pause, 0, 0, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(X86Base, DivRem, 0, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_idiv, INS_div, INS_idiv, INS_div, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_BaseTypeFromSecondArg|HW_Flag_MultiReg|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen)

// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// ISA Function name SIMD size NumArg Instructions Category Flags
Expand All @@ -246,6 +247,7 @@ HARDWARE_INTRINSIC(X86Base, Pause,
// X86Base 64-bit-only Intrinsics
HARDWARE_INTRINSIC(X86Base_X64, BitScanForward, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsf, INS_bsf, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(X86Base_X64, BitScanReverse, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsr, INS_bsr, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics)
HARDWARE_INTRINSIC(X86Base_X64, DivRem, 0, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_idiv, INS_div, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_BaseTypeFromSecondArg|HW_Flag_MultiReg|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen)

// ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
// ISA Function name SIMD size NumArg Instructions Category Flags
Expand Down
23 changes: 22 additions & 1 deletion src/coreclr/jit/hwintrinsicxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,6 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
}

var_types simdBaseType = TYP_UNKNOWN;

if (simdSize != 0)
{
simdBaseType = JitType2PreciseVarType(simdBaseJitType);
Expand Down Expand Up @@ -2366,6 +2365,28 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic,
break;
}

case NI_X86Base_DivRem:
case NI_X86Base_X64_DivRem:
{
assert(sig->numArgs == 3);
assert(HWIntrinsicInfo::IsMultiReg(intrinsic));
assert(retType == TYP_STRUCT);
assert(simdBaseJitType != CORINFO_TYPE_UNDEF);

op3 = impPopStack().val;
op2 = impPopStack().val;
op1 = impPopStack().val;

GenTreeHWIntrinsic* divRemIntrinsic = gtNewScalarHWIntrinsicNode(retType, op1, op2, op3, intrinsic);

// Store the type from signature into SIMD base type for convenience
divRemIntrinsic->SetSimdBaseJitType(simdBaseJitType);

retNode = impAssignMultiRegTypeToVar(divRemIntrinsic,
sig->retTypeSigClass DEBUGARG(CorInfoCallConvExtension::Managed));
break;
}

case NI_SSE_CompareScalarGreaterThan:
case NI_SSE_CompareScalarGreaterThanOrEqual:
case NI_SSE_CompareScalarNotGreaterThan:
Expand Down
13 changes: 8 additions & 5 deletions src/coreclr/jit/importer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11009,16 +11009,19 @@ GenTree* Compiler::impAssignMultiRegTypeToVar(GenTree* op,
{
unsigned tmpNum = lvaGrabTemp(true DEBUGARG("Return value temp for multireg return"));
impAssignTempGen(tmpNum, op, hClass, CHECK_SPILL_ALL);
GenTree* ret = gtNewLclvNode(tmpNum, lvaTable[tmpNum].lvType);

LclVarDsc* varDsc = lvaGetDesc(tmpNum);

// Set "lvIsMultiRegRet" to block promotion under "!lvaEnregMultiRegVars".
varDsc->lvIsMultiRegRet = true;

GenTreeLclVar* ret = gtNewLclvNode(tmpNum, varDsc->lvType);

// TODO-1stClassStructs: Handle constant propagation and CSE-ing of multireg returns.
ret->gtFlags |= GTF_DONT_CSE;
ret->SetDoNotCSE();

assert(IsMultiRegReturnedType(hClass, callConv) || op->IsMultiRegNode());

// Set "lvIsMultiRegRet" to block promotion under "!lvaEnregMultiRegVars".
lvaTable[tmpNum].lvIsMultiRegRet = true;

return ret;
}

Expand Down
Loading