Open
Description
I think there's something wrong with Rust loops, they could lose some range information. So even if a for loop should be slightly simpler to analize compared to a while loop, the foo2 has no array bound tests, unlike foo1 (if N becomes 10 both get compiled to about the same asm without array bound tests):
pub fn foo1() -> u32 {
const N: usize = 20;
let mut data = [[0; N + 2]; N + 2];
for x in 0 .. N + 2 {
for y in 0 .. N + 2 {
if x == 1 || x == N || y == 1 || y == N {
data[x][y] = 1;
}
}
}
data[0][0]
}
pub fn foo2() -> u32 {
const N: usize = 20;
let mut data = [[0; N + 2]; N + 2];
let mut x = 0;
while x < N + 2 {
let mut y = 0;
while y < N + 2 {
if x == 1 || x == N || y == 1 || y == N {
data[x][y] = 1;
}
y += 1;
}
x += 1;
}
data[0][0]
}
rustc (V.1.51.0-nightly a4cbb44 2021-01-20) gives:
foo1:
push rbx
sub rsp, 1936
mov rdi, rsp
xor ebx, ebx
mov edx, 1936
xor esi, esi
call qword ptr [rip + memset@GOTPCREL]
mov al, 1
vbroadcastss ymm0, dword ptr [rip + .LCPI0_0]
xor edi, edi
jmp .LBB0_1
.LBB0_9:
vmovups ymmword ptr [rsp + rbx + 88], ymm0
vmovups ymmword ptr [rsp + rbx + 120], ymm0
vmovups xmmword ptr [rsp + rbx + 152], xmm0
mov ecx, 21
mov edx, 20
.LBB0_10:
add rdi, 2
lea rdx, [rsp + 4*rdx]
mov dword ptr [rbx + rdx + 88], 1
lea rcx, [rsp + 4*rcx]
mov dword ptr [rbx + rcx + 88], 1
cmp rax, 21
setb al
add rbx, 176
cmp rbx, 1936
je .LBB0_11
.LBB0_1:
cmp rbx, 1760
jne .LBB0_6
test al, 1
je .LBB0_8
vmovups ymmword ptr [rsp + rbx], ymm0
vmovups ymmword ptr [rsp + rbx + 32], ymm0
vmovups xmmword ptr [rsp + rbx + 64], xmm0
mov ecx, 21
mov edx, 20
jmp .LBB0_4
.LBB0_6:
test al, 1
je .LBB0_8
mov ecx, 20
mov edx, 1
.LBB0_4:
lea rax, [rdi + 1]
lea rdx, [rsp + 4*rdx]
mov dword ptr [rbx + rdx], 1
lea rcx, [rsp + 4*rcx]
mov dword ptr [rbx + rcx], 1
test rbx, rbx
je .LBB0_9
mov ecx, 20
mov edx, 1
jmp .LBB0_10
.LBB0_11:
mov eax, dword ptr [rsp]
add rsp, 1936
pop rbx
vzeroupper
ret
.LBB0_8:
lea rdx, [rip + .L__unnamed_1]
mov esi, 22
vzeroupper
call qword ptr [rip + core::panicking::panic_bounds_check@GOTPCREL]
ud2
foo2:
push rbx
sub rsp, 1936
mov rdi, rsp
xor ebx, ebx
mov edx, 1936
xor esi, esi
call qword ptr [rip + memset@GOTPCREL]
vbroadcastss ymm0, dword ptr [rip + .LCPI1_0]
jmp .LBB1_1
.LBB1_3:
lea rsi, [rsp + 4*rsi]
mov dword ptr [rbx + rsi], 1
lea rdx, [rsp + 4*rdx]
mov dword ptr [rbx + rdx], 1
test rbx, rbx
je .LBB1_4
.LBB1_5:
lea rcx, [rsp + 4*rcx]
mov dword ptr [rbx + rcx + 88], 1
lea rax, [rsp + 4*rax]
mov dword ptr [rbx + rax + 88], 1
add rbx, 176
cmp rbx, 1936
je .LBB1_6
.LBB1_1:
mov eax, 20
mov ecx, 1
mov esi, 1
mov edx, 20
cmp rbx, 1760
jne .LBB1_3
vmovups ymmword ptr [rsp + rbx], ymm0
vmovups ymmword ptr [rsp + rbx + 32], ymm0
vmovups xmmword ptr [rsp + rbx + 64], xmm0
mov edx, 21
mov esi, 20
jmp .LBB1_3
.LBB1_4:
vmovups ymmword ptr [rsp + rbx + 88], ymm0
vmovups ymmword ptr [rsp + rbx + 120], ymm0
vmovups xmmword ptr [rsp + rbx + 152], xmm0
mov eax, 21
mov ecx, 20
jmp .LBB1_5
.LBB1_6:
mov eax, dword ptr [rsp]
add rsp, 1936
pop rbx
vzeroupper
ret