llvm/llvm/test/Transforms/SimplifyCFG/hoist-common-code-with-unreachable.ll

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes='simplifycfg<hoist-common-insts;no-sink-common-insts>' -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s

define i1 @common_instr_with_unreachable(i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: @common_instr_with_unreachable(
; CHECK-NEXT:  start:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
; CHECK-NEXT:    ret i1 [[TMP0]]
;
start:
  switch i64 %a, label %unreachable [
  i64 0, label %bb0
  i64 1, label %bb1
  i64 2, label %bb2
  ]

unreachable:
  unreachable

bb0:                                              ; preds = %start
  %0 = icmp eq i64 %b, %c
  br label %exit

bb1:                                              ; preds = %start
  %1 = icmp eq i64 %b, %c
  br label %exit

bb2:                                              ; preds = %start
  %2 = icmp eq i64 %b, %c
  br label %exit

exit:                                             ; preds = %bb2, %bb1, %bb0
  %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
  ret i1 %result
}

define i1 @common_instr_with_unreachable_2(i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: @common_instr_with_unreachable_2(
; CHECK-NEXT:  start:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
; CHECK-NEXT:    ret i1 [[TMP0]]
;
start:
  switch i64 %a, label %bb1 [
  i64 0, label %bb0
  i64 1, label %unreachable
  i64 2, label %bb2
  ]

unreachable:
  unreachable

bb0:                                              ; preds = %start
  %0 = icmp eq i64 %b, %c
  br label %exit

bb1:                                              ; preds = %start
  %1 = icmp eq i64 %b, %c
  br label %exit

bb2:                                              ; preds = %start
  %2 = icmp eq i64 %b, %c
  br label %exit

exit:                                             ; preds = %bb2, %bb1, %bb0
  %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
  ret i1 %result
}

define i1 @not_only_unreachable(i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: @not_only_unreachable(
; CHECK-NEXT:  start:
; CHECK-NEXT:    switch i64 [[A:%.*]], label [[UNREACHABLE:%.*]] [
; CHECK-NEXT:      i64 0, label [[BB0:%.*]]
; CHECK-NEXT:      i64 1, label [[BB1:%.*]]
; CHECK-NEXT:      i64 2, label [[BB2:%.*]]
; CHECK-NEXT:    ]
; CHECK:       unreachable:
; CHECK-NEXT:    call void @no_return()
; CHECK-NEXT:    unreachable
; CHECK:       bb0:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[B:%.*]], [[C:%.*]]
; CHECK-NEXT:    call void @foo()
; CHECK-NEXT:    br label [[EXIT:%.*]]
; CHECK:       bb1:
; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[B]], [[C]]
; CHECK-NEXT:    call void @foo()
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       bb2:
; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[B]], [[C]]
; CHECK-NEXT:    call void @foo()
; CHECK-NEXT:    br label [[EXIT]]
; CHECK:       exit:
; CHECK-NEXT:    [[RESULT:%.*]] = phi i1 [ [[TMP0]], [[BB0]] ], [ [[TMP1]], [[BB1]] ], [ [[TMP2]], [[BB2]] ]
; CHECK-NEXT:    ret i1 [[RESULT]]
;
start:
  switch i64 %a, label %unreachable [
  i64 0, label %bb0
  i64 1, label %bb1
  i64 2, label %bb2
  ]

unreachable:
  call void @no_return()
  unreachable

bb0:                                              ; preds = %start
  %0 = icmp eq i64 %b, %c
  call void @foo()
  br label %exit

bb1:                                              ; preds = %start
  %1 = icmp eq i64 %b, %c
  call void @foo()
  br label %exit

bb2:                                              ; preds = %start
  %2 = icmp eq i64 %b, %c
  call void @foo()
  br label %exit

exit:                                             ; preds = %bb2, %bb1, %bb0
  %result = phi i1 [ %0, %bb0 ], [ %1, %bb1 ], [ %2, %bb2 ]
  ret i1 %result
}

; If we can hoist a musttail call,
; we can and have to hoist subsequent bitcast and ret instructions.
define ptr @switch_musttail_call(ptr %arg) {
; CHECK-LABEL: @switch_musttail_call(
; CHECK-NEXT:  bb:
; CHECK-NEXT:    [[P0:%.*]] = musttail call ptr @musttail_call(ptr [[ARG:%.*]])
; CHECK-NEXT:    ret ptr [[P0]]
;
bb:
  %load = load i16, ptr %arg, align 2
  switch i16 %load, label %unreachable [
  i16 0, label %bb0
  i16 1, label %bb1
  i16 2, label %bb2
  ]

unreachable:
  unreachable

bb0:
  %p0 = musttail call ptr @musttail_call(ptr %arg)
  ret ptr %p0

bb1:
  %p1 = musttail call ptr @musttail_call(ptr %arg)
  ret ptr %p1

bb2:
  %p2 = musttail call ptr @musttail_call(ptr %arg)
  ret ptr %p2
}

declare void @no_return()
declare void @foo()
declare ptr @musttail_call(ptr)