Optimize MethodTable on both sides of `==` (#87238)
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>
Thu, 8 Jun 2023 06:19:01 +0000 (15:19 +0900)
committerGitHub <noreply@github.com>
Thu, 8 Jun 2023 06:19:01 +0000 (15:19 +0900)
Optimizes `typeof(Foo) == typeof(Bar)` for both sides. This is necessary to get `System.Double` MethodTable from hello world again.

I tried to write a test for this but I wasn't able to come up with something in 10 minutes so I gave up. It seems to require interactions of several things to actually trigger the size bloat without this extra optimization. But this does fix the `Double` case.

src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs

index bda68c3..8ea05d0 100644 (file)
@@ -929,12 +929,32 @@ namespace Internal.IL
                             nextBasicBlock = _basicBlocks[_currentOffset + 5];
                             if (nextBasicBlock == null)
                             {
+                                // We expect pattern:
+                                //
+                                // ldtoken Foo
+                                // call GetTypeFromHandle
+                                // ldtoken Bar
+                                // call GetTypeFromHandle
+                                // call Equals
+                                //
+                                // We check for both ldtoken cases
                                 if ((ILOpcode)_ilBytes[_currentOffset + 5] == ILOpcode.call)
                                 {
                                     methodToken = ReadILTokenAt(_currentOffset + 6);
                                     method = (MethodDesc)_methodIL.GetObject(methodToken);
                                     isTypeEquals = IsTypeEquals(method);
                                 }
+                                else if ((ILOpcode)_ilBytes[_currentOffset + 5] == ILOpcode.ldtoken
+                                    && _basicBlocks[_currentOffset + 10] == null
+                                    && (ILOpcode)_ilBytes[_currentOffset + 10] == ILOpcode.call
+                                    && methodToken == ReadILTokenAt(_currentOffset + 11)
+                                    && _basicBlocks[_currentOffset + 15] == null
+                                    && (ILOpcode)_ilBytes[_currentOffset + 15] == ILOpcode.call)
+                                {
+                                    methodToken = ReadILTokenAt(_currentOffset + 16);
+                                    method = (MethodDesc)_methodIL.GetObject(methodToken);
+                                    isTypeEquals = IsTypeEquals(method);
+                                }
                             }
                         }
                     }