; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -O3 -mtriple=arm64-apple-macosx -o - %s | FileCheck %s
; RUN: llc -O3 -mtriple=arm64-apple-macosx -global-isel -o - %s | FileCheck --check-prefix=GISEL %s

define i32 @switch_with_matching_dests_0_and_pow2_3_cases(i8 %v) {
; CHECK-LABEL: switch_with_matching_dests_0_and_pow2_3_cases:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    mov w9, #100 ; =0x64
; CHECK-NEXT:    mov w8, #20 ; =0x14
; CHECK-NEXT:  LBB0_1: ; %loop.header
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ands w10, w0, #0xff
; CHECK-NEXT:    b.eq LBB0_6
; CHECK-NEXT:  ; %bb.2: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT:    cmp w10, #32
; CHECK-NEXT:    b.eq LBB0_6
; CHECK-NEXT:  ; %bb.3: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT:    cmp w10, #124
; CHECK-NEXT:    b.eq LBB0_7
; CHECK-NEXT:  ; %bb.4: ; %loop.latch
; CHECK-NEXT:    ; in Loop: Header=BB0_1 Depth=1
; CHECK-NEXT:    subs w9, w9, #1
; CHECK-NEXT:    b.ne LBB0_1
; CHECK-NEXT:  ; %bb.5:
; CHECK-NEXT:    mov w8, #20 ; =0x14
; CHECK-NEXT:  LBB0_6: ; %common.ret
; CHECK-NEXT:    mov w0, w8
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB0_7: ; %e2
; CHECK-NEXT:    mov w0, #30 ; =0x1e
; CHECK-NEXT:    ret
;
; GISEL-LABEL: switch_with_matching_dests_0_and_pow2_3_cases:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    mov w8, w0
; GISEL-NEXT:    mov w0, #20 ; =0x14
; GISEL-NEXT:    mov w9, #100 ; =0x64
; GISEL-NEXT:  LBB0_1: ; %loop.header
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    ands w10, w8, #0xff
; GISEL-NEXT:    b.eq LBB0_5
; GISEL-NEXT:  ; %bb.2: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB0_1 Depth=1
; GISEL-NEXT:    cmp w10, #32
; GISEL-NEXT:    b.eq LBB0_5
; GISEL-NEXT:  ; %bb.3: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB0_1 Depth=1
; GISEL-NEXT:    cmp w10, #124
; GISEL-NEXT:    b.eq LBB0_6
; GISEL-NEXT:  ; %bb.4: ; %loop.latch
; GISEL-NEXT:    ; in Loop: Header=BB0_1 Depth=1
; GISEL-NEXT:    subs w9, w9, #1
; GISEL-NEXT:    b.ne LBB0_1
; GISEL-NEXT:  LBB0_5: ; %common.ret
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB0_6: ; %e2
; GISEL-NEXT:    mov w0, #30 ; =0x1e
; GISEL-NEXT:    ret
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  switch i8 %v, label %loop.latch [
  i8 32, label %e1
  i8 0, label %e1
  i8 124, label %e2
  ]

loop.latch:
  %iv.next = add i32 %iv, 1
  %c = icmp eq i32 %iv.next, 100
  br i1 %c, label %e1, label %loop.header

e1:
  ret i32 20

e2:
  ret i32 30
}

define i32 @switch_with_matching_dests_0_and_pow2_3_cases_swapped(i8 %v) {
; CHECK-LABEL: switch_with_matching_dests_0_and_pow2_3_cases_swapped:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    mov w9, #100 ; =0x64
; CHECK-NEXT:    mov w8, #20 ; =0x14
; CHECK-NEXT:  LBB1_1: ; %loop.header
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ands w10, w0, #0xff
; CHECK-NEXT:    b.eq LBB1_6
; CHECK-NEXT:  ; %bb.2: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB1_1 Depth=1
; CHECK-NEXT:    cmp w10, #32
; CHECK-NEXT:    b.eq LBB1_6
; CHECK-NEXT:  ; %bb.3: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB1_1 Depth=1
; CHECK-NEXT:    cmp w10, #124
; CHECK-NEXT:    b.eq LBB1_7
; CHECK-NEXT:  ; %bb.4: ; %loop.latch
; CHECK-NEXT:    ; in Loop: Header=BB1_1 Depth=1
; CHECK-NEXT:    subs w9, w9, #1
; CHECK-NEXT:    b.ne LBB1_1
; CHECK-NEXT:  ; %bb.5:
; CHECK-NEXT:    mov w8, #10 ; =0xa
; CHECK-NEXT:  LBB1_6: ; %common.ret
; CHECK-NEXT:    mov w0, w8
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB1_7: ; %e2
; CHECK-NEXT:    mov w0, #30 ; =0x1e
; CHECK-NEXT:    ret
;
; GISEL-LABEL: switch_with_matching_dests_0_and_pow2_3_cases_swapped:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    mov w9, #100 ; =0x64
; GISEL-NEXT:    mov w8, #20 ; =0x14
; GISEL-NEXT:  LBB1_1: ; %loop.header
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    ands w10, w0, #0xff
; GISEL-NEXT:    b.eq LBB1_6
; GISEL-NEXT:  ; %bb.2: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB1_1 Depth=1
; GISEL-NEXT:    cmp w10, #32
; GISEL-NEXT:    b.eq LBB1_6
; GISEL-NEXT:  ; %bb.3: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB1_1 Depth=1
; GISEL-NEXT:    cmp w10, #124
; GISEL-NEXT:    b.eq LBB1_7
; GISEL-NEXT:  ; %bb.4: ; %loop.latch
; GISEL-NEXT:    ; in Loop: Header=BB1_1 Depth=1
; GISEL-NEXT:    subs w9, w9, #1
; GISEL-NEXT:    b.ne LBB1_1
; GISEL-NEXT:  ; %bb.5:
; GISEL-NEXT:    mov w8, #10 ; =0xa
; GISEL-NEXT:  LBB1_6: ; %common.ret
; GISEL-NEXT:    mov w0, w8
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB1_7: ; %e2
; GISEL-NEXT:    mov w0, #30 ; =0x1e
; GISEL-NEXT:    ret
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  switch i8 %v, label %loop.latch [
  i8 0, label %e1
  i8 32, label %e1
  i8 124, label %e2
  ]

loop.latch:
  %iv.next = add i32 %iv, 1
  %c = icmp eq i32 %iv.next, 100
  br i1 %c, label %e0, label %loop.header

e0:
  ret i32 10

e1:
  ret i32 20

e2:
  ret i32 30
}

