Closed
Description
I am using this function to decode gray coded u64
into decimal values (also u64
).
fn decimal(mut gray: u64) -> u64 {
// Copy the gray value.
let mut temp = gray;
while temp != 0 {
// Shift right temp.
temp >>= 1;
// XOR the gray value.
gray ^= temp;
}
gray
}
Target architecture is thumbv8.main-none-eabihf
with RUSTFLAGS:
rustflags = [
"-C", "link-arg=--nmagic",
"-C", "link-arg=-Tlink.x",
#"-C", "link-arg=-Tmemory.x",
"-C", "link-arg=-Tdefmt.x",
# Code optimizations
#"-Z", "trap-unreachable=no",
#"-C", "inline-threshold=5",
#"-C", "no-vectorize-loops",
# Fixes LLVM bug on function outlining
"-C", "llvm-args=--enable-machine-outliner=never",
]
The resulting code should be a function that transforms the input gray code into a decimal. Instead, the function gets optimized to directly return the input u64
. The final assembly of this function is:
00001190 <_ZN7lpc55006timers7ostimer7decimal17h543acbca5175c913E>:
1190: 4770 bx lr
To make the code correctly appear, the function must be marked with #[inline(never)]
, #[no_mangle]
and extern "Rust"
. Additionally, if the function is a member of a struct impl
not matter what it always get optimized away.
Correct function signature:
#[inline(never)]
#[no_mangle]
extern "Rust" fn decimal(mut gray: u64) -> u64 {}
Correct assembly:
00001190 <decimal>:
1190: ea50 0201 orrs.w r2, r0, r1
1194: bf02 ittt eq
1196: 2000 moveq r0, #0
1198: 2100 moveq r1, #0
119a: 4770 bxeq lr
119c: b5d0 push {r4, r6, r7, lr}
119e: af02 add r7, sp, #8
11a0: 4604 mov r4, r0
11a2: 460b mov r3, r1
11a4: ea5f 0c53 movs.w ip, r3, lsr #1
11a8: ea81 010c eor.w r1, r1, ip
11ac: ea4f 0e34 mov.w lr, r4, rrx
11b0: ea80 000e eor.w r0, r0, lr
11b4: ea5e 020c orrs.w r2, lr, ip
11b8: d01d beq.n 11f6 <decimal+0x66>
11ba: 08a2 lsrs r2, r4, #2
11bc: ea81 0193 eor.w r1, r1, r3, lsr #2
11c0: ea42 7283 orr.w r2, r2, r3, lsl #30
11c4: 4050 eors r0, r2
11c6: ea52 0293 orrs.w r2, r2, r3, lsr #2
11ca: bf1f itttt ne
11cc: ea81 01d3 eorne.w r1, r1, r3, lsr #3
11d0: 08e2 lsrne r2, r4, #3
11d2: ea42 7243 orrne.w r2, r2, r3, lsl #29
11d6: 4050 eorne r0, r2
11d8: bf18 it ne
11da: ea52 02d3 orrsne.w r2, r2, r3, lsr #3
11de: d00a beq.n 11f6 <decimal+0x66>
11e0: 0922 lsrs r2, r4, #4
11e2: ea42 7403 orr.w r4, r2, r3, lsl #28
11e6: ea81 1113 eor.w r1, r1, r3, lsr #4
11ea: 4060 eors r0, r4
11ec: ea54 1213 orrs.w r2, r4, r3, lsr #4
11f0: ea4f 1313 mov.w r3, r3, lsr #4
11f4: d1d6 bne.n 11a4 <decimal+0x14>
11f6: bdd0 pop {r4, r6, r7, pc}
Meta
rustc --version --verbose
:
rustc 1.78.0-nightly (3cbb93223 2024-03-13)
binary: rustc
commit-hash: 3cbb93223f33024db464a4df27a13c7cce870173
commit-date: 2024-03-13
host: x86_64-unknown-linux-gnu
release: 1.78.0-nightly
LLVM version: 18.1.0