Skip to content
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

ILLink is leaving in callsite to constant method #1113

Closed
eerhardt opened this issue Apr 16, 2020 · 3 comments
Closed

ILLink is leaving in callsite to constant method #1113

eerhardt opened this issue Apr 16, 2020 · 3 comments
Labels

Comments

@eerhardt
Copy link
Member

In the dotnet/runtime libraries, we have the following code in System.SR:

        private static bool UsingResourceKeys() => false;

        internal static string GetResourceString(string resourceKey, string? defaultString = null)
        {
            if (UsingResourceKeys())
            {
                return defaultString ?? resourceKey;
            }

            // do the resource look-up

When this is passed through the linker, the IL is re-written to remove the branch around the constant UsingResourceKeys(), but the linker is leaving the call site to UsingResourceKeys() in GetResourceString().

.method assembly hidebysig static string 
        GetResourceString(string resourceKey,
                          [opt] string defaultString) cil managed
{
  .param [2] = nullref
  // Code size       42 (0x2a)
  .maxstack  2
  .locals (string V_0)
  IL_0000:  call       bool System.SR::UsingResourceKeys()
  IL_0005:  brfalse.s  IL_0007
  IL_0007:  ldnull
  IL_0008:  stloc.0
  .try
  {
    IL_0009:  call       class [System.Runtime]System.Resources.ResourceManager System.SR::get_ResourceManager()

We should be removing the call to UsingResourceKeys() as well, since it is not used.

@marek-safar
Copy link
Contributor

The linker is not IL optimizer/rewriter, we tried to not to go there unless really necessary. We might consider that in the future but no noticeable saving scenario showed up based on this yet.

@radekdoulik
Copy link
Member

Similar example of the same from dotnet/runtime#41097 where we branch like this:

        if (Sse2.IsSupported || AdvSimd.Arm64.IsSupported || Vector.IsHardwareAccelerated)
        {
            return IndexOfOrLessThan(
                    ref MemoryMarshal.GetReference(span),
                    JsonConstants.Quote,
                    JsonConstants.BackSlash,
                    lessThan: JsonConstants.Space,
                    span.Length);
        }
        else
        {
            return IndexOfOrLessThanNonVector(span);
        }

we endup with this IL after linking:

.method public hidebysig static int32  IndexOfQuoteOrAnyControlOrBackSlash(valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<uint8> span) cil managed aggressiveinlining
{
  // Code size       26 (0x1a)
  .maxstack  8
  IL_0000:  call       bool [System.Private.CoreLib]System.Runtime.Intrinsics.X86.Sse2::get_IsSupported()
  IL_0005:  pop
  IL_0006:  call       bool [System.Private.CoreLib]System.Runtime.Intrinsics.Arm.AdvSimd/Arm64::get_IsSupported()
  IL_000b:  pop
  IL_000c:  call       bool [System.Private.CoreLib]System.Numerics.Vector::get_IsHardwareAccelerated()
  IL_0011:  brfalse.s  IL_0013
  IL_0013:  ldarg.0
  IL_0014:  call       int32 System.Text.Json.JsonReaderHelper::IndexOfOrLessThanNonVector(valuetype [System.Private.CoreLib]System.ReadOnlySpan`1<uint8>)
  IL_0019:  ret
} // end of method JsonReaderHelper::IndexOfQuoteOrAnyControlOrBackSlash

All the get methods return false. It would be nice to avoid calling them and removing the brfalse.s instruction.

@vitek-karas
Copy link
Member

Linker now inlines some of the const methods. For example the SR.GetResourceString now looks like this:

	IL_0000: ldc.i4.1
	IL_0001: pop
	IL_0002: ldarg.0
	IL_0003: ret

It's still not perfect (there's no need for ldc.i4.1, pop) but the call is removed and JIT will probably optimize this fully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants