-
Notifications
You must be signed in to change notification settings - Fork 14.1k
Description
I was code golfing different implementations for a function that "inverts" (rotates by 2) an enum with discriminants 1, 2, 4, 8 (i.e. f(1) = 4), the obvious implementation being this:
pub enum Side {
Top = 1 << 0,
Right = 1 << 1,
Bottom = 1 << 2,
Left = 1 << 3,
}
pub fn opposite_match(x: Side) -> Side {
use Side::*;
match x {
Top => Bottom,
Right => Left,
Bottom => Top,
Left => Right,
}
}I expected to see this happen: on riscv opposite_match produces the optimal code, or at least a reasonable one.
Instead, this happened: compiler generates the following asm:
opposite_match:
addi a0, a0, -1
slli a0, a0, 24
srai a0, a0, 24
lui a1, %hi(.Lswitch.table.opposite_match)
addi a1, a1, %lo(.Lswitch.table.opposite_match)
add a0, a1, a0
lbu a0, 0(a0)
example::table_lookup::T::h07c70895e308d45b:
.ascii "\004\b\004\001\004\004\004\002"The problem is the slli (shift left logical immediate) and srai (shift right arithmetic immediate) instructions -- those together are noop, since a0 <= 7 at that point and 7 << 24 < 1.rotate_right(1).
The underlying issue is that llvm at some point replaces indexing by u8 with indexing by u32, inserting a sext in the process; sext is not getting optimized out afterwards and is later lowered to ssli+srai. LLVM issue: llvm/llvm-project#124841.
If you write the lookup table by hand compiler generates better asm:
pub fn table_lookup(x: Side) -> Side {
static T: [Side; 8] = [
Side::Bottom, // <--
Side::Left, // <--
Side::Bottom,
Side::Top, // <--
Side::Bottom,
Side::Bottom,
Side::Bottom,
Side::Right, // <--
];
T[x as usize - 1]
}example::table_lookup::h8d56712109e87652:
lui a1, %hi(example::table_lookup::T::h07c70895e308d45b)
addi a1, a1, %lo(example::table_lookup::T::h07c70895e308d45b)
add a0, a1, a0
lbu a0, -1(a0)
ret
example::table_lookup::T::h07c70895e308d45b:
.ascii "\004\b\004\001\004\004\004\002"
There are no shifts and the -1 is merged into the the lbu (load byte unsigned).
Meta
rustc version:
1.86.0-nightly (2025-01-27 2f348cb7ce4063fa4eb4)