I’m studying machine code produced by the Rust compiler. Here is a simple function that calculates the sum of all elements in a slice. (In Rust, a slice is essentially an array whose length is generally only known at runtime. It resides in a contiguous region of memory and is described by a pointer to the first element and the number of elements.)
fn sum_imperative(slice: &[i64]) -> i64 {
let mut sum = 0;
for n in slice {
sum += n;
}
sum
}
With SSE disabled and optimizations turned on, rustc 1.46.0 produces code that starts like this:
example::sum_imperative:
test rsi, rsi
je .LBB0_1
lea rax, [8*rsi - 8]
mov rdx, rax
shr rdx, 3
add rdx, 1
Here, the number of elements N in the slice is in rsi. If my understanding is correct, the code first calculates 8N−8 and stores that in rax. Then it uses that result to calculate (8N−8)/8+1 and stores that in rdx. Assuming there is no overflow, the rdx result should always be equal to the original value of N that is still available in rsi.
Why did the compiler recalculate the value of N rather than use one that was already available in rsi?