JIT: Optimize range checks for a[i & C], a[i % c] and a[(i & c1)>>c2)] patterns by EgorBo · Pull Request #1644 · dotnet/runtime (original) (raw)
static ReadOnlySpan span => new byte[] { 1,2,3,4 };
byte Case1(int i) => span[i & 2]; byte Case2(int i) => span[i & (span.Length - 1)]; // "i & 3" byte Case3(int i) => span[(i & 10) >> 2]; // or << byte Case4(uint i) => span[(int)(i % 2)]; // only for unsigned i
This PR currently handles only &, % and >>
operators with constant op2
and ignores actual range of op1
(always sets 0 as a lower limit and op2->IconValue()
as an upper limit) to keep this PR simple and harmless.
Total bytes of diff: -133 (-0.00% of base)
diff is an improvement.
Top file improvements by size (bytes):
-69 : System.Private.CoreLib.dasm (-0.00% of base)
-64 : System.Private.Uri.dasm (-0.07% of base)
2 total files with size differences (2 improved, 0 regressed), 107 unchanged.
Top method improvements by size (bytes):
-69 (-8.61% of base) : System.Private.CoreLib.dasm - System.IO.Path:Populate83FileNameFromRandomBytes(long,int,System.Span`1[Char])
-38 (-2.77% of base) : System.Private.Uri.dasm - System.UriHelper:EscapeStringToBuilder(System.ReadOnlySpan`1[Char],byref,System.ReadOnlySpan`1[Boolean],bool)
-14 (-5.88% of base) : System.Private.Uri.dasm - System.UriHelper:EscapeAsciiChar(ushort,byref)
-12 (-10.34% of base) : System.Private.Uri.dasm - <>c:<HexEscape>b__121_0(System.Span`1[Char],ushort):this
Top method improvements by size (percentage):
-12 (-10.34% of base) : System.Private.Uri.dasm - <>c:<HexEscape>b__121_0(System.Span`1[Char],ushort):this
-69 (-8.61% of base) : System.Private.CoreLib.dasm - System.IO.Path:Populate83FileNameFromRandomBytes(long,int,System.Span`1[Char])
-14 (-5.88% of base) : System.Private.Uri.dasm - System.UriHelper:EscapeAsciiChar(ushort,byref)
-38 (-2.77% of base) : System.Private.Uri.dasm - System.UriHelper:EscapeStringToBuilder(System.ReadOnlySpan`1[Char],byref,System.ReadOnlySpan`1[Boolean],bool)
4 total methods with size differences (4 improved, 0 regressed), 262165 unchanged.
The jit diff is quite small but there are few more places in the BCL where we can slightly tune and benefit from this opt, e.g.: here, also, see this comment. Also all [x % c]
patterns require cast to uint
.