From 2a0dfd7c248962c58d6122b98c4d37a6c709033f Mon Sep 17 00:00:00 2001 From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com> Date: Tue, 10 Mar 2026 12:03:24 -0700 Subject: [PATCH] Remove async method inlining restrictions in crossgen2 Remove four restrictions that prevented async methods from being inlined during ReadyToRun compilation: 1. CanInline() rejected IsAsyncThunk()/IsAsyncCall() callees 2. CrossModuleInlineableUncached() rejected async variants/thunks 3. reportInlining() threw when async methods were cross-module inlined 4. InliningInfoNode skipped recording inlining info for async thunks All 69 async tests pass with both crossgen2 and composite R2R modes. Fixes https://github.com/dotnet/runtime/issues/124665 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../DependencyAnalysis/ReadyToRun/InliningInfoNode.cs | 5 ----- .../Compiler/ReadyToRunCodegenCompilation.cs | 6 ------ .../Compiler/ReadyToRunCompilationModuleGroupBase.cs | 4 ---- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 11 ----------- 4 files changed, 26 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs index 49c964cd0149da..e9a76a74d8a8dc 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs @@ -72,11 +72,6 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) continue; } MethodDesc inliner = methodNode.Method; - if (inliner.IsCompilerGeneratedILBodyForAsync()) - { - // Async thunks are restricted from inlining. https://github.com/dotnet/runtime/issues/124665 - continue; - } EcmaMethod inlinerDefinition = (EcmaMethod)inliner.GetPrimaryMethodDesc().GetTypicalMethodDefinition(); if (inlinerDefinition.IsNonVersionable()) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index 6a6ec431b9dffe..9d2fe7eaa309e3 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -109,12 +109,6 @@ public bool CanInline(MethodDesc caller, MethodDesc callee) } } - // TODO: Enable async inlining. https://github.com/dotnet/runtime/issues/124665 - if (callee.IsAsyncThunk() || callee.IsAsyncCall()) - { - return false; - } - _nodeFactory.DetectGenericCycles(caller, callee); return NodeFactory.CompilationModuleGroup.CanInline(caller, callee); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs index 96f78ba0309247..7d3b30db219454 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilationModuleGroupBase.cs @@ -520,10 +520,6 @@ private bool CrossModuleInlineableInternal(MethodDesc method) private bool CrossModuleInlineableUncached(MethodDesc method) { - // Async thunks and variants cannot currently be inlined cross module - if (method.IsAsyncVariant() || method.IsAsync || method.IsAsyncThunk()) - return false; - // Defined in corelib MetadataType owningMetadataType = method.OwningType.GetTypeDefinition() as MetadataType; if (owningMetadataType == null) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index c5e2d1f8ca40c3..3f35c1325eed82 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -3306,17 +3306,6 @@ private void reportInliningDecision(CORINFO_METHOD_STRUCT_* inlinerHnd, CORINFO_ var typicalMethod = inlinee.GetTypicalMethodDefinition(); - if ((typicalMethod.IsAsyncVariant() || typicalMethod.IsAsync || typicalMethod.IsCompilerGeneratedILBodyForAsync()) && !_compilation.CompilationModuleGroup.VersionsWithMethodBody(typicalMethod)) - { - // TODO: fix this restriction in runtime async. https://github.com/dotnet/runtime/issues/124665 - // Disable async methods in cross module inlines for now, we need to trigger the CheckILBodyFixupSignature in the right situations, and that hasn't been implemented - // yet. Currently, we'll correctly trigger the _ilBodiesNeeded logic below, but we also need to avoid triggering the ILBodyFixupSignature for the async thunks, but we ALSO need to make - // sure we generate the CheckILBodyFixupSignature for the actual runtime-async body in which case I think the typicalMethod will be an AsyncVariantMethod, which doesn't appear - // to be handled here. This check is here in the place where I believe we actually would behave incorrectly, but we also have a check in CrossModuleInlineable which disallows - // the cross module inline of async methods currently. - throw new Exception("Inlining async methods is not supported in ReadyToRun compilation."); - } - MethodIL methodIL = _compilation.GetMethodIL(typicalMethod); if (methodIL is ILStubMethodIL ilStubMethodIL && ilStubMethodIL.StubILHasGeneratedTokens) {