Skip to content
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

LLVM cannot remove switch even if all branches jump to same code #62570

Open
AngelicosPhosphoros opened this issue May 5, 2023 · 1 comment

Comments

@AngelicosPhosphoros
Copy link

AngelicosPhosphoros commented May 5, 2023

godbolt link

Code:

; ModuleID = 'playground.c03e094e-cgu.0'
source_filename = "playground.c03e094e-cgu.0"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%"MyEnum<'_>::A" = type { [1 x i64], { ptr, i64 } }
%"MyEnum<'_>::B" = type { [1 x i64], { ptr, i64 } }
%"MyEnum<'_>::C" = type { [1 x i64], { ptr, i64 } }
%"MyEnum<'_>::D" = type { [1 x i64], { ptr, i64 } }

; playground::test_bounds
; Function Attrs: mustprogress nofree norecurse nosync nounwind nonlazybind readonly willreturn uwtable
define noundef i64 @get_lengths(
    ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %en
) unnamed_addr #0 {
start:
  %_2 = load i64, ptr %en, align 8, !range !2, !noundef !3
  switch i64 %_2, label %bb2 [
    i64 0, label %bb3
    i64 1, label %bb4
    i64 2, label %bb5
    i64 3, label %bb1
  ]

bb2:                                              ; preds = %start
  unreachable

bb3:                                              ; preds = %start
  %0 = getelementptr inbounds %"MyEnum<'_>::A", ptr %en, i64 0, i32 1, i32 1
  br label %bb6

bb4:                                              ; preds = %start
  %1 = getelementptr inbounds %"MyEnum<'_>::B", ptr %en, i64 0, i32 1, i32 1
  br label %bb6

bb5:                                              ; preds = %start
  %2 = getelementptr inbounds %"MyEnum<'_>::C", ptr %en, i64 0, i32 1, i32 1
  br label %bb6

bb1:                                              ; preds = %start
  %3 = getelementptr inbounds %"MyEnum<'_>::D", ptr %en, i64 0, i32 1, i32 1
  br label %bb6

bb6:                                              ; preds = %bb3, %bb4, %bb5, %bb1
  %.0.in = phi ptr [ %3, %bb1 ], [ %2, %bb5 ], [ %1, %bb4 ], [ %0, %bb3 ]
  %.0 = load i64, ptr %.0.in, align 8
  ret i64 %.0
}

attributes #0 = {
    mustprogress
    nofree
    norecurse
    nosync
    nounwind
    nonlazybind
    readonly
    willreturn
    uwtable "probe-stack"="__rust_probestack"
    "target-cpu"="x86-64"
}

!llvm.module.flags = !{!0, !1}

!0 = !{i32 7, !"PIC Level", i32 2}
!1 = !{i32 2, !"RtLibUseGOT", i32 1}
!2 = !{i64 0, i64 4}
!3 = !{}

Generated ASM:

get_lengths:                            # @get_lengths
        mov     rax, qword ptr [rdi]
        jmp     qword ptr [8*rax + .LJTI0_0]
.LBB0_1:                                # %bb6
        mov     rax, qword ptr [rdi + 16]
        ret
.LJTI0_0:
        .quad   .LBB0_1
        .quad   .LBB0_1
        .quad   .LBB0_1
        .quad   .LBB0_1

If you look at the asm, it is clear that jump and jump-table can be removed because all branches jump to same place.

@nikic
Copy link
Contributor

nikic commented May 5, 2023

This will be fixed by https://discourse.llvm.org/t/rfc-replacing-getelementptr-with-ptradd/68699, or an intermediate step towards it (e.g. canonicalizing all constant GEPs to i8 in InstCombine would be sufficient).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants