Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Apparent no-op in Rust assembly output?

I was studying the x86_64 assembly for the following function:

/// Returns the greatest power of two less than or equal to `self`, or 0 otherwise.
pub const fn prev_power_of_two(n: u64) -> u64 {
    // n = 0 gives highest_bit_set_idx = 0.
    let highest_bit_set_idx = 63 - (n|1).leading_zeros();
    // Binary AND of highest bit with n is a no-op, except zero gets wiped.
    (1 << highest_bit_set_idx) & n
}

When compiling with -C opt=level=3 we get the following assembly on nightly and 1.50.0:

example::prev_power_of_two:
        mov     rax, rdi
        or      rax, 1
        bsr     rcx, rax
        xor     ecx, 63
        xor     cl, 63
        mov     eax, 1
        shl     rax, cl
        and     rax, rdi
        ret

Everything seems good, except I can't explain these two instructions:

    xor     ecx, 63
    xor     cl, 63

As far as I can see, these are a no-op. Why are they generated?

like image 682
orlp Avatar asked Mar 16 '21 23:03

orlp


1 Answers

This problem has been fixed. Rust nightly no longer generates these xor instructions.

See Godbolt

like image 188
Robin Lindner Avatar answered Oct 28 '22 14:10

Robin Lindner