define i32 @switch_with_matching_dests_0_and_pow2_3_cases_with_phi(i8 %v, i1 %c) {
; CHECK-LABEL: switch_with_matching_dests_0_and_pow2_3_cases_with_phi:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    tbz w1, #0, LBB2_8
; CHECK-NEXT:  ; %bb.1: ; %loop.header.preheader
; CHECK-NEXT:    mov w9, #100 ; =0x64
; CHECK-NEXT:    mov w8, #20 ; =0x14
; CHECK-NEXT:  LBB2_2: ; %loop.header
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ands w10, w0, #0xff
; CHECK-NEXT:    b.eq LBB2_7
; CHECK-NEXT:  ; %bb.3: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB2_2 Depth=1
; CHECK-NEXT:    cmp w10, #32
; CHECK-NEXT:    b.eq LBB2_7
; CHECK-NEXT:  ; %bb.4: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB2_2 Depth=1
; CHECK-NEXT:    cmp w10, #124
; CHECK-NEXT:    b.eq LBB2_9
; CHECK-NEXT:  ; %bb.5: ; %loop.latch
; CHECK-NEXT:    ; in Loop: Header=BB2_2 Depth=1
; CHECK-NEXT:    subs w9, w9, #1
; CHECK-NEXT:    b.ne LBB2_2
; CHECK-NEXT:  ; %bb.6:
; CHECK-NEXT:    mov w8, #10 ; =0xa
; CHECK-NEXT:  LBB2_7: ; %common.ret
; CHECK-NEXT:    mov w0, w8
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB2_8:
; CHECK-NEXT:    mov w0, wzr
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB2_9: ; %e2
; CHECK-NEXT:    mov w0, #30 ; =0x1e
; CHECK-NEXT:    ret
;
; GISEL-LABEL: switch_with_matching_dests_0_and_pow2_3_cases_with_phi:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    mov w8, wzr
; GISEL-NEXT:    tbz w1, #0, LBB2_7
; GISEL-NEXT:  ; %bb.1: ; %loop.header.preheader
; GISEL-NEXT:    mov w9, #100 ; =0x64
; GISEL-NEXT:    mov w8, #20 ; =0x14
; GISEL-NEXT:  LBB2_2: ; %loop.header
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    ands w10, w0, #0xff
; GISEL-NEXT:    b.eq LBB2_7
; GISEL-NEXT:  ; %bb.3: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB2_2 Depth=1
; GISEL-NEXT:    cmp w10, #32
; GISEL-NEXT:    b.eq LBB2_7
; GISEL-NEXT:  ; %bb.4: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB2_2 Depth=1
; GISEL-NEXT:    cmp w10, #124
; GISEL-NEXT:    b.eq LBB2_8
; GISEL-NEXT:  ; %bb.5: ; %loop.latch
; GISEL-NEXT:    ; in Loop: Header=BB2_2 Depth=1
; GISEL-NEXT:    subs w9, w9, #1
; GISEL-NEXT:    b.ne LBB2_2
; GISEL-NEXT:  ; %bb.6:
; GISEL-NEXT:    mov w8, #10 ; =0xa
; GISEL-NEXT:  LBB2_7: ; %common.ret
; GISEL-NEXT:    mov w0, w8
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB2_8: ; %e2
; GISEL-NEXT:    mov w0, #30 ; =0x1e
; GISEL-NEXT:    ret
entry:
  br i1 %c, label %then, label %e1

then:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %then], [ %iv.next, %loop.latch ]
  switch i8 %v, label %loop.latch [
  i8 32, label %e1
  i8 0, label %e1
  i8 124, label %e2
  ]

