-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Open
Labels
llvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passesCovers the InstCombine, InstSimplify and AggressiveInstCombine passesmissed-optimization
Description
Here's some IR I got from rust on LLVM21 when matching on an enum:
define noundef range(i8 0, 101) i8 @match5(i8 noundef range(i8 0, 5) %0) unnamed_addr #2 {
start:
%1 = icmp ne i8 %0, 3
tail call void @llvm.assume(i1 %1)
%2 = add nsw i8 %0, -2
%3 = zext i8 %2 to i64
%4 = icmp samesign ugt i8 %0, 1
%5 = add nuw nsw i64 %3, 257 // <--
%_2 = select i1 %4, i64 %5, i64 258 // <--
switch i64 %_2, label %bb1 [ // <--
i64 257, label %bb5
i64 258, label %bb3
i64 259, label %bb2
]
bb1: ; preds = %start
unreachable
bb3: ; preds = %start
%6 = and i8 %0, 1
br label %bb5
bb2: ; preds = %start
br label %bb5
bb5: ; preds = %start, %bb2, %bb3
%_0.sroa.0.0 = phi i8 [ %6, %bb3 ], [ 100, %bb2 ], [ 13, %start ]
ret i8 %_0.sroa.0.0
}
Where on trunk it's a bit improved by not using i64
https://llvm.godbolt.org/z/4TqMdTKjW, but could still be much better.
Most notably, that %5 = add
is only used in the select
, which is only used in the switch
. As such, it can be removed entirely by adjusting the switch
arms accordingly: https://alive2.llvm.org/ce/z/mR6wBE
%_2 = select i1 %4, i64 %3, i64 1
switch i64 %_2, label %bb1 [
i64 0, label %bb5
i64 1, label %bb3
i64 2, label %bb2
]
And that would unblock other optimizations as well, for example having done it opt
can already remove the zext
as well, letting the switch
can stay over i8
(instead of i9
or i64
): https://llvm.godbolt.org/z/Ybf8zafGE
This is basically a follow-up to #134024 and #134086 and rust-lang/rust#144764, all of which are motivated by improving match
ing in Rust.
Metadata
Metadata
Assignees
Labels
llvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passesCovers the InstCombine, InstSimplify and AggressiveInstCombine passesmissed-optimization