Uh oh!
There was an error while loading. Please reload this page.
Replace default(T) != null with typeof(T).IsValueType - #32098
Conversation
Does this have any negative impact on tier 0 code that might make start-up slower? (Presumably R2R shared framework images will employ the optimization and so are fine.) And I assume the new asm in these cases is as good / better than what it was before the change? |
Uh oh!
There was an error while loading. Please reload this page.
GrabYourPitchforks
commented
Feb 11, 2020
I'm not really qualified to answer this. @dotnet/jit-contrib, thoughts? |
GrabYourPitchforks
commented
Feb 11, 2020
As far as I can tell, yeah. [Benchmark]publicintTestNullableInt()=>Array.Empty<int?>().AsSpan().Length;; before00007ffd`54b7a210 4883ec28 subrsp,28h00007ffd`54b7a214 33c0 xoreax,eax00007ffd`54b7a216 4889442420mov qword ptr [rsp+20h],rax00007ffd`54b7a21b 48b8782d009019020000 movrax,21990002D78h00007ffd`54b7a225 488b00 movrax,qword ptr [rax]00007ffd`54b7a228 4885c0 testrax,rax00007ffd`54b7a22b 7504jne ConsoleAppBenchmark!ConsoleAppBenchmark.DefaultOfTRunner.Test()+0x1d01 (00007ffd`54b7a231)00007ffd`54b7a22d 33c0 xoreax,eax00007ffd`54b7a22f eb20 jmp ConsoleAppBenchmark!ConsoleAppBenchmark.DefaultOfTRunner.Test()+0x1d21 (00007ffd`54b7a251)00007ffd`54b7a231 33d2 xoredx,edx00007ffd`54b7a233 4889542420mov qword ptr [rsp+20h],rdx00007ffd`54b7a238 807c242000 cmp byte ptr [rsp+20h],000007ffd`54b7a23d 750f jne ConsoleAppBenchmark!ConsoleAppBenchmark.DefaultOfTRunner.Test()+0x1d1e (00007ffd`54b7a24e)00007ffd`54b7a23f 48bac8aec054fd7f0000 movrdx,7FFD54C0AEC8h00007ffd`54b7a249 483910cmp qword ptr [rax],rdx00007ffd`54b7a24c 7508jne ConsoleAppBenchmark!ConsoleAppBenchmark.DefaultOfTRunner.Test()+0x1d26 (00007ffd`54b7a256)00007ffd`54b7a24e 8b4008 moveax,dword ptr [rax+8]00007ffd`54b7a251 4883c428 addrsp,28h00007ffd`54b7a255 c3 ret; after00007ffd`517ba2e0 48b8782ddb1594010000 movrax,19415DB2D78h00007ffd`517ba2ea 488b00 movrax,qword ptr [rax]00007ffd`517ba2ed 4885c0 testrax,rax00007ffd`517ba2f0 7504jne ConsoleAppBenchmark!ConsoleAppBenchmark.DefaultOfTRunner.Test()+0x20e6 (00007ffd`517ba2f6)00007ffd`517ba2f2 33c0 xoreax,eax00007ffd`517ba2f4 eb03 jmp ConsoleAppBenchmark!ConsoleAppBenchmark.DefaultOfTRunner.Test()+0x20e9 (00007ffd`517ba2f9)00007ffd`517ba2f6 8b4008 moveax,dword ptr [rax+8]00007ffd`517ba2f9 c3 ret |
CarolEidt
commented
Feb 11, 2020
I assume that the question pertains to the quality of the generated code, which can be seen by compiling with COMPlus_JitMinOpts=1. |
stephentoub
commented
Feb 12, 2020
Effectively, yes, whether typeof(T).IsValueType is going to be treated as an intrinsic and substituted for even in min opts, or whether by adding a bunch of these calls we're actually going to be doing more reflection and invoking IsValueTypeImpl on a bunch more code paths. If it's the former, great. |
GrabYourPitchforks
commented
Feb 12, 2020
I believe that since |
That is not correct. The intrinsics are recognized only with optimizations on by default. |
AndyAyersMS
commented
Feb 12, 2020
(as Jan's just commented) Intrinsics are generally not expanded in Tier0 compilation (aka min opts).
So for some of the cases in this PR, this change would cause regressions in Tier0 code. |
The Tier0 code will be bigger and slower with this, but I do not think that it is a problem. And it is not going to allocate repeatedly, so it is not going to show up on the radar for folks who look at GC allocations. |
GrabYourPitchforks
commented
Feb 12, 2020
CI failures seem to be known issue #32126. |
Builds on top of the optimizations done at #1157.
Replaces
default(T) != nullwithtypeof(T).IsValueTypewhen: (a) the code targets netcoreapp5.0+; and (b) the caller intended to use this pattern as a cheap "is value type?" check and isn't intending to special-case nullable types.