loop.latch:
  %iv.next = add i32 %iv, 1
  %ec = icmp eq i32 %iv.next, 100
  br i1 %ec, label %e0, label %loop.header

e0:
  ret i32 10

e1:
  %p = phi i32 [ 0, %entry ], [ 20, %loop.header ], [ 20, %loop.header ]
  ret i32 %p

e2:
  ret i32 30
}

define i32 @switch_with_matching_dests_0_and_pow2_3_cases_all_different_succs(i8 %v) {
; CHECK-LABEL: switch_with_matching_dests_0_and_pow2_3_cases_all_different_succs:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    mov w8, #100 ; =0x64
; CHECK-NEXT:  LBB3_1: ; %loop.header
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ands w9, w0, #0xff
; CHECK-NEXT:    b.eq LBB3_6
; CHECK-NEXT:  ; %bb.2: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB3_1 Depth=1
; CHECK-NEXT:    cmp w9, #32
; CHECK-NEXT:    b.eq LBB3_8
; CHECK-NEXT:  ; %bb.3: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB3_1 Depth=1
; CHECK-NEXT:    cmp w9, #124
; CHECK-NEXT:    b.eq LBB3_7
; CHECK-NEXT:  ; %bb.4: ; %loop.latch
; CHECK-NEXT:    ; in Loop: Header=BB3_1 Depth=1
; CHECK-NEXT:    subs w8, w8, #1
; CHECK-NEXT:    b.ne LBB3_1
; CHECK-NEXT:  ; %bb.5:
; CHECK-NEXT:    mov w0, #10 ; =0xa
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB3_6: ; %e2
; CHECK-NEXT:    mov w0, #30 ; =0x1e
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB3_7: ; %e3
; CHECK-NEXT:    mov w0, #40 ; =0x28
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB3_8:
; CHECK-NEXT:    mov w0, #20 ; =0x14
; CHECK-NEXT:    ret
;
; GISEL-LABEL: switch_with_matching_dests_0_and_pow2_3_cases_all_different_succs:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    mov w8, #100 ; =0x64
; GISEL-NEXT:  LBB3_1: ; %loop.header
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    ands w9, w0, #0xff
; GISEL-NEXT:    b.eq LBB3_6
; GISEL-NEXT:  ; %bb.2: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB3_1 Depth=1
; GISEL-NEXT:    cmp w9, #32
; GISEL-NEXT:    b.eq LBB3_8
; GISEL-NEXT:  ; %bb.3: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB3_1 Depth=1
; GISEL-NEXT:    cmp w9, #124
; GISEL-NEXT:    b.eq LBB3_7
; GISEL-NEXT:  ; %bb.4: ; %loop.latch
; GISEL-NEXT:    ; in Loop: Header=BB3_1 Depth=1
; GISEL-NEXT:    subs w8, w8, #1
; GISEL-NEXT:    b.ne LBB3_1
; GISEL-NEXT:  ; %bb.5:
; GISEL-NEXT:    mov w0, #10 ; =0xa
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB3_6: ; %e2
; GISEL-NEXT:    mov w0, #30 ; =0x1e
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB3_7: ; %e3
; GISEL-NEXT:    mov w0, #40 ; =0x28
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB3_8:
; GISEL-NEXT:    mov w0, #20 ; =0x14
; GISEL-NEXT:    ret
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  switch i8 %v, label %loop.latch [
  i8 32, label %e1
  i8 0, label %e2
  i8 124, label %e3
  ]

loop.latch:
  %iv.next = add i32 %iv, 1
  %ec = icmp eq i32 %iv.next, 100
  br i1 %ec, label %e0, label %loop.header

e0:
  ret i32 10

e1:
  ret i32 20

e2:
  ret i32 30

e3:
  ret i32 40
}

