-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inefficient codegen for eq
of enum with identical variants
#113506
Comments
Looks similar to #55030 I minimized this a bit to #[derive(PartialEq, Eq)]
pub enum MyEnum {
A(u64),
B(u64),
C(u64),
}
pub fn compare(a: &MyEnum, b: &MyEnum) -> bool {
*a == *b
} Which emits different LLVM IR with Here is the IR for the code above with define noundef zeroext i1 @_ZN7example7compare17had18f8c96abc6decE(ptr noalias nocapture noundef readonly align 4 dereferenceable(8) %a, ptr noalias nocapture noundef readonly align 4 dereferenceable(8) %b) unnamed_addr #0 !dbg !6 {
start:
%a.val = load i32, ptr %a, align 4, !dbg !11, !range !12, !noundef !10
%0 = getelementptr i8, ptr %a, i64 4, !dbg !11
%a.val1 = load i32, ptr %0, align 4, !dbg !11
%b.val = load i32, ptr %b, align 4, !dbg !11, !range !12, !noundef !10
%1 = getelementptr i8, ptr %b, i64 4, !dbg !11
%b.val2 = load i32, ptr %1, align 4, !dbg !11
%_5.i = icmp eq i32 %a.val, %b.val, !dbg !13
br i1 %_5.i, label %bb2.i, label %"_ZN56_$LT$example..MyEnum$u20$as$u20$core..cmp..PartialEq$GT$2eq17h895d84d9838af47eE.exit", !dbg !13
bb2.i: ; preds = %start
switch i32 %a.val, label %bb5.i [
i32 0, label %bb4.i
i32 1, label %bb6.i
i32 2, label %bb7.i
], !dbg !13
bb5.i: ; preds = %bb2.i
unreachable, !dbg !19
bb4.i: ; preds = %bb2.i
%2 = icmp eq i32 %a.val1, %b.val2, !dbg !21
br label %"_ZN56_$LT$example..MyEnum$u20$as$u20$core..cmp..PartialEq$GT$2eq17h895d84d9838af47eE.exit", !dbg !23
bb6.i: ; preds = %bb2.i
%3 = icmp eq i32 %a.val1, %b.val2, !dbg !24
br label %"_ZN56_$LT$example..MyEnum$u20$as$u20$core..cmp..PartialEq$GT$2eq17h895d84d9838af47eE.exit", !dbg !23
bb7.i: ; preds = %bb2.i
%4 = icmp eq i32 %a.val1, %b.val2, !dbg !26
br label %"_ZN56_$LT$example..MyEnum$u20$as$u20$core..cmp..PartialEq$GT$2eq17h895d84d9838af47eE.exit", !dbg !23
"_ZN56_$LT$example..MyEnum$u20$as$u20$core..cmp..PartialEq$GT$2eq17h895d84d9838af47eE.exit": ; preds = %start, %bb4.i, %bb6.i, %bb7.i
%.0.i = phi i1 [ false, %start ], [ %4, %bb7.i ], [ %3, %bb6.i ], [ %2, %bb4.i ]
ret i1 %.0.i, !dbg !28
} It is technically possible to optimize out these duplicate match arms before LLVM, but probably waste of time given the current state of MIR. I think special-casing the derive macro might be better, if we don't want to wait for LLVM. |
Upstream issue: llvm/llvm-project#64031. |
@rustbot claim |
@rustbot label llvm-fixed-upstream |
This did not get fixed by the LLVM 18 upgrade. I believe the problem is that we can only hoist instructions from some of the successors, so we'd need to perform some kind of edge splitting. |
Well, indeed, now otherwise it's not unreachable. I'm not sure splitting edge is always beneficial, but for this example is ok. |
Given an enum:
The generated comparison uses jump table despite every jump target being identical:
https://godbolt.org/z/6nWW53eb5
As far as I'm aware, this jump should have been optimized away entirely, probably to something like
With WASM target, it's even worse, as it doesn't deduplicate the identical match arms at all:
https://godbolt.org/z/Gf16rM4MY
The text was updated successfully, but these errors were encountered: