From 39a4204d3525114836fd98d0572369065b812ade Mon Sep 17 00:00:00 2001 From: Steven He Date: Wed, 29 Jan 2025 17:00:52 +0900 Subject: [PATCH 01/15] Teach the JIT about System.SZArrayHelper.GetEnumerator --- src/coreclr/jit/fgbasic.cpp | 2 ++ src/coreclr/jit/fginline.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index a34e2622157ba3..68a8894f5b46ae 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -3562,6 +3562,8 @@ void Compiler::fgFindBasicBlocks() lvaSetClass(lvaInlineeReturnSpillTemp, retClassHnd); } } + + impInlineInfo->inlineCandidateInfo->preexistingSpillTemp = lvaInlineeReturnSpillTemp; } } diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index ba55f989961d8d..32aac52271c1d1 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -1416,6 +1416,24 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineRe // Let's insert it to inliner's basic block list. fgInsertInlineeBlocks(&inlineInfo); + // If we are inlining System.SZArrayHelper.GetEnumerator, mark the temp as single def to allow updating + // class. This can enable further devirtualization and inlining of MoveNext, get_Current and Dispose + // methods. + if (lookupNamedIntrinsic(inlineInfo.fncHandle) == NI_System_SZArrayHelper_GetEnumerator && + inlineInfo.inlineCandidateInfo->preexistingSpillTemp != BAD_VAR_NUM) + { + lvaGetDesc(inlineInfo.inlineCandidateInfo->preexistingSpillTemp)->lvSingleDef = 1; + +#ifdef DEBUG + if (verbose) + { + printf( + "\nInlinee is System.SZArrayHelper.GetEnumerator, mark the return spilling local V%02u as single def.\n", + inlineInfo.inlineCandidateInfo->preexistingSpillTemp); + } +#endif // DEBUG + } + #ifdef DEBUG if (verbose) From 6ec367f7b33f039de74a53f07c82c7551d1c17f0 Mon Sep 17 00:00:00 2001 From: Steven He Date: Wed, 29 Jan 2025 18:23:54 +0900 Subject: [PATCH 02/15] A better approach --- src/coreclr/jit/fginline.cpp | 18 ------------------ src/coreclr/jit/fgopt.cpp | 19 +++++++++++++++++-- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index 32aac52271c1d1..ba55f989961d8d 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -1416,24 +1416,6 @@ void Compiler::fgInvokeInlineeCompiler(GenTreeCall* call, InlineResult* inlineRe // Let's insert it to inliner's basic block list. fgInsertInlineeBlocks(&inlineInfo); - // If we are inlining System.SZArrayHelper.GetEnumerator, mark the temp as single def to allow updating - // class. This can enable further devirtualization and inlining of MoveNext, get_Current and Dispose - // methods. - if (lookupNamedIntrinsic(inlineInfo.fncHandle) == NI_System_SZArrayHelper_GetEnumerator && - inlineInfo.inlineCandidateInfo->preexistingSpillTemp != BAD_VAR_NUM) - { - lvaGetDesc(inlineInfo.inlineCandidateInfo->preexistingSpillTemp)->lvSingleDef = 1; - -#ifdef DEBUG - if (verbose) - { - printf( - "\nInlinee is System.SZArrayHelper.GetEnumerator, mark the return spilling local V%02u as single def.\n", - inlineInfo.inlineCandidateInfo->preexistingSpillTemp); - } -#endif // DEBUG - } - #ifdef DEBUG if (verbose) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 6187274c70332f..98e2f0846dedd0 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -317,9 +317,24 @@ PhaseStatus Compiler::fgPostImportationCleanup() { LclVarDsc* returnSpillVarDsc = lvaGetDesc(lvaInlineeReturnSpillTemp); - if ((returnSpillVarDsc->lvType == TYP_REF) && returnSpillVarDsc->lvSingleDef) + if ((returnSpillVarDsc->lvType == TYP_REF)) { - lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, impInlineInfo->retExprClassHndIsExact); + if (returnSpillVarDsc->lvSingleDef) + { + lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, + impInlineInfo->retExprClassHndIsExact); + } + else if (lookupNamedIntrinsic(info.compMethodHnd) == NI_System_SZArrayHelper_GetEnumerator) + { + // If we are inlining System.SZArrayHelper.GetEnumerator, update the type of the return spill + // temp regardless of whether it is single def or not. + returnSpillVarDsc->lvType = TYP_REF; + returnSpillVarDsc->lvClassHnd = retExprClassHnd; + returnSpillVarDsc->lvClassIsExact = impInlineInfo->retExprClassHndIsExact; +#if DEBUG + returnSpillVarDsc->lvClassInfoUpdated = true; +#endif + } } } } From 126a04287d516a5f929b731ae12aee36759101bc Mon Sep 17 00:00:00 2001 From: Steven He Date: Wed, 29 Jan 2025 18:24:54 +0900 Subject: [PATCH 03/15] Format JIT --- src/coreclr/jit/fgopt.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 98e2f0846dedd0..6bd46ce1e5faeb 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -328,8 +328,7 @@ PhaseStatus Compiler::fgPostImportationCleanup() { // If we are inlining System.SZArrayHelper.GetEnumerator, update the type of the return spill // temp regardless of whether it is single def or not. - returnSpillVarDsc->lvType = TYP_REF; - returnSpillVarDsc->lvClassHnd = retExprClassHnd; + returnSpillVarDsc->lvClassHnd = retExprClassHnd; returnSpillVarDsc->lvClassIsExact = impInlineInfo->retExprClassHndIsExact; #if DEBUG returnSpillVarDsc->lvClassInfoUpdated = true; From 0e91fd0fd7e96e929eb32375e60201b471f04955 Mon Sep 17 00:00:00 2001 From: Steven He Date: Wed, 29 Jan 2025 18:44:08 +0900 Subject: [PATCH 04/15] Use lvaInlineeReturnSpillTempFreshlyCreated --- src/coreclr/jit/compiler.h | 2 ++ src/coreclr/jit/fgbasic.cpp | 2 +- src/coreclr/jit/fgopt.cpp | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 442dd8f17a5a24..dc5b00f176065d 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4091,6 +4091,8 @@ class Compiler unsigned lvaInlineeReturnSpillTemp = BAD_VAR_NUM; // The temp to spill the non-VOID return expression // in case there are multiple BBJ_RETURN blocks in the inlinee // or if the inlinee has GC ref locals. + + bool lvaInlineeReturnSpillTempFreshlyCreated = false; // True if the temp was freshly created for the inlinee return #if FEATURE_FIXED_OUT_ARGS unsigned lvaOutgoingArgSpaceVar = BAD_VAR_NUM; // var that represents outgoing argument space diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 68a8894f5b46ae..6772977aed91a4 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -3563,7 +3563,7 @@ void Compiler::fgFindBasicBlocks() } } - impInlineInfo->inlineCandidateInfo->preexistingSpillTemp = lvaInlineeReturnSpillTemp; + lvaInlineeReturnSpillTempFreshlyCreated = true; } } diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 6bd46ce1e5faeb..61c68d12d6aa80 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -324,10 +324,10 @@ PhaseStatus Compiler::fgPostImportationCleanup() lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, impInlineInfo->retExprClassHndIsExact); } - else if (lookupNamedIntrinsic(info.compMethodHnd) == NI_System_SZArrayHelper_GetEnumerator) + else if (lvaInlineeReturnSpillTempFreshlyCreated) { - // If we are inlining System.SZArrayHelper.GetEnumerator, update the type of the return spill - // temp regardless of whether it is single def or not. + // If the inlinee return spill temp was freshly created in fgFindBasicBlocks, we can update the + // type regardless of whether it is single def or not. returnSpillVarDsc->lvClassHnd = retExprClassHnd; returnSpillVarDsc->lvClassIsExact = impInlineInfo->retExprClassHndIsExact; #if DEBUG From c43cf22007ffb5f074d172a40bef17716667d0e8 Mon Sep 17 00:00:00 2001 From: Steve Date: Wed, 29 Jan 2025 18:53:05 +0900 Subject: [PATCH 05/15] Update src/coreclr/jit/fgopt.cpp Co-authored-by: Jakob Botsch Nielsen --- src/coreclr/jit/fgopt.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 61c68d12d6aa80..99f93d0003de23 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -319,21 +319,11 @@ PhaseStatus Compiler::fgPostImportationCleanup() if ((returnSpillVarDsc->lvType == TYP_REF)) { - if (returnSpillVarDsc->lvSingleDef) + if (returnSpillVarDsc->lvSingleDef || lvaInlineeReturnSpillTempFreshlyCreated) { lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, impInlineInfo->retExprClassHndIsExact); } - else if (lvaInlineeReturnSpillTempFreshlyCreated) - { - // If the inlinee return spill temp was freshly created in fgFindBasicBlocks, we can update the - // type regardless of whether it is single def or not. - returnSpillVarDsc->lvClassHnd = retExprClassHnd; - returnSpillVarDsc->lvClassIsExact = impInlineInfo->retExprClassHndIsExact; -#if DEBUG - returnSpillVarDsc->lvClassInfoUpdated = true; -#endif - } } } } From 1c45b3eee102ecf469f3bd9684c9d53fba31dae8 Mon Sep 17 00:00:00 2001 From: Steven He Date: Wed, 29 Jan 2025 18:53:22 +0900 Subject: [PATCH 06/15] Update assertion --- src/coreclr/jit/lclvars.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index ad9b203b454e3b..63bdd1d8ca61cb 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -3631,8 +3631,9 @@ void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool // We should already have a class assert(varDsc->lvClassHnd != NO_CLASS_HANDLE); - // We should only be updating classes for single-def locals. - assert(varDsc->lvSingleDef); + // We should only be updating classes for single-def locals, + // or for the inlinee return spill temp that is freshly created. + assert(varDsc->lvSingleDef || (lvaInlineeReturnSpillTempFreshlyCreated && varNum == lvaInlineeReturnSpillTemp)); // Now see if we should update. // @@ -3679,7 +3680,7 @@ void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool } //------------------------------------------------------------------------ -// lvaUpdateClass: Uupdate class information for a local var from a tree +// lvaUpdateClass: Update class information for a local var from a tree // or stack type // // Arguments: From 02c808b88ee022cb5df932f185306df41e22b685 Mon Sep 17 00:00:00 2001 From: Steven He Date: Wed, 29 Jan 2025 18:57:03 +0900 Subject: [PATCH 07/15] Nit --- src/coreclr/jit/fgopt.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 99f93d0003de23..3760b8745f4f51 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -317,13 +317,10 @@ PhaseStatus Compiler::fgPostImportationCleanup() { LclVarDsc* returnSpillVarDsc = lvaGetDesc(lvaInlineeReturnSpillTemp); - if ((returnSpillVarDsc->lvType == TYP_REF)) + if (returnSpillVarDsc->lvType == TYP_REF && + (returnSpillVarDsc->lvSingleDef || lvaInlineeReturnSpillTempFreshlyCreated)) { - if (returnSpillVarDsc->lvSingleDef || lvaInlineeReturnSpillTempFreshlyCreated) - { - lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, - impInlineInfo->retExprClassHndIsExact); - } + lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, impInlineInfo->retExprClassHndIsExact); } } } From 3ae7287345a7146535cfa416cffbb407613e234a Mon Sep 17 00:00:00 2001 From: Steven He Date: Wed, 29 Jan 2025 18:58:37 +0900 Subject: [PATCH 08/15] Nit --- src/coreclr/jit/lclvars.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 63bdd1d8ca61cb..3e6625f4c52a72 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -3632,7 +3632,7 @@ void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool assert(varDsc->lvClassHnd != NO_CLASS_HANDLE); // We should only be updating classes for single-def locals, - // or for the inlinee return spill temp that is freshly created. + // or for the inlinee return spill temps that are freshly created. assert(varDsc->lvSingleDef || (lvaInlineeReturnSpillTempFreshlyCreated && varNum == lvaInlineeReturnSpillTemp)); // Now see if we should update. From f5fd84ed6921519a0496e27ea32d98ae677abcfe Mon Sep 17 00:00:00 2001 From: Steven He Date: Thu, 30 Jan 2025 01:18:49 +0900 Subject: [PATCH 09/15] Address review feedbacks --- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/fgopt.cpp | 5 +++-- src/coreclr/jit/lclvars.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index dc5b00f176065d..bb24937e794faf 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4357,7 +4357,7 @@ class Compiler // If the local is TYP_REF, set or update the associated class information. void lvaSetClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false); void lvaSetClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE stackHandle = nullptr); - void lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false); + void lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false DEBUGARG(bool mustBeSingleDef = true)); void lvaUpdateClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE stackHandle = nullptr); #define MAX_NumOfFieldsInPromotableStruct 4 // Maximum number of fields in promotable struct diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 3760b8745f4f51..91ad0de4d8b62f 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -309,7 +309,7 @@ PhaseStatus Compiler::fgPostImportationCleanup() { // Update type of return spill temp if we have gathered // better info when importing the inlinee, and the return - // spill temp is single def. + // spill temp is single def or was freshly created for this inlinee if (fgNeedReturnSpillTemp()) { CORINFO_CLASS_HANDLE retExprClassHnd = impInlineInfo->retExprClassHnd; @@ -320,7 +320,8 @@ PhaseStatus Compiler::fgPostImportationCleanup() if (returnSpillVarDsc->lvType == TYP_REF && (returnSpillVarDsc->lvSingleDef || lvaInlineeReturnSpillTempFreshlyCreated)) { - lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, impInlineInfo->retExprClassHndIsExact); + lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, + impInlineInfo->retExprClassHndIsExact DEBUGARG(false)); } } } diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 3e6625f4c52a72..11d822e8654a21 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -3601,6 +3601,7 @@ void Compiler::lvaSetClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE // varNum -- number of the variable // clsHnd -- class handle to use in set or update // isExact -- true if class is known exactly +// mustBeSingleDef -- true if we should only update single-def locals // // Notes: // @@ -3618,7 +3619,7 @@ void Compiler::lvaSetClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE // for shared code, so ensuring this is so is currently not // possible. -void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact) +void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact DEBUGARG(bool mustBeSingleDef)) { assert(varNum < lvaCount); @@ -3631,9 +3632,8 @@ void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool // We should already have a class assert(varDsc->lvClassHnd != NO_CLASS_HANDLE); - // We should only be updating classes for single-def locals, - // or for the inlinee return spill temps that are freshly created. - assert(varDsc->lvSingleDef || (lvaInlineeReturnSpillTempFreshlyCreated && varNum == lvaInlineeReturnSpillTemp)); + // We should only be updating classes for single-def locals if requested + assert(!mustBeSingleDef || varDsc->lvSingleDef); // Now see if we should update. // From 22bd9cf32b8c6fa3ca24930fa312048caf6ff039 Mon Sep 17 00:00:00 2001 From: Steven He Date: Thu, 30 Jan 2025 01:32:03 +0900 Subject: [PATCH 10/15] Make the check always available --- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/fgopt.cpp | 4 ++-- src/coreclr/jit/lclvars.cpp | 10 +++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index bb24937e794faf..ab95317e184cb5 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4357,7 +4357,7 @@ class Compiler // If the local is TYP_REF, set or update the associated class information. void lvaSetClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false); void lvaSetClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE stackHandle = nullptr); - void lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false DEBUGARG(bool mustBeSingleDef = true)); + void lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact = false, bool singleDefOnly = true); void lvaUpdateClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE stackHandle = nullptr); #define MAX_NumOfFieldsInPromotableStruct 4 // Maximum number of fields in promotable struct diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 91ad0de4d8b62f..a9442342b50436 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -320,8 +320,8 @@ PhaseStatus Compiler::fgPostImportationCleanup() if (returnSpillVarDsc->lvType == TYP_REF && (returnSpillVarDsc->lvSingleDef || lvaInlineeReturnSpillTempFreshlyCreated)) { - lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, - impInlineInfo->retExprClassHndIsExact DEBUGARG(false)); + lvaUpdateClass(lvaInlineeReturnSpillTemp, retExprClassHnd, impInlineInfo->retExprClassHndIsExact, + false); } } } diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 11d822e8654a21..dc5144b0431659 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -3601,7 +3601,7 @@ void Compiler::lvaSetClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE // varNum -- number of the variable // clsHnd -- class handle to use in set or update // isExact -- true if class is known exactly -// mustBeSingleDef -- true if we should only update single-def locals +// singleDefOnly -- true if we should only update single-def locals // // Notes: // @@ -3619,7 +3619,7 @@ void Compiler::lvaSetClass(unsigned varNum, GenTree* tree, CORINFO_CLASS_HANDLE // for shared code, so ensuring this is so is currently not // possible. -void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact DEBUGARG(bool mustBeSingleDef)) +void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool isExact, bool singleDefOnly) { assert(varNum < lvaCount); @@ -3633,7 +3633,11 @@ void Compiler::lvaUpdateClass(unsigned varNum, CORINFO_CLASS_HANDLE clsHnd, bool assert(varDsc->lvClassHnd != NO_CLASS_HANDLE); // We should only be updating classes for single-def locals if requested - assert(!mustBeSingleDef || varDsc->lvSingleDef); + if (singleDefOnly && !varDsc->lvSingleDef) + { + assert(!"Updating class for multi-def local"); + return; + } // Now see if we should update. // From e94839bf462b636e07e13e3d14553de4281e781a Mon Sep 17 00:00:00 2001 From: Steven He Date: Thu, 30 Jan 2025 17:52:20 +0900 Subject: [PATCH 11/15] Deploy a fix for COM objects --- src/coreclr/jit/importer.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 0435ecf0b514e4..a031aecebd8ec5 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -11075,6 +11075,18 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) // of this return value. impInlineInfo->retExprClassHnd = returnClsHnd; impInlineInfo->retExprClassHndIsExact = isExact; +#ifdef FEATURE_COMINTEROP + if (returnClsHnd != nullptr) + { + const char* className = eeGetClassName(returnClsHnd); + if (strcmp(className, "System.Dynamic.DynamicMetaObject") == 0) + { + // We don't want to set DynamicMetaObject as exact + // because of dynamic runtime binding on COM objects. + impInlineInfo->retExprClassHndIsExact = false; + } + } +#endif // FEATURE_COMINTEROP } else if (impInlineInfo->retExprClassHnd != returnClsHnd) { From 7844b8f7130fde125bc1a8475d8244dd3149b16d Mon Sep 17 00:00:00 2001 From: Steven He Date: Thu, 30 Jan 2025 22:46:16 +0900 Subject: [PATCH 12/15] Revert "Deploy a fix for COM objects" This reverts commit e94839bf462b636e07e13e3d14553de4281e781a. --- src/coreclr/jit/importer.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index a031aecebd8ec5..0435ecf0b514e4 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -11075,18 +11075,6 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) // of this return value. impInlineInfo->retExprClassHnd = returnClsHnd; impInlineInfo->retExprClassHndIsExact = isExact; -#ifdef FEATURE_COMINTEROP - if (returnClsHnd != nullptr) - { - const char* className = eeGetClassName(returnClsHnd); - if (strcmp(className, "System.Dynamic.DynamicMetaObject") == 0) - { - // We don't want to set DynamicMetaObject as exact - // because of dynamic runtime binding on COM objects. - impInlineInfo->retExprClassHndIsExact = false; - } - } -#endif // FEATURE_COMINTEROP } else if (impInlineInfo->retExprClassHnd != returnClsHnd) { From 3c5a41b5ab35e228103d722c713eddc07ba27dc4 Mon Sep 17 00:00:00 2001 From: Steven He Date: Fri, 31 Jan 2025 00:45:11 +0900 Subject: [PATCH 13/15] The real fix --- src/coreclr/jit/importer.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 0435ecf0b514e4..8447d06ba4db0c 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -11076,13 +11076,22 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) impInlineInfo->retExprClassHnd = returnClsHnd; impInlineInfo->retExprClassHndIsExact = isExact; } - else if (impInlineInfo->retExprClassHnd != returnClsHnd) + else { - // This return site type differs from earlier seen sites, - // so reset the info and we'll fall back to using the method's - // declared return type for the return spill temp. - impInlineInfo->retExprClassHnd = nullptr; - impInlineInfo->retExprClassHndIsExact = false; + if (impInlineInfo->retExprClassHndIsExact != isExact) + { + // This return site type exactness differs from earlier seen sites, + // so reset the exactness info. + impInlineInfo->retExprClassHndIsExact = false; + } + if (impInlineInfo->retExprClassHnd != returnClsHnd) + { + // This return site type differs from earlier seen sites, + // so reset the info and we'll fall back to using the method's + // declared return type for the return spill temp. + impInlineInfo->retExprClassHnd = nullptr; + impInlineInfo->retExprClassHndIsExact = false; + } } } From b177f777c55acbad451fa65bbd0b82bf3ebd263c Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 31 Jan 2025 15:49:05 +0900 Subject: [PATCH 14/15] Address review feedback --- src/coreclr/jit/importer.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 8447d06ba4db0c..41983fb77c3ef4 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -11078,12 +11078,6 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) } else { - if (impInlineInfo->retExprClassHndIsExact != isExact) - { - // This return site type exactness differs from earlier seen sites, - // so reset the exactness info. - impInlineInfo->retExprClassHndIsExact = false; - } if (impInlineInfo->retExprClassHnd != returnClsHnd) { // This return site type differs from earlier seen sites, @@ -11092,6 +11086,11 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) impInlineInfo->retExprClassHnd = nullptr; impInlineInfo->retExprClassHndIsExact = false; } + else + { + // Same return type, but we may need to update exactness. + impInlineInfo->regExprClassHndIsExact &= isExact; + } } } From 1ea346a2f9fe8cf38572efc5ea4cdea0e6068e9d Mon Sep 17 00:00:00 2001 From: Steven He Date: Fri, 31 Jan 2025 18:49:12 +0900 Subject: [PATCH 15/15] Fix typo --- src/coreclr/jit/importer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 41983fb77c3ef4..4246e58f9fd869 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -11089,7 +11089,7 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) else { // Same return type, but we may need to update exactness. - impInlineInfo->regExprClassHndIsExact &= isExact; + impInlineInfo->retExprClassHndIsExact &= isExact; } } }