define i32 @switch_in_loop_with_matching_dests_0_and_pow2_3_cases(ptr %start) {
; CHECK-LABEL: switch_in_loop_with_matching_dests_0_and_pow2_3_cases:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    add x8, x0, #1
; CHECK-NEXT:  LBB4_1: ; %loop
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ldrb w9, [x8], #1
; CHECK-NEXT:    cbz w9, LBB4_4
; CHECK-NEXT:  ; %bb.2: ; %loop
; CHECK-NEXT:    ; in Loop: Header=BB4_1 Depth=1
; CHECK-NEXT:    cmp w9, #124
; CHECK-NEXT:    b.eq LBB4_5
; CHECK-NEXT:  ; %bb.3: ; %loop
; CHECK-NEXT:    ; in Loop: Header=BB4_1 Depth=1
; CHECK-NEXT:    cmp w9, #32
; CHECK-NEXT:    b.ne LBB4_1
; CHECK-NEXT:  LBB4_4: ; %e1
; CHECK-NEXT:    mov w0, #-1 ; =0xffffffff
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB4_5: ; %e2.loopexit
; CHECK-NEXT:    mov w0, wzr
; CHECK-NEXT:    ret
;
; GISEL-LABEL: switch_in_loop_with_matching_dests_0_and_pow2_3_cases:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    add x8, x0, #1
; GISEL-NEXT:  LBB4_1: ; %loop
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    ldrb w9, [x8], #1
; GISEL-NEXT:    cbz w9, LBB4_4
; GISEL-NEXT:  ; %bb.2: ; %loop
; GISEL-NEXT:    ; in Loop: Header=BB4_1 Depth=1
; GISEL-NEXT:    cmp w9, #124
; GISEL-NEXT:    b.eq LBB4_5
; GISEL-NEXT:  ; %bb.3: ; %loop
; GISEL-NEXT:    ; in Loop: Header=BB4_1 Depth=1
; GISEL-NEXT:    cmp w9, #32
; GISEL-NEXT:    b.ne LBB4_1
; GISEL-NEXT:  LBB4_4: ; %e1
; GISEL-NEXT:    mov w0, #-1 ; =0xffffffff
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB4_5: ; %e2.loopexit
; GISEL-NEXT:    mov w0, wzr
; GISEL-NEXT:    ret
entry:
  br label %loop

loop:
  %p = phi ptr [ %start, %entry ], [ %4, %loop ]
  %4 = getelementptr inbounds nuw i8, ptr %p, i64 1
  %l = load i8, ptr %4, align 1
  switch i8 %l, label %loop [
  i8 32, label %e1
  i8 0, label %e1
  i8 124, label %e2
  ]

e1:
  br label %e2

e2:
  %8 = phi i32 [ -1, %e1 ], [ 0, %loop ]
  ret i32 %8
}

define i32 @switch_in_loop_with_matching_dests_0_and_pow2_4_cases(ptr %start) {
; CHECK-LABEL: switch_in_loop_with_matching_dests_0_and_pow2_4_cases:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    mov x10, #32769 ; =0x8001
; CHECK-NEXT:    mov w8, #1 ; =0x1
; CHECK-NEXT:    add x9, x0, #1
; CHECK-NEXT:    movk x10, #1, lsl #32
; CHECK-NEXT:    b LBB5_2
; CHECK-NEXT:  LBB5_1: ; %loop
; CHECK-NEXT:    ; in Loop: Header=BB5_2 Depth=1
; CHECK-NEXT:    cmp w11, #124
; CHECK-NEXT:    b.eq LBB5_5
; CHECK-NEXT:  LBB5_2: ; %loop
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ldrb w11, [x9], #1
; CHECK-NEXT:    cmp w11, #32
; CHECK-NEXT:    b.hi LBB5_1
; CHECK-NEXT:  ; %bb.3: ; %loop
; CHECK-NEXT:    ; in Loop: Header=BB5_2 Depth=1
; CHECK-NEXT:    lsl x12, x8, x11
; CHECK-NEXT:    tst x12, x10
; CHECK-NEXT:    b.eq LBB5_1
; CHECK-NEXT:  ; %bb.4: ; %e1
; CHECK-NEXT:    mov w0, #-1 ; =0xffffffff
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB5_5: ; %e2.loopexit
; CHECK-NEXT:    mov w0, wzr
; CHECK-NEXT:    ret
;
; GISEL-LABEL: switch_in_loop_with_matching_dests_0_and_pow2_4_cases:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    mov x10, #32769 ; =0x8001
; GISEL-NEXT:    mov w8, #1 ; =0x1
; GISEL-NEXT:    add x9, x0, #1
; GISEL-NEXT:    movk x10, #1, lsl #32
; GISEL-NEXT:    b LBB5_2
; GISEL-NEXT:  LBB5_1: ; %loop
; GISEL-NEXT:    ; in Loop: Header=BB5_2 Depth=1
; GISEL-NEXT:    cmp w11, #124
; GISEL-NEXT:    b.eq LBB5_5
; GISEL-NEXT:  LBB5_2: ; %loop
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    ldrb w11, [x9], #1
; GISEL-NEXT:    cmp w11, #32
; GISEL-NEXT:    b.hi LBB5_1
; GISEL-NEXT:  ; %bb.3: ; %loop
; GISEL-NEXT:    ; in Loop: Header=BB5_2 Depth=1
; GISEL-NEXT:    lsl x12, x8, x11
; GISEL-NEXT:    tst x12, x10
; GISEL-NEXT:    b.eq LBB5_1
; GISEL-NEXT:  ; %bb.4: ; %e1
; GISEL-NEXT:    mov w0, #-1 ; =0xffffffff
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB5_5: ; %e2.loopexit
; GISEL-NEXT:    mov w0, wzr
; GISEL-NEXT:    ret
entry:
  br label %loop

loop:
  %p = phi ptr [ %start, %entry ], [ %4, %loop ]
  %4 = getelementptr inbounds nuw i8, ptr %p, i64 1
  %l = load i8, ptr %4, align 1
  switch i8 %l, label %loop [
  i8 0, label %e1
  i8 15, label %e1
  i8 32, label %e1
  i8 124, label %e2
  ]

e1:
  br label %e2

e2:
  %8 = phi i32 [ -1, %e1 ], [ 0, %loop ]
  ret i32 %8
}

