-
Notifications
You must be signed in to change notification settings - Fork 2.7k
JIT: infer ranges from small int type operations #21857
Conversation
Have range check use the ranges for small int types if it has no better information. Fixes dotnet#21481
@erozenfeld PTAL This fixes the case in #21841 and gets a few other hits in the framework code. It might be worth looking at related cases (say casts) to see if there's more to be had here. There may be some symbolic way to express the value range for the small types, but I couldn't find suitable defines. Jit-diffs over fx:
Search loop in #21841 is now: G_M32190_IG03:
4863D0 movsxd rdx, eax
48B9E82985840B020000 mov rcx, 0x20B848529E8
0FB6140A movzx rdx, byte ptr [rdx+rcx]
4863D2 movsxd rdx, edx
48B9E82885840B020000 mov rcx, 0x20B848528E8
803C0A00 cmp byte ptr [rdx+rcx], 0
740C je SHORT G_M32190_IG05
FFC0 inc eax
83F804 cmp eax, 4
7CD5 jl SHORT G_M32190_IG03 |
I suppose you could use Or you could "steal" the code from GenIntCastDesc that computes min/max from the type size and signedness: coreclr/src/jit/codegenlinear.cpp Lines 1989 to 1991 in ca65764
|
Test failures seem unrelated, will rerun a few... @dotnet-bot retest OSX10.12 x64 Checked Innerloop Build and Test |
OSX now showing "typical" failures in PAL file tests:
will give it one more try.... @dotnet-bot retest OSX10.12 x64 Checked Innerloop Build and Test Ubuntu arm failure in "dynamo" GC test (linking to #17129)
@dotnet-bot retest Ubuntu arm Cross Checked Innerloop Build and Test |
We have MAX_SHORT_AS_INT and MIN_SHORT_AS_INT consts in jit.h (currently unused). Perhaps we can add constants for ushort, byte, and ubyte there. |
LGTM |
@AndyAyersMS, in your code gen you have the following. 0FB6140A movzx rdx, byte ptr [rdx+rcx]
4863D2 movsxd rdx, edx Is it possible to get the JIT to drop the |
The jit disassembler is not quite right here -- actual disassembly is 0FB6140A movzx edx, byte ptr [rdx+rcx] // dest is edx, not rdx
4863D2 movsxd rdx, edx (encoding would need to be And while it seems like it ought to be simple to fix this, there are various issues... Early on there are two uses of the load result -- one for the bounds check and one for the array element address, of type Later during optimization we eliminate the bounds check (which this PR enables) and only the We don't catch this later on after lowering even though def and use trees end up adjacent because the jit does not model the implicit upper half zeroing on x64 for 32 bit register destinations (that is, we don't realize the |
If the JIT did model/track the implicit upper half zeroing on x64, it would allow most sign-extensions to be eliminated from array/span accesses also. I tried to get something working in #21553, but at the moment it looks a bit too complicated for my limited JIT development skill. While replacing |
range = Range(Limit(Limit::keConstant, 0), Limit(Limit::keConstant, 255)); | ||
break; | ||
case TYP_BYTE: | ||
range = Range(Limit(Limit::keConstant, -127), Limit(Limit::keConstant, 128)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be -128 to 127 or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it should be... thanks for spotting it.
We have GetLowerBoundForIntegralType and GetUpperBoundForIntegralType that could've been used here. |
…allTypes JIT: infer ranges from small int type operations Commit migrated from dotnet/coreclr@eaf9823
Have range check use the ranges for small int types if it has no better
information.
Fixes #21841