-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
RyuJIT: Don't inline calls inside rarely used basic-blocks #41923
Comments
Typical improvements: UnmanagedMemoryAccessor.ReadArray(...) SR.SomeStr is inlined into "key str" + SR.GetStringResource call There are a few minor regressions, mainly because sometimes inlining decreases caller size. E.g. https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/DiagnosticUtility.cs#L47-L50 |
I like your thinking here, but I would try and work within the current policy framework rather than override it.
Also there are times (though we're not smart enough to spot them yet) where we may want to inline more aggressively in a cold path to reveal facts that allow us to optimize a hotter path. So I'd prefer to keep this information as part of tunable policy and not as a fatal observation. Can you try smaller multipliers for the And FYI, I'm hoping to start chipping away at various sorts of profile support in the 6.0 timeframe so we have better guidance for the inliner. |
These
in my case these 11 bytes of IL lead to +46 bytes of asm in a cold block 🙂 |
Regarding 0.1 - Total bytes of diff: 0 (0.00% of base) |
Thanks. So you are saying these size increases all come from always inline cases? Last I looked the overwhelming majority of these were size-decreasing. I still think we're better of overall doing some inlining in cold regions; we just need to pick the right candidates. We still do some analysis of always inlines, in particular the IL scan, so one possible route here is to look for IL visible properties that distinguish size-decreasing always inlines from size-increasing inlines and use that to inform policy. I did something like that a while back when working on ML-derived heuristics; one of the heuristics this derived was the |
Especially this pattern: public class Program
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void Test(int x)
{
if (x % 2 != 0)
throw new ArgumentException(SR.Argument_NotPOT);
}
}
internal static class SR
{
internal static string Argument_NotPOT => GetResourceString(nameof(Argument_NotPOT));
[MethodImpl(MethodImplOptions.NoInlining)] // simulates resource lookup
internal static string GetResourceString(string resourceKey) => resourceKey;
} We use this SR.ResourceKey everywhere and everywhere we inline them as "string literal (key) + GetResourceString call" but the thing is - for A possible strategy: ldstr tokens aren't cheap in cold blocks. |
Moving this to Future, in theory, it should be eventually fixed by #43914 |
Let's not inline calls inside rarely used basic blocks, e.g. blocks with
throw
(we already don't do it insidecatch
andfilter
ones).An example with
throw
:Current Codegen (inliner inlines
GetMyException()
):Expected Codegen (my prototype):
-46 bytes of code.
It shouldn't also inline various
SR.get_...()
calls (used a lot across the BCL) string properties for exceptions, e.g.:jit-diff from my prototype (Release, -pmi -f):
crossgen2 diff:
As far as I understand, such blocks won't be even compiled in future (@AndyAyersMS 's #34522) but I guess it still makes sense to abort inlining inside them?
@dotnet/jit-contrib
category:cq
theme:inlining
skill-level:intermediate
cost:medium
The text was updated successfully, but these errors were encountered: