-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Loops aren't cloned for Spans #82946
Comments
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch, @kunalspathak Issue Detailsvoid Test(Span<byte> source)
{
for (int i = 0; i < 100; i++)
source[i] = 0;
} Codegen: ; Method Progr:Test(System.Span`1[ubyte]):this
G_M11420_IG01:
4883EC28 sub rsp, 40
G_M11420_IG02:
33C0 xor eax, eax
align [0 bytes for IG03]
G_M11420_IG03:
3B4208 cmp eax, dword ptr [rdx+08H]
7317 jae SHORT G_M11420_IG05
488B0A mov rcx, bword ptr [rdx]
448BC0 mov r8d, eax
42C6040100 mov byte ptr [rcx+r8], 0
FFC0 inc eax
83F864 cmp eax, 100
7CE9 jl SHORT G_M11420_IG03
G_M11420_IG04:
4883C428 add rsp, 40
C3 ret
G_M11420_IG05:
E829C64C5F call CORINFO_HELP_RNGCHKFAIL
CC int3
; Total bytes of code: 40 Here it is expected to have two loops and one of them without bound checks. cc @BruceForstall @dotnet/jit-contrib
|
Is this a regression? Back when we first implemented span we deliberately patterned the IR after array so that we'd get all the same optimizations. |
No, it has always been like that. |
And, guess it was me who made it so: dotnet/coreclr#19493 |
What about having the JIT recognize Math.Min and eliminate the bounds check. This way, a programmer can guarantee bounds by using Math.Min.
Also it would be nice if JIT also recognize Downwards loop variants. |
It is expected to be handled by Loop Clonning as is today, just not for spans (yet). E.g. for Arrays: void Test(byte[] source)
{
int length = Math.Min(100, source.Length);
for (int i = 0; i < length; i++)
source[i] = 0;
} Emits: ; Method Program:Test(ubyte[]):this (FullOpts)
G_M50342_IG01: ;; offset=0x0000
sub rsp, 40
G_M50342_IG02: ;; offset=0x0004
mov eax, dword ptr [rdx+0x08]
mov ecx, 100
cmp eax, 100
cmovl ecx, eax
xor eax, eax
test ecx, ecx
jle SHORT G_M50342_IG05
G_M50342_IG03: ;; offset=0x0018
cmp dword ptr [rdx+0x08], ecx
jl SHORT G_M50342_IG06
align [3 bytes for IG04]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
G_M50342_IG04: ;; offset=0x0020
mov r8d, eax
mov byte ptr [rdx+r8+0x10], 0
inc eax
cmp eax, ecx
jl SHORT G_M50342_IG04
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
G_M50342_IG05: ;; offset=0x002F
add rsp, 40
ret
G_M50342_IG06: ;; offset=0x0034
cmp eax, dword ptr [rdx+0x08]
jae SHORT G_M50342_IG07
mov r8d, eax
mov byte ptr [rdx+r8+0x10], 0
inc eax
cmp eax, ecx
jl SHORT G_M50342_IG06
jmp SHORT G_M50342_IG05
G_M50342_IG07: ;; offset=0x004A
call CORINFO_HELP_RNGCHKFAIL
int3
; Total bytes of code: 80 It is still emitting the slow loop here which is redundant, but it shouldn't affect performance |
cc @AndyAyersMS it looks like we can actually fold the "clonned" condition here via assertions (over PHI node). |
Codegen:
Here it is expected to have two loops and one of them without bound checks.
cc @BruceForstall @dotnet/jit-contrib
category:cq
theme:loop-opt
skill-level:expert
cost:medium
impact:large
The text was updated successfully, but these errors were encountered: