Is casting between integers expensive?

后端 未结 1 1200
梦如初夏
梦如初夏 2021-01-17 16:46

I am working on a project where I am doing a lot of index-based calculation. I have a few lines like:

let mut current_x: usize = (start.x as isize + i as isi         


        
相关标签:
1条回答
  • 2021-01-17 17:31

    It depends

    It's basically impossible to answer your question in isolation. These types of low-level things can be aggressively combined with operations that have to happen anyway, so any amount of inlining can change the behavior. Additionally, it strongly depends on your processor; changing to a 64-bit number on an 8-bit microcontroller is probably pretty expensive!

    My general advice is to not worry. Keep your types consistent, get the right answers, then profile your code and fix the issues you find.

    Pragmatically, what are you going to do instead?


    That said, here's some concrete stuff for x86-64 and Rust 1.18.0.

    Same size, changing sign

    Basically no impact. If these were inlined, then you probably would never even see any assembly.

    #[inline(never)]
    pub fn signed_to_unsigned(i: isize) -> usize {
        i as usize
    }
    
    #[inline(never)]
    pub fn unsigned_to_signed(i: usize) -> isize {
        i as isize
    }
    

    Each generates the assembly

    movq    %rdi, %rax
    retq
    

    Extending a value

    These have to sign- or zero-extend the value, so some kind of minimal operation has to occur to fill those extra bits:

    #[inline(never)]
    pub fn u8_to_u64(i: u8) -> u64 {
        i as u64
    }
    
    #[inline(never)]
    pub fn i8_to_i64(i: i8) -> i64 {
        i as i64
    }
    

    Generates the assembly

    movzbl  %dil, %eax
    retq
    
    movsbq  %dil, %rax
    retq
    

    Truncating a value

    Truncating is again just another move, basically no impact.

    #[inline(never)]
    pub fn u64_to_u8(i: u64) -> u8 {
        i as u8
    }
    
    #[inline(never)]
    pub fn i64_to_i8(i: i64) -> i8 {
        i as i8
    }
    

    Generates the assembly

    movl    %edi, %eax
    retq
    
    movl    %edi, %eax
    retq
    

    All these operations boil down to a single instruction on x86-64. Then you get into complications around "how long does an operation take" and that's even harder.

    0 讨论(0)
提交回复
热议问题