JIT: Writing into local memory prevents hoisting loads out of loop
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
https://godbolt.org/z/f7xheT6E6
Inside the loop I expect 1 load per iteration from `buildData.OriginalTriIds`.
The actual number of loads is 4. It seems like loop hoisting gives up because of the write into `indices`. But `indices` shouldn't be able to alias `leafNode` in any way:
```cs
static Span GetUnindexed(in GpuBlasNode leafNode, BuildData buildData)
{
Span indices = new int[leafNode.TriCount];
for (int i = 0; i < leafNode.TriCount; i++)
{
indices[i] = buildData.OriginalTriIds[leafNode.TriStartOrChild + i];
}
return indices;
}
```
`leafNode.TriCount`, `leafNode.TriStartOrChild` and `buildData.OriginalTriIds.Length` (for the bounds check) can be hoisted.
```assembly
Program:GetUnindexed(byref,Program+BuildData):System.Span`1[int] (FullOpts):
push rbp
push r15
push r14
push rbx
push rax
lea rbp, [rsp+0x20]
mov rbx, rdi
mov r15, rsi
mov r14d, dword ptr [rbx+0x24]
movsxd rsi, r14d
mov rdi, 0x7AD3E913A7C0 ; int[]
call CORINFO_HELP_NEWARR_1_VC
add rax, 16
mov edx, r14d
xor ecx, ecx
test r14d, r14d
jle SHORT G_M9601_IG04
align [10 bytes for IG03]
G_M9601_IG03: ;; offset=0x0040
cmp ecx, edx
jae SHORT G_M9601_IG05
mov edi, ecx
add edi, dword ptr [rbx+0x10] ; <-- load leafNode.TriStartOrChild
cmp edi, dword ptr [r15+0x08] ; <-- load buildData.OriginalTriIds.Length
jae SHORT G_M9601_IG05
mov edi, dword ptr [r15+4*rdi+0x10]
mov dword ptr [rax+4*rcx], edi
inc ecx
cmp ecx, dword ptr [rbx+0x24] ; <-- load leafNode.TriCount
jl SHORT G_M9601_IG03
G_M9601_IG04: ;; offset=0x005E
add rsp, 8
pop rbx
pop r14
pop r15
pop rbp
ret
G_M9601_IG05: ;; offset=0x0069
call CORINFO_HELP_RNGCHKFAIL
int3
```
Contributor guide
Assessment
This issue has not been assessed yet.