-
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: optimize comparisons for const strings #33338
Comments
Can you share some examples where this occurs in production code? |
Would this be triggered by Attribute annotations? e.g. string in attribute then used by |
The consuming code using reflection to access the attribute wouldn't see it as a const, right? And even if it did, we're talking about reflection; the extra optimizations matter in such cases? |
I'll try to find production cases but I am more interested in feedback regarding the jit inliner as I think it should allow to inline more calls when args are const strings (with Also in theory we can optimize things like |
I think teaching JIT to inline
Both of these can change during process lifetime. And both of these are expensive operations by design that are not meant to be called on hot paths. Not worth doing anything for these in the JIT. |
I have a demo! Inliner now takes public static void Test()
{
Validate("hello");
}
public static void Validate(string a)
{
if (a.Length > 10)
throw new Exception();
} Currently
So the current codegen for ; Method Program:Test()
G_M24707_IG01:
4883EC28 sub rsp, 40
G_M24707_IG02:
48B9E0310C235C020000 mov rcx, 0x25C230C31E0
488B09 mov rcx, gword ptr [rcx]
E81AA3FEFF call Program:Validate(System.String)
90 nop
G_M24707_IG03:
4883C428 add rsp, 40
C3 ret
; Total bytes of code: 28 With my ; Method Program:Test()
G_M24707_IG01:
G_M24707_IG02:
C3 ret
; Total bytes of code: 1 Here is the fix (it's based on existing cc @AndyAyersMS 🙂
|
@EgorBo it probably costs too much jit time to resolve every callvirt token. Noticing the when caller passes or callee pushes constant strings and that those values are then used in comparisons or as the "this arg" in calls is probably the sort of analysis we can afford here. I can work up a code sketch, but it may take me a day or two. |
@AndyAyersMS Is it too expensive even for tiered JIT? |
@deiruch probably so. At some point down the road we'll be able to consider more aggressive optimizations in higher tiers, but we're not there yet. |
Probably not so important for R2R? and then R2R can give hints to Tier1 where it's profitable to inline. |
As a motivating example, consider a source generator that generates a method which acts differently depending on where it's called form. To do so it switches on CallerLineNumber, and CallerFilePath. For example, a source generator might provide a method to print the expression passed into it as an argument (see it on sharplab): using System;
using System.Runtime.CompilerServices;
public static class Program
{
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static void Main()
{
Console.WriteLine(Helpers.PrintExpression(1 + 3 + 7));
Console.WriteLine(Helpers.PrintExpression(new object()));
Console.WriteLine(Helpers.PrintExpression(5 == 7));
}
}
public static partial class Helpers
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string PrintExpression(object expression, [CallerFilePath] string filePath = default, [CallerLineNumber] int lineNumber = default)
{
return lineNumber switch {
10 => filePath switch { "main.cs" => "1 + 3 + 7", _ => ""},
11 => filePath switch { "main.cs" => "new object()", _ => ""},
12 => filePath switch { "main.cs" => "5 == 7", _ => ""},
_ => ""
};
}
} By inlining you can get rid of the first switch, on |
Let's say I have a code:
Validate
is inlined intoTest
like this:And it's not optimized into just
false
constant.There are 3 solutions to fix it:
string.Equals
, working prototype: EgorBo@06eca1cstring.Equals
always inlineable via[MethodImpl(MethodImplOptions.AggressiveInlining)]
and it will work! However, it will significantly regress non-constant cases - definitely not an option.E.g. if I remove
object.ReferenceEquals(a, b)
it will be inlined!category:cq
theme:inlining
skill-level:intermediate
cost:medium
The text was updated successfully, but these errors were encountered: