From 3e4673981e1b0fbf4c40415cd0c6f88b66605859 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 11 Jun 2023 17:57:34 +0200 Subject: [PATCH 1/2] Set JitGuardedDevirtualizationMaxTypeChecks for JIT --- .../Compiler/RyuJitCompilationBuilder.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs index ea29f7ff342c95..9938ee3df22735 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs @@ -43,6 +43,14 @@ public override CompilationBuilder UseBackendOptions(IEnumerable options { var builder = default(ArrayBuilder>); + if (_optimizationMode != OptimizationMode.PreferSize) + { + // Enable GDV with multiple guesses - it's useful even without PGO as we can still + // devirtualize virtual calls when we know that the number of their targets is limited. + // It can be overridden by --codegenopt:JitGuardedDevirtualizationMaxTypeChecks=X + builder.Add(new KeyValuePair("JitGuardedDevirtualizationMaxTypeChecks", "3")); + } + foreach (string param in options) { int indexOfEquals = param.IndexOf('='); From 1ad859dd4b18e43907b76813c6baf4b6d26242f4 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 12 Jun 2023 14:04:20 +0200 Subject: [PATCH 2/2] Address feedback --- src/coreclr/jit/compiler.h | 22 +++++++++++++++++++ src/coreclr/jit/importercalls.cpp | 6 ++--- src/coreclr/jit/jitconfigvalues.h | 4 ++-- .../Compiler/RyuJitCompilationBuilder.cs | 8 ------- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 65379c6c8240fb..ad509b04b213f8 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7149,6 +7149,28 @@ class Compiler unsigned classAttr, unsigned likelihood); + int getGDVMaxTypeChecks() + { + int typeChecks = JitConfig.JitGuardedDevirtualizationMaxTypeChecks(); + if (typeChecks < 0) + { + // Negative value means "it's up to JIT to decide" + if (IsTargetAbi(CORINFO_NATIVEAOT_ABI) && !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_SIZE_OPT)) + { + return 3; + } + + // We plan to use 3 for CoreCLR too, but we need to make sure it doesn't regress performance + // as CoreCLR heavily relies on Dynamic PGO while for NativeAOT we *usually* don't have it and + // can only perform the "exact" devirtualization. + return 1; + } + + // MAX_GDV_TYPE_CHECKS is the upper limit. The constant can be changed, we just suspect that even + // 4 type checks is already too much. + return min(MAX_GDV_TYPE_CHECKS, typeChecks); + } + bool doesMethodHaveExpRuntimeLookup() { return (optMethodFlags & OMF_HAS_EXPRUNTIMELOOKUP) != 0; diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 43ad185b63e8a9..18fbf94c6f811e 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -5730,7 +5730,7 @@ void Compiler::pickGDV(GenTreeCall* call, // Prefer class guess as it is cheaper if (numberOfClasses > 0) { - const int maxNumberOfGuesses = min(MAX_GDV_TYPE_CHECKS, JitConfig.JitGuardedDevirtualizationMaxTypeChecks()); + const int maxNumberOfGuesses = getGDVMaxTypeChecks(); if (maxNumberOfGuesses == 0) { // DOTNET_JitGuardedDevirtualizationMaxTypeChecks=0 means we don't want to do any guarded devirtualization @@ -5931,7 +5931,7 @@ void Compiler::considerGuardedDevirtualization(GenTreeCall* call, { pickGDV(call, ilOffset, isInterface, likelyClasses, likelyMethodes, &candidatesCount, likelihoods); assert((unsigned)candidatesCount <= MAX_GDV_TYPE_CHECKS); - assert((unsigned)candidatesCount <= (unsigned)JitConfig.JitGuardedDevirtualizationMaxTypeChecks()); + assert((unsigned)candidatesCount <= (unsigned)getGDVMaxTypeChecks()); if (candidatesCount == 0) { hasPgoData = false; @@ -5944,7 +5944,7 @@ void Compiler::considerGuardedDevirtualization(GenTreeCall* call, // from both. if (!hasPgoData && (baseClass != NO_CLASS_HANDLE) && JitConfig.JitEnableExactDevirtualization()) { - int maxTypeChecks = min(JitConfig.JitGuardedDevirtualizationMaxTypeChecks(), MAX_GDV_TYPE_CHECKS); + int maxTypeChecks = min(getGDVMaxTypeChecks(), MAX_GDV_TYPE_CHECKS); CORINFO_CLASS_HANDLE exactClasses[MAX_GDV_TYPE_CHECKS]; int numExactClasses = info.compCompHnd->getExactClasses(baseClass, MAX_GDV_TYPE_CHECKS, exactClasses); diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 8657940e5a00c5..05cca1ff739438 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -527,8 +527,8 @@ CONFIG_INTEGER(JitEnableGuardedDevirtualization, W("JitEnableGuardedDevirtualiza #define MAX_GDV_TYPE_CHECKS 5 // Number of types to probe for polymorphic virtual call-sites to devirtualize them, -// Max number is MAX_GDV_TYPE_CHECKS defined above ^ -CONFIG_INTEGER(JitGuardedDevirtualizationMaxTypeChecks, W("JitGuardedDevirtualizationMaxTypeChecks"), 1) +// Max number is MAX_GDV_TYPE_CHECKS defined above ^. -1 means it's up to JIT to decide +CONFIG_INTEGER(JitGuardedDevirtualizationMaxTypeChecks, W("JitGuardedDevirtualizationMaxTypeChecks"), -1) // Various policies for GuardedDevirtualization CONFIG_INTEGER(JitGuardedDevirtualizationChainLikelihood, W("JitGuardedDevirtualizationChainLikelihood"), 0x4B) // 75 diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs index 9938ee3df22735..ea29f7ff342c95 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilationBuilder.cs @@ -43,14 +43,6 @@ public override CompilationBuilder UseBackendOptions(IEnumerable options { var builder = default(ArrayBuilder>); - if (_optimizationMode != OptimizationMode.PreferSize) - { - // Enable GDV with multiple guesses - it's useful even without PGO as we can still - // devirtualize virtual calls when we know that the number of their targets is limited. - // It can be overridden by --codegenopt:JitGuardedDevirtualizationMaxTypeChecks=X - builder.Add(new KeyValuePair("JitGuardedDevirtualizationMaxTypeChecks", "3")); - } - foreach (string param in options) { int indexOfEquals = param.IndexOf('=');