define i32 @switch_in_loop_with_matching_dests_0_and_non_pow2(ptr %start) {
; CHECK-LABEL: switch_in_loop_with_matching_dests_0_and_non_pow2:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    add x8, x0, #1
; CHECK-NEXT:  LBB6_1: ; %loop
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ldrb w9, [x8], #1
; CHECK-NEXT:    cmp w9, #35
; CHECK-NEXT:    b.eq LBB6_4
; CHECK-NEXT:  ; %bb.2: ; %loop
; CHECK-NEXT:    ; in Loop: Header=BB6_1 Depth=1
; CHECK-NEXT:    cmp w9, #33
; CHECK-NEXT:    b.eq LBB6_5
; CHECK-NEXT:  ; %bb.3: ; %loop
; CHECK-NEXT:    ; in Loop: Header=BB6_1 Depth=1
; CHECK-NEXT:    cbnz w9, LBB6_1
; CHECK-NEXT:  LBB6_4: ; %common.ret.loopexit
; CHECK-NEXT:    mov w0, #-1 ; =0xffffffff
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB6_5: ; %e2
; CHECK-NEXT:    mov w0, #10 ; =0xa
; CHECK-NEXT:    ret
;
; GISEL-LABEL: switch_in_loop_with_matching_dests_0_and_non_pow2:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    add x8, x0, #1
; GISEL-NEXT:  LBB6_1: ; %loop
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    ldrb w9, [x8], #1
; GISEL-NEXT:    cmp w9, #35
; GISEL-NEXT:    b.eq LBB6_4
; GISEL-NEXT:  ; %bb.2: ; %loop
; GISEL-NEXT:    ; in Loop: Header=BB6_1 Depth=1
; GISEL-NEXT:    cmp w9, #33
; GISEL-NEXT:    b.eq LBB6_5
; GISEL-NEXT:  ; %bb.3: ; %loop
; GISEL-NEXT:    ; in Loop: Header=BB6_1 Depth=1
; GISEL-NEXT:    cbnz w9, LBB6_1
; GISEL-NEXT:  LBB6_4: ; %common.ret.loopexit
; GISEL-NEXT:    mov w0, #-1 ; =0xffffffff
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB6_5: ; %e2
; GISEL-NEXT:    mov w0, #10 ; =0xa
; GISEL-NEXT:    ret
entry:
  br label %loop

loop:
  %p = phi ptr [ %start, %entry ], [ %4, %loop ]
  %4 = getelementptr inbounds nuw i8, ptr %p, i64 1
  %l = load i8, ptr %4, align 1
  switch i8 %l, label %loop [
  i8 0, label %e1
  i8 35, label %e1
  i8 33, label %e2
  ]

e1:
  ret i32 -1

e2:
  ret i32 10
}

define void @test_successor_with_loop_phi(ptr %A, ptr %B) {
; CHECK-LABEL: test_successor_with_loop_phi:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:  LBB7_1: ; %loop
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ldr w8, [x0]
; CHECK-NEXT:    str wzr, [x0]
; CHECK-NEXT:    mov x0, x1
; CHECK-NEXT:    tst w8, #0xfffffffb
; CHECK-NEXT:    b.eq LBB7_1
; CHECK-NEXT:  ; %bb.2: ; %exit
; CHECK-NEXT:    ret
;
; GISEL-LABEL: test_successor_with_loop_phi:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:  LBB7_1: ; %loop
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    ldr w8, [x0]
; GISEL-NEXT:    str wzr, [x0]
; GISEL-NEXT:    mov x0, x1
; GISEL-NEXT:    cbz w8, LBB7_1
; GISEL-NEXT:  ; %bb.2: ; %loop
; GISEL-NEXT:    ; in Loop: Header=BB7_1 Depth=1
; GISEL-NEXT:    cmp w8, #4
; GISEL-NEXT:    mov x0, x1
; GISEL-NEXT:    b.eq LBB7_1
; GISEL-NEXT:  ; %bb.3: ; %exit
; GISEL-NEXT:    ret
entry:
  br label %loop

loop:
  %p = phi ptr [ %A, %entry ], [ %B , %loop ], [ %B, %loop ]
  %l = load i32, ptr %p
  store i32 0, ptr %p
  switch i32 %l, label %exit [
  i32 4, label %loop
  i32 0, label %loop
  ]

exit:
  ret void
}

define i64 @consecutive_match_both(ptr %p, i32 %param) {
; CHECK-LABEL: consecutive_match_both:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    mov w8, #1 ; =0x1
; CHECK-NEXT:    mov w9, #100 ; =0x64
; CHECK-NEXT:    mov w10, #249 ; =0xf9
; CHECK-NEXT:    lsl w8, w8, w1
; CHECK-NEXT:    b LBB8_2
; CHECK-NEXT:  LBB8_1: ; %loop.latch
; CHECK-NEXT:    ; in Loop: Header=BB8_2 Depth=1
; CHECK-NEXT:    subs w9, w9, #1
; CHECK-NEXT:    b.eq LBB8_5
; CHECK-NEXT:  LBB8_2: ; %loop.header
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    cmp w1, #7
; CHECK-NEXT:    b.hi LBB8_1
; CHECK-NEXT:  ; %bb.3: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB8_2 Depth=1
; CHECK-NEXT:    tst w8, w10
; CHECK-NEXT:    b.eq LBB8_1
; CHECK-NEXT:  ; %bb.4: ; %e0
; CHECK-NEXT:    mov x0, xzr
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB8_5:
; CHECK-NEXT:    mov x0, #-42 ; =0xffffffffffffffd6
; CHECK-NEXT:    ret
;
; GISEL-LABEL: consecutive_match_both:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    mov w8, #1 ; =0x1
; GISEL-NEXT:    mov w9, #100 ; =0x64
; GISEL-NEXT:    mov w10, #249 ; =0xf9
; GISEL-NEXT:    lsl w8, w8, w1
; GISEL-NEXT:    b LBB8_2
; GISEL-NEXT:  LBB8_1: ; %loop.latch
; GISEL-NEXT:    ; in Loop: Header=BB8_2 Depth=1
; GISEL-NEXT:    subs w9, w9, #1
; GISEL-NEXT:    b.eq LBB8_5
; GISEL-NEXT:  LBB8_2: ; %loop.header
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    cmp w1, #7
; GISEL-NEXT:    b.hi LBB8_1
; GISEL-NEXT:  ; %bb.3: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB8_2 Depth=1
; GISEL-NEXT:    tst w8, w10
; GISEL-NEXT:    b.eq LBB8_1
; GISEL-NEXT:  ; %bb.4: ; %e0
; GISEL-NEXT:    mov x0, xzr
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB8_5:
; GISEL-NEXT:    mov x0, #-42 ; =0xffffffffffffffd6
; GISEL-NEXT:    ret
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  switch i32 %param, label %loop.latch [
  i32 7, label %e0
  i32 6, label %e0
  i32 5, label %e0
  i32 4, label %e0
  i32 3, label %e0
  i32 0, label %e0
  ]

loop.latch:
  %iv.next = add i32 %iv, 1
  %ec = icmp eq i32 %iv.next, 100
  br i1 %ec, label %e1, label %loop.header

e0:
  %m = getelementptr i8, ptr %p, i64 20
  br label %e1

e1:
  %res = phi i64 [ 0, %e0 ], [ -42, %loop.latch ]
  ret i64 %res
}

define i64 @consecutive_match_before(ptr %p, i32 %param) {
; CHECK-LABEL: consecutive_match_before:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    mov w8, #1 ; =0x1
; CHECK-NEXT:    mov w9, #100 ; =0x64
; CHECK-NEXT:    mov w10, #25 ; =0x19
; CHECK-NEXT:    lsl w8, w8, w1
; CHECK-NEXT:    b LBB9_2
; CHECK-NEXT:  LBB9_1: ; %loop.latch
; CHECK-NEXT:    ; in Loop: Header=BB9_2 Depth=1
; CHECK-NEXT:    subs w9, w9, #1
; CHECK-NEXT:    b.eq LBB9_5
; CHECK-NEXT:  LBB9_2: ; %loop.header
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    cmp w1, #4
; CHECK-NEXT:    b.hi LBB9_1
; CHECK-NEXT:  ; %bb.3: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB9_2 Depth=1
; CHECK-NEXT:    tst w8, w10
; CHECK-NEXT:    b.eq LBB9_1
; CHECK-NEXT:  ; %bb.4: ; %e0
; CHECK-NEXT:    mov x0, xzr
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB9_5:
; CHECK-NEXT:    mov x0, #-42 ; =0xffffffffffffffd6
; CHECK-NEXT:    ret
;
; GISEL-LABEL: consecutive_match_before:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    mov w8, #1 ; =0x1
; GISEL-NEXT:    mov w9, #100 ; =0x64
; GISEL-NEXT:    mov w10, #25 ; =0x19
; GISEL-NEXT:    lsl w8, w8, w1
; GISEL-NEXT:    b LBB9_2
; GISEL-NEXT:  LBB9_1: ; %loop.latch
; GISEL-NEXT:    ; in Loop: Header=BB9_2 Depth=1
; GISEL-NEXT:    subs w9, w9, #1
; GISEL-NEXT:    b.eq LBB9_5
; GISEL-NEXT:  LBB9_2: ; %loop.header
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    cmp w1, #4
; GISEL-NEXT:    b.hi LBB9_1
; GISEL-NEXT:  ; %bb.3: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB9_2 Depth=1
; GISEL-NEXT:    tst w8, w10
; GISEL-NEXT:    b.eq LBB9_1
; GISEL-NEXT:  ; %bb.4: ; %e0
; GISEL-NEXT:    mov x0, xzr
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB9_5:
; GISEL-NEXT:    mov x0, #-42 ; =0xffffffffffffffd6
; GISEL-NEXT:    ret
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  switch i32 %param, label %loop.latch [
  i32 4, label %e0
  i32 3, label %e0
  i32 0, label %e0
  ]

loop.latch:
  %iv.next = add i32 %iv, 1
  %ec = icmp eq i32 %iv.next, 100
  br i1 %ec, label %e1, label %loop.header

e0:
  %m = getelementptr i8, ptr %p, i64 20
  br label %e1

e1:
  %res = phi i64 [ 0, %e0 ], [ -42, %loop.latch ]
  ret i64 %res
}

