From 5ac34e35331b372d891deceba0e4eefc011c664e Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Wed, 2 Jul 2025 17:44:12 -0700 Subject: [PATCH] JIT: relax another check in conditional escape analysis Proceed with CEA cloning even when the allocation site dominates the assignment to the enumerator var. The cloning will be a bit wasteful as the original code will become unreachable, but the code is set up to specialize the clone and so this is the less risky fix. Also restore recognition of `IEnumerable.GetEnumerator` as this gives a useful inlining boost in some cases. Fixes #117204 cases that were not fixed by #117222. --- src/coreclr/jit/importercalls.cpp | 7 +++++++ src/coreclr/jit/namedintrinsiclist.h | 3 ++- src/coreclr/jit/objectalloc.cpp | 16 ++++++++++++---- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index bc6c2da6dae770..cbdb15e9a63d9d 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -10420,6 +10420,13 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) result = NI_System_Collections_Generic_EqualityComparer_get_Default; } } + else if (strcmp(className, "IEnumerable`1") == 0) + { + if (strcmp(methodName, "GetEnumerator") == 0) + { + result = NI_System_Collections_Generic_IEnumerable_GetEnumerator; + } + } } else if (strcmp(namespaceName, "Numerics") == 0) { diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 72ea2c164fd9eb..71a7124e0974ac 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -255,10 +255,11 @@ enum NamedIntrinsic : unsigned short NI_PRIMITIVE_END, // - // Array Intrinsics + // Enumeration Intrinsics // NI_System_SZArrayHelper_GetEnumerator, NI_System_Array_T_GetEnumerator, + NI_System_Collections_Generic_IEnumerable_GetEnumerator, }; #endif // _NAMEDINTRINSICLIST_H_ diff --git a/src/coreclr/jit/objectalloc.cpp b/src/coreclr/jit/objectalloc.cpp index 7098790d4a4b57..0b5a62f3400a36 100644 --- a/src/coreclr/jit/objectalloc.cpp +++ b/src/coreclr/jit/objectalloc.cpp @@ -3845,13 +3845,21 @@ bool ObjectAllocator::CheckCanClone(CloneInfo* info) // (if it does, optimization does not require cloning, as // there should be only one reaching def...) // + // For now we're going to just go ahead and clone, despite the + // fact that this is wasteful. + // + // In the transformation that follows the cloned path is the + // "fast" path and gets properly specialized; the original "slow + // path" will become unreachable and get cleaned up later on. + // + // See dotnet/runtime issue #117204. + // if (comp->m_domTree->Dominates(allocBlock, defBlock)) { - JITDUMP("Unexpected, alloc site " FMT_BB " dominates def block " FMT_BB "\n", allocBlock->bbNum, - defBlock->bbNum); - - return false; + JITDUMP("Unexpected, alloc site " FMT_BB " dominates def block " FMT_BB ". We will clone anyways.\n", + allocBlock->bbNum, defBlock->bbNum); } + // Classify the other local appearances // as Ts (allocTemps) or Us (useTemps), and look for guard appearances. //