define i64 @consecutive_match_after(ptr %p, i32 %param) {
; CHECK-LABEL: consecutive_match_after:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    mov w8, #1 ; =0x1
; CHECK-NEXT:    mov w9, #100 ; =0x64
; CHECK-NEXT:    mov w10, #49 ; =0x31
; CHECK-NEXT:    lsl w8, w8, w1
; CHECK-NEXT:    b LBB10_2
; CHECK-NEXT:  LBB10_1: ; %loop.latch
; CHECK-NEXT:    ; in Loop: Header=BB10_2 Depth=1
; CHECK-NEXT:    subs w9, w9, #1
; CHECK-NEXT:    b.eq LBB10_5
; CHECK-NEXT:  LBB10_2: ; %loop.header
; CHECK-NEXT:    ; =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    cmp w1, #5
; CHECK-NEXT:    b.hi LBB10_1
; CHECK-NEXT:  ; %bb.3: ; %loop.header
; CHECK-NEXT:    ; in Loop: Header=BB10_2 Depth=1
; CHECK-NEXT:    tst w8, w10
; CHECK-NEXT:    b.eq LBB10_1
; CHECK-NEXT:  ; %bb.4: ; %e0
; CHECK-NEXT:    mov x0, xzr
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB10_5:
; CHECK-NEXT:    mov x0, #-42 ; =0xffffffffffffffd6
; CHECK-NEXT:    ret
;
; GISEL-LABEL: consecutive_match_after:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    mov w8, #1 ; =0x1
; GISEL-NEXT:    mov w9, #100 ; =0x64
; GISEL-NEXT:    mov w10, #49 ; =0x31
; GISEL-NEXT:    lsl w8, w8, w1
; GISEL-NEXT:    b LBB10_2
; GISEL-NEXT:  LBB10_1: ; %loop.latch
; GISEL-NEXT:    ; in Loop: Header=BB10_2 Depth=1
; GISEL-NEXT:    subs w9, w9, #1
; GISEL-NEXT:    b.eq LBB10_5
; GISEL-NEXT:  LBB10_2: ; %loop.header
; GISEL-NEXT:    ; =>This Inner Loop Header: Depth=1
; GISEL-NEXT:    cmp w1, #5
; GISEL-NEXT:    b.hi LBB10_1
; GISEL-NEXT:  ; %bb.3: ; %loop.header
; GISEL-NEXT:    ; in Loop: Header=BB10_2 Depth=1
; GISEL-NEXT:    tst w8, w10
; GISEL-NEXT:    b.eq LBB10_1
; GISEL-NEXT:  ; %bb.4: ; %e0
; GISEL-NEXT:    mov x0, xzr
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB10_5:
; GISEL-NEXT:    mov x0, #-42 ; =0xffffffffffffffd6
; GISEL-NEXT:    ret
entry:
  br label %loop.header

loop.header:
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.latch ]
  switch i32 %param, label %loop.latch [
  i32 5, label %e0
  i32 4, label %e0
  i32 0, label %e0
  ]

loop.latch:
  %iv.next = add i32 %iv, 1
  %ec = icmp eq i32 %iv.next, 100
  br i1 %ec, label %e1, label %loop.header

e0:
  %m = getelementptr i8, ptr %p, i64 20
  br label %e1

e1:
  %res = phi i64 [ 0, %e0 ], [ -42, %loop.latch ]
  ret i64 %res
}

define void @merge_with_stores(ptr %A, i16 %v) {
; CHECK-LABEL: merge_with_stores:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    and w8, w1, #0xffff
; CHECK-NEXT:    sub w9, w8, #10
; CHECK-NEXT:    cmp w9, #2
; CHECK-NEXT:    b.lo LBB11_4
; CHECK-NEXT:  ; %bb.1: ; %entry
; CHECK-NEXT:    cbz w8, LBB11_5
; CHECK-NEXT:  ; %bb.2: ; %entry
; CHECK-NEXT:    cmp w8, #2
; CHECK-NEXT:    b.eq LBB11_5
; CHECK-NEXT:  ; %bb.3: ; %default.dst
; CHECK-NEXT:    strh wzr, [x0]
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB11_4: ; %other.dst
; CHECK-NEXT:    mov w8, #1 ; =0x1
; CHECK-NEXT:    strh w8, [x0, #36]
; CHECK-NEXT:  LBB11_5: ; %pow2.dst
; CHECK-NEXT:    ret
;
; GISEL-LABEL: merge_with_stores:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    and w8, w1, #0xffff
; GISEL-NEXT:    sub w9, w8, #10
; GISEL-NEXT:    cmp w9, #1
; GISEL-NEXT:    b.ls LBB11_4
; GISEL-NEXT:  ; %bb.1: ; %entry
; GISEL-NEXT:    cbz w8, LBB11_5
; GISEL-NEXT:  ; %bb.2: ; %entry
; GISEL-NEXT:    cmp w8, #2
; GISEL-NEXT:    b.eq LBB11_5
; GISEL-NEXT:  ; %bb.3: ; %default.dst
; GISEL-NEXT:    strh wzr, [x0]
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB11_4: ; %other.dst
; GISEL-NEXT:    mov w8, #1 ; =0x1
; GISEL-NEXT:    strh w8, [x0, #36]
; GISEL-NEXT:  LBB11_5: ; %pow2.dst
; GISEL-NEXT:    ret
entry:
  switch i16 %v, label %default.dst [
    i16 10, label %other.dst
    i16 0, label %pow2.dst
    i16 2, label %pow2.dst
    i16 11, label %other.dst
  ]

default.dst:
  store i16 0, ptr %A, align 8
  br label %pow2.dst

other.dst:
  %gep = getelementptr i8, ptr %A, i64 36
  store i16 1, ptr %gep, align 8
  br label %pow2.dst

pow2.dst:
  ret void
}

define void @switch_large_enough_for_clustering(i32 %x, ptr %dst) {
; CHECK-LABEL: switch_large_enough_for_clustering:
; CHECK:       ; %bb.0: ; %entry
; CHECK-NEXT:    cmp w0, #1
; CHECK-NEXT:    b.le LBB12_5
; CHECK-NEXT:  ; %bb.1: ; %entry
; CHECK-NEXT:    cmp w0, #7
; CHECK-NEXT:    b.eq LBB12_9
; CHECK-NEXT:  ; %bb.2: ; %entry
; CHECK-NEXT:    cmp w0, #4
; CHECK-NEXT:    b.eq LBB12_7
; CHECK-NEXT:  ; %bb.3: ; %entry
; CHECK-NEXT:    cmp w0, #2
; CHECK-NEXT:    b.eq LBB12_8
; CHECK-NEXT:  LBB12_4: ; %exit
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB12_5: ; %entry
; CHECK-NEXT:    cbz w0, LBB12_8
; CHECK-NEXT:  ; %bb.6: ; %entry
; CHECK-NEXT:    cmp w0, #1
; CHECK-NEXT:    b.ne LBB12_4
; CHECK-NEXT:  LBB12_7: ; %succ.2
; CHECK-NEXT:    str wzr, [x1]
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB12_8: ; %succ.1
; CHECK-NEXT:    strb wzr, [x1]
; CHECK-NEXT:    ret
; CHECK-NEXT:  LBB12_9: ; %succ.3
; CHECK-NEXT:    strh wzr, [x1]
; CHECK-NEXT:    ret
;
; GISEL-LABEL: switch_large_enough_for_clustering:
; GISEL:       ; %bb.0: ; %entry
; GISEL-NEXT:    cmp w0, #2
; GISEL-NEXT:    b.lt LBB12_5
; GISEL-NEXT:  ; %bb.1: ; %entry
; GISEL-NEXT:    cmp w0, #7
; GISEL-NEXT:    b.eq LBB12_9
; GISEL-NEXT:  ; %bb.2: ; %entry
; GISEL-NEXT:    cmp w0, #4
; GISEL-NEXT:    b.eq LBB12_7
; GISEL-NEXT:  ; %bb.3: ; %entry
; GISEL-NEXT:    cmp w0, #2
; GISEL-NEXT:    b.eq LBB12_8
; GISEL-NEXT:  LBB12_4: ; %exit
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB12_5: ; %entry
; GISEL-NEXT:    cbz w0, LBB12_8
; GISEL-NEXT:  ; %bb.6: ; %entry
; GISEL-NEXT:    cmp w0, #1
; GISEL-NEXT:    b.ne LBB12_4
; GISEL-NEXT:  LBB12_7: ; %succ.2
; GISEL-NEXT:    str wzr, [x1]
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB12_8: ; %succ.1
; GISEL-NEXT:    strb wzr, [x1]
; GISEL-NEXT:    ret
; GISEL-NEXT:  LBB12_9: ; %succ.3
; GISEL-NEXT:    strh wzr, [x1]
; GISEL-NEXT:    ret
entry:
  switch i32 %x, label %exit [
    i32 0, label %succ.1
    i32 2, label %succ.1
    i32 1, label %succ.2
    i32 4, label %succ.2
    i32 7, label %succ.3
  ]

succ.1:
  store i8 0, ptr %dst
  br label %exit

succ.2:
  call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 4, i1 false)
  br label %exit

succ.3:
  call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 2, i1 false)
  br label %exit

exit:
  ret void
}

declare void @llvm.memset.p0.i64(ptr writeonly captures(none), i8, i64, i1 immarg)
