llvm/llvm/test/Transforms/Attributor/range.ll

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC

; FIXME: CGSCC is not looking at callees and calleers even though it could be allowed.

define i32 @test0(ptr %p) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
; CHECK-LABEL: define {{[^@]+}}@test0
; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0:![0-9]+]]
; CHECK-NEXT:    ret i32 [[A]]
;
  %a = load i32, ptr %p, !range !0
  ret i32 %a
}

define i32 @test0-range-check(ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
; TUNIT-LABEL: define {{[^@]+}}@test0-range-check
; TUNIT-SAME: (ptr nocapture nofree readonly align 4 [[P:%.*]]) #[[ATTR0]] {
; TUNIT-NEXT:    [[A:%.*]] = tail call i32 @test0(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3:[0-9]+]], !range [[RNG0]]
; TUNIT-NEXT:    ret i32 [[A]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)
; CGSCC-LABEL: define {{[^@]+}}@test0-range-check
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR1:[0-9]+]] {
; CGSCC-NEXT:    [[A:%.*]] = tail call i32 @test0(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P]]) #[[ATTR5:[0-9]+]]
; CGSCC-NEXT:    ret i32 [[A]]
;
  %a = tail call i32 @test0(ptr %p)
  ret i32 %a
}

declare void @use3-dummy(i1, i1, i1)
define void @use3(i1, i1, i1) {
; CHECK-LABEL: define {{[^@]+}}@use3
; CHECK-SAME: (i1 [[TMP0:%.*]], i1 [[TMP1:%.*]], i1 [[TMP2:%.*]]) {
; CHECK-NEXT:    tail call void @use3-dummy(i1 [[TMP0]], i1 [[TMP1]], i1 [[TMP2]])
; CHECK-NEXT:    ret void
;
  tail call void @use3-dummy(i1 %0, i1 %1, i1 %2)
  ret void
}

; TEST0 icmp test
define void @test0-icmp-check(ptr %p){
  ; ret = [0, 10)
; TUNIT-LABEL: define {{[^@]+}}@test0-icmp-check
; TUNIT-SAME: (ptr nocapture nofree readonly align 4 [[P:%.*]]) {
; TUNIT-NEXT:    [[RET:%.*]] = tail call i32 @test0(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3]]
; TUNIT-NEXT:    [[CMP_EQ_1:%.*]] = icmp eq i32 [[RET]], 10
; TUNIT-NEXT:    [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
; TUNIT-NEXT:    [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
; TUNIT-NEXT:    [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
; TUNIT-NEXT:    [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
; TUNIT-NEXT:    [[CMP_EQ_6:%.*]] = icmp eq i32 [[RET]], -1
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_EQ_1]], i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 [[CMP_EQ_6]])
; TUNIT-NEXT:    [[CMP_NE_1:%.*]] = icmp ne i32 [[RET]], 10
; TUNIT-NEXT:    [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
; TUNIT-NEXT:    [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
; TUNIT-NEXT:    [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
; TUNIT-NEXT:    [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
; TUNIT-NEXT:    [[CMP_NE_6:%.*]] = icmp ne i32 [[RET]], -1
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_NE_1]], i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 [[CMP_NE_6]])
; TUNIT-NEXT:    [[CMP_UGT_1:%.*]] = icmp ugt i32 [[RET]], 10
; TUNIT-NEXT:    [[CMP_UGT_2:%.*]] = icmp ugt i32 [[RET]], 9
; TUNIT-NEXT:    [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
; TUNIT-NEXT:    [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
; TUNIT-NEXT:    [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_UGT_1]], i1 [[CMP_UGT_2]], i1 [[CMP_UGT_3]])
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 noundef false)
; TUNIT-NEXT:    [[CMP_UGE_1:%.*]] = icmp uge i32 [[RET]], 10
; TUNIT-NEXT:    [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
; TUNIT-NEXT:    [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
; TUNIT-NEXT:    [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
; TUNIT-NEXT:    [[CMP_UGE_6:%.*]] = icmp uge i32 [[RET]], -1
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_UGE_1]], i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_UGE_4]], i1 noundef true, i1 [[CMP_UGE_6]])
; TUNIT-NEXT:    [[CMP_SGT_1:%.*]] = icmp sgt i32 [[RET]], 10
; TUNIT-NEXT:    [[CMP_SGT_2:%.*]] = icmp sgt i32 [[RET]], 9
; TUNIT-NEXT:    [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
; TUNIT-NEXT:    [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
; TUNIT-NEXT:    [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
; TUNIT-NEXT:    [[CMP_SGT_6:%.*]] = icmp sgt i32 [[RET]], -1
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_SGT_1]], i1 [[CMP_SGT_2]], i1 [[CMP_SGT_3]])
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 [[CMP_SGT_6]])
; TUNIT-NEXT:    [[CMP_GTE_1:%.*]] = icmp sge i32 [[RET]], 10
; TUNIT-NEXT:    [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
; TUNIT-NEXT:    [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
; TUNIT-NEXT:    [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
; TUNIT-NEXT:    [[CMP_GTE_5:%.*]] = icmp sge i32 [[RET]], 0
; TUNIT-NEXT:    [[CMP_GTE_6:%.*]] = icmp sge i32 [[RET]], -1
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_GTE_1]], i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_GTE_4]], i1 [[CMP_GTE_5]], i1 [[CMP_GTE_6]])
; TUNIT-NEXT:    [[CMP_SLT_1:%.*]] = icmp slt i32 [[RET]], 10
; TUNIT-NEXT:    [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
; TUNIT-NEXT:    [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
; TUNIT-NEXT:    [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
; TUNIT-NEXT:    [[CMP_SLT_5:%.*]] = icmp slt i32 [[RET]], 0
; TUNIT-NEXT:    [[CMP_SLT_6:%.*]] = icmp slt i32 [[RET]], -1
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_SLT_1]], i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_SLT_4]], i1 [[CMP_SLT_5]], i1 [[CMP_SLT_6]])
; TUNIT-NEXT:    [[CMP_LTE_1:%.*]] = icmp sle i32 [[RET]], 10
; TUNIT-NEXT:    [[CMP_LTE_2:%.*]] = icmp sle i32 [[RET]], 9
; TUNIT-NEXT:    [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
; TUNIT-NEXT:    [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
; TUNIT-NEXT:    [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
; TUNIT-NEXT:    [[CMP_LTE_6:%.*]] = icmp sle i32 [[RET]], -1
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_LTE_1]], i1 [[CMP_LTE_2]], i1 [[CMP_LTE_3]])
; TUNIT-NEXT:    tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 [[CMP_LTE_6]])
; TUNIT-NEXT:    ret void
;
; CGSCC-LABEL: define {{[^@]+}}@test0-icmp-check
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) {
; CGSCC-NEXT:    [[RET:%.*]] = tail call i32 @test0(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P]]) #[[ATTR5]]
; CGSCC-NEXT:    [[CMP_EQ_1:%.*]] = icmp eq i32 [[RET]], 10
; CGSCC-NEXT:    [[CMP_EQ_2:%.*]] = icmp eq i32 [[RET]], 9
; CGSCC-NEXT:    [[CMP_EQ_3:%.*]] = icmp eq i32 [[RET]], 8
; CGSCC-NEXT:    [[CMP_EQ_4:%.*]] = icmp eq i32 [[RET]], 1
; CGSCC-NEXT:    [[CMP_EQ_5:%.*]] = icmp eq i32 [[RET]], 0
; CGSCC-NEXT:    [[CMP_EQ_6:%.*]] = icmp eq i32 [[RET]], -1
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_EQ_1]], i1 [[CMP_EQ_2]], i1 [[CMP_EQ_3]])
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_EQ_4]], i1 [[CMP_EQ_5]], i1 [[CMP_EQ_6]])
; CGSCC-NEXT:    [[CMP_NE_1:%.*]] = icmp ne i32 [[RET]], 10
; CGSCC-NEXT:    [[CMP_NE_2:%.*]] = icmp ne i32 [[RET]], 9
; CGSCC-NEXT:    [[CMP_NE_3:%.*]] = icmp ne i32 [[RET]], 8
; CGSCC-NEXT:    [[CMP_NE_4:%.*]] = icmp ne i32 [[RET]], 1
; CGSCC-NEXT:    [[CMP_NE_5:%.*]] = icmp ne i32 [[RET]], 0
; CGSCC-NEXT:    [[CMP_NE_6:%.*]] = icmp ne i32 [[RET]], -1
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_NE_1]], i1 [[CMP_NE_2]], i1 [[CMP_NE_3]])
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_NE_4]], i1 [[CMP_NE_5]], i1 [[CMP_NE_6]])
; CGSCC-NEXT:    [[CMP_UGT_1:%.*]] = icmp ugt i32 [[RET]], 10
; CGSCC-NEXT:    [[CMP_UGT_2:%.*]] = icmp ugt i32 [[RET]], 9
; CGSCC-NEXT:    [[CMP_UGT_3:%.*]] = icmp ugt i32 [[RET]], 8
; CGSCC-NEXT:    [[CMP_UGT_4:%.*]] = icmp ugt i32 [[RET]], 1
; CGSCC-NEXT:    [[CMP_UGT_5:%.*]] = icmp ugt i32 [[RET]], 0
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_UGT_1]], i1 [[CMP_UGT_2]], i1 [[CMP_UGT_3]])
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_UGT_4]], i1 [[CMP_UGT_5]], i1 noundef false)
; CGSCC-NEXT:    [[CMP_UGE_1:%.*]] = icmp uge i32 [[RET]], 10
; CGSCC-NEXT:    [[CMP_UGE_2:%.*]] = icmp uge i32 [[RET]], 9
; CGSCC-NEXT:    [[CMP_UGE_3:%.*]] = icmp uge i32 [[RET]], 8
; CGSCC-NEXT:    [[CMP_UGE_4:%.*]] = icmp uge i32 [[RET]], 1
; CGSCC-NEXT:    [[CMP_UGE_6:%.*]] = icmp uge i32 [[RET]], -1
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_UGE_1]], i1 [[CMP_UGE_2]], i1 [[CMP_UGE_3]])
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_UGE_4]], i1 noundef true, i1 [[CMP_UGE_6]])
; CGSCC-NEXT:    [[CMP_SGT_1:%.*]] = icmp sgt i32 [[RET]], 10
; CGSCC-NEXT:    [[CMP_SGT_2:%.*]] = icmp sgt i32 [[RET]], 9
; CGSCC-NEXT:    [[CMP_SGT_3:%.*]] = icmp sgt i32 [[RET]], 8
; CGSCC-NEXT:    [[CMP_SGT_4:%.*]] = icmp sgt i32 [[RET]], 1
; CGSCC-NEXT:    [[CMP_SGT_5:%.*]] = icmp sgt i32 [[RET]], 0
; CGSCC-NEXT:    [[CMP_SGT_6:%.*]] = icmp sgt i32 [[RET]], -1
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_SGT_1]], i1 [[CMP_SGT_2]], i1 [[CMP_SGT_3]])
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_SGT_4]], i1 [[CMP_SGT_5]], i1 [[CMP_SGT_6]])
; CGSCC-NEXT:    [[CMP_GTE_1:%.*]] = icmp sge i32 [[RET]], 10
; CGSCC-NEXT:    [[CMP_GTE_2:%.*]] = icmp sge i32 [[RET]], 9
; CGSCC-NEXT:    [[CMP_GTE_3:%.*]] = icmp sge i32 [[RET]], 8
; CGSCC-NEXT:    [[CMP_GTE_4:%.*]] = icmp sge i32 [[RET]], 1
; CGSCC-NEXT:    [[CMP_GTE_5:%.*]] = icmp sge i32 [[RET]], 0
; CGSCC-NEXT:    [[CMP_GTE_6:%.*]] = icmp sge i32 [[RET]], -1
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_GTE_1]], i1 [[CMP_GTE_2]], i1 [[CMP_GTE_3]])
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_GTE_4]], i1 [[CMP_GTE_5]], i1 [[CMP_GTE_6]])
; CGSCC-NEXT:    [[CMP_SLT_1:%.*]] = icmp slt i32 [[RET]], 10
; CGSCC-NEXT:    [[CMP_SLT_2:%.*]] = icmp slt i32 [[RET]], 9
; CGSCC-NEXT:    [[CMP_SLT_3:%.*]] = icmp slt i32 [[RET]], 8
; CGSCC-NEXT:    [[CMP_SLT_4:%.*]] = icmp slt i32 [[RET]], 1
; CGSCC-NEXT:    [[CMP_SLT_5:%.*]] = icmp slt i32 [[RET]], 0
; CGSCC-NEXT:    [[CMP_SLT_6:%.*]] = icmp slt i32 [[RET]], -1
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_SLT_1]], i1 [[CMP_SLT_2]], i1 [[CMP_SLT_3]])
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_SLT_4]], i1 [[CMP_SLT_5]], i1 [[CMP_SLT_6]])
; CGSCC-NEXT:    [[CMP_LTE_1:%.*]] = icmp sle i32 [[RET]], 10
; CGSCC-NEXT:    [[CMP_LTE_2:%.*]] = icmp sle i32 [[RET]], 9
; CGSCC-NEXT:    [[CMP_LTE_3:%.*]] = icmp sle i32 [[RET]], 8
; CGSCC-NEXT:    [[CMP_LTE_4:%.*]] = icmp sle i32 [[RET]], 1
; CGSCC-NEXT:    [[CMP_LTE_5:%.*]] = icmp sle i32 [[RET]], 0
; CGSCC-NEXT:    [[CMP_LTE_6:%.*]] = icmp sle i32 [[RET]], -1
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_LTE_1]], i1 [[CMP_LTE_2]], i1 [[CMP_LTE_3]])
; CGSCC-NEXT:    tail call void @use3(i1 [[CMP_LTE_4]], i1 [[CMP_LTE_5]], i1 [[CMP_LTE_6]])
; CGSCC-NEXT:    ret void
;
  %ret = tail call i32 @test0(ptr %p)

  ; ret = [0, 10), eq
  %cmp-eq-1 = icmp eq i32 %ret, 10
  %cmp-eq-2 = icmp eq i32 %ret, 9
  %cmp-eq-3 = icmp eq i32 %ret, 8
  %cmp-eq-4 = icmp eq i32 %ret, 1
  %cmp-eq-5 = icmp eq i32 %ret, 0
  %cmp-eq-6 = icmp eq i32 %ret, -1
  tail call void @use3(i1 %cmp-eq-1, i1 %cmp-eq-2, i1 %cmp-eq-3)
  tail call void @use3(i1 %cmp-eq-4, i1 %cmp-eq-5, i1 %cmp-eq-6)

  ; ret = [0, 10), ne
  %cmp-ne-1 = icmp ne i32 %ret, 10
  %cmp-ne-2 = icmp ne i32 %ret, 9
  %cmp-ne-3 = icmp ne i32 %ret, 8
  %cmp-ne-4 = icmp ne i32 %ret, 1
  %cmp-ne-5 = icmp ne i32 %ret, 0
  %cmp-ne-6 = icmp ne i32 %ret, -1
  tail call void @use3(i1 %cmp-ne-1, i1 %cmp-ne-2, i1 %cmp-ne-3)
  tail call void @use3(i1 %cmp-ne-4, i1 %cmp-ne-5, i1 %cmp-ne-6)

  ; ret = [0, 10), ugt
  %cmp-ugt-1 = icmp ugt i32 %ret, 10
  %cmp-ugt-2 = icmp ugt i32 %ret, 9
  %cmp-ugt-3 = icmp ugt i32 %ret, 8
  %cmp-ugt-4 = icmp ugt i32 %ret, 1
  %cmp-ugt-5 = icmp ugt i32 %ret, 0
  %cmp-ugt-6 = icmp ugt i32 %ret, -1
  tail call void @use3(i1 %cmp-ugt-1, i1 %cmp-ugt-2, i1 %cmp-ugt-3)
  tail call void @use3(i1 %cmp-ugt-4, i1 %cmp-ugt-5, i1 %cmp-ugt-6)

  ; ret = [0, 10), uge
  %cmp-uge-1 = icmp uge i32 %ret, 10
  %cmp-uge-2 = icmp uge i32 %ret, 9
  %cmp-uge-3 = icmp uge i32 %ret, 8
  %cmp-uge-4 = icmp uge i32 %ret, 1
  %cmp-uge-5 = icmp uge i32 %ret, 0
  %cmp-uge-6 = icmp uge i32 %ret, -1
  tail call void @use3(i1 %cmp-uge-1, i1 %cmp-uge-2, i1 %cmp-uge-3)
  tail call void @use3(i1 %cmp-uge-4, i1 %cmp-uge-5, i1 %cmp-uge-6)

  ; ret = [0, 10), sgt
  %cmp-sgt-1 = icmp sgt i32 %ret, 10
  %cmp-sgt-2 = icmp sgt i32 %ret, 9
  %cmp-sgt-3 = icmp sgt i32 %ret, 8
  %cmp-sgt-4 = icmp sgt i32 %ret, 1
  %cmp-sgt-5 = icmp sgt i32 %ret, 0
  %cmp-sgt-6 = icmp sgt i32 %ret, -1
  tail call void @use3(i1 %cmp-sgt-1, i1 %cmp-sgt-2, i1 %cmp-sgt-3)
  tail call void @use3(i1 %cmp-sgt-4, i1 %cmp-sgt-5, i1 %cmp-sgt-6)

  ; ret = [0, 10), sge
  %cmp-gte-1 = icmp sge i32 %ret, 10
  %cmp-gte-2 = icmp sge i32 %ret, 9
  %cmp-gte-3 = icmp sge i32 %ret, 8
  %cmp-gte-4 = icmp sge i32 %ret, 1
  %cmp-gte-5 = icmp sge i32 %ret, 0
  %cmp-gte-6 = icmp sge i32 %ret, -1
  tail call void @use3(i1 %cmp-gte-1, i1 %cmp-gte-2, i1 %cmp-gte-3)
  tail call void @use3(i1 %cmp-gte-4, i1 %cmp-gte-5, i1 %cmp-gte-6)

  ; ret = [0, 10), slt
  %cmp-slt-1 = icmp slt i32 %ret, 10
  %cmp-slt-2 = icmp slt i32 %ret, 9
  %cmp-slt-3 = icmp slt i32 %ret, 8
  %cmp-slt-4 = icmp slt i32 %ret, 1
  %cmp-slt-5 = icmp slt i32 %ret, 0
  %cmp-slt-6 = icmp slt i32 %ret, -1
  tail call void @use3(i1 %cmp-slt-1, i1 %cmp-slt-2, i1 %cmp-slt-3)
  tail call void @use3(i1 %cmp-slt-4, i1 %cmp-slt-5, i1 %cmp-slt-6)

  ; ret = [0, 10), sle
  %cmp-lte-1 = icmp sle i32 %ret, 10
  %cmp-lte-2 = icmp sle i32 %ret, 9
  %cmp-lte-3 = icmp sle i32 %ret, 8
  %cmp-lte-4 = icmp sle i32 %ret, 1
  %cmp-lte-5 = icmp sle i32 %ret, 0
  %cmp-lte-6 = icmp sle i32 %ret, -1
  tail call void @use3(i1 %cmp-lte-1, i1 %cmp-lte-2, i1 %cmp-lte-3)
  tail call void @use3(i1 %cmp-lte-4, i1 %cmp-lte-5, i1 %cmp-lte-6)

  ret void
}
define i32 @test1(ptr %p) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
; CHECK-LABEL: define {{[^@]+}}@test1
; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    [[LOAD_10_100:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG1:![0-9]+]]
; CHECK-NEXT:    [[ADD_10_THEN_20_110:%.*]] = add i32 [[LOAD_10_100]], 10
; CHECK-NEXT:    [[MUL_10_THEN_200_1091:%.*]] = mul i32 [[ADD_10_THEN_20_110]], 10
; CHECK-NEXT:    ret i32 [[MUL_10_THEN_200_1091]]
;
  %load-10-100 = load i32, ptr %p, !range !1
  %add-10-then-20-110 = add i32 %load-10-100, 10
  %mul-10-then-200-1091 = mul i32 %add-10-then-20-110, 10
  ret i32 %mul-10-then-200-1091
}

define i1 @test1-check(ptr %p) {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
; TUNIT-LABEL: define {{[^@]+}}@test1-check
; TUNIT-SAME: (ptr nocapture nofree readonly align 4 [[P:%.*]]) #[[ATTR0]] {
; TUNIT-NEXT:    [[RES:%.*]] = tail call i32 @test1(ptr nocapture nofree noundef readonly align 4 [[P]]) #[[ATTR3]], !range [[RNG2:![0-9]+]]
; TUNIT-NEXT:    [[CMP:%.*]] = icmp eq i32 [[RES]], 500
; TUNIT-NEXT:    ret i1 [[CMP]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)
; CGSCC-LABEL: define {{[^@]+}}@test1-check
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR1]] {
; CGSCC-NEXT:    [[RES:%.*]] = tail call i32 @test1(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P]]) #[[ATTR5]]
; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq i32 [[RES]], 500
; CGSCC-NEXT:    ret i1 [[CMP]]
;
  %res = tail call i32 @test1(ptr %p)
  %cmp = icmp eq i32 %res, 500
  ret i1 %cmp
}

;  TEST2
;  int test2(int *p) { return *p == 0 ? 4 : 3; }
;  int test2_check(int *p) {
;    int call = test2(p);
;    if (call == 5) {
;      // dead block
;      return 2;
;    } else {
;      return 3;
;    }
;  }

define i32 @test2(ptr %p) {
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
; CHECK-LABEL: define {{[^@]+}}@test2
; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[P]], align 4
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0
; CHECK-NEXT:    [[COND:%.*]] = select i1 [[TOBOOL]], i32 4, i32 3
; CHECK-NEXT:    ret i32 [[COND]]
;
entry:
  %0 = load i32, ptr %p, align 4
  %tobool = icmp eq i32 %0, 0
  %cond = select i1 %tobool, i32 4, i32 3
  ret i32 %cond
}

define i32 @test2_check(ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@test2_check
; TUNIT-SAME: (ptr nocapture nofree readnone align 4 [[P:%.*]]) #[[ATTR1:[0-9]+]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    br label [[IF_THEN:%.*]]
; TUNIT:       if.then:
; TUNIT-NEXT:    br label [[RETURN:%.*]]
; TUNIT:       if.end:
; TUNIT-NEXT:    unreachable
; TUNIT:       return:
; TUNIT-NEXT:    ret i32 2
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)
; CGSCC-LABEL: define {{[^@]+}}@test2_check
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR1]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    [[CALL:%.*]] = tail call i32 @test2(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[P]]) #[[ATTR5]]
; CGSCC-NEXT:    [[CMP:%.*]] = icmp slt i32 [[CALL]], 5
; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CGSCC:       if.then:
; CGSCC-NEXT:    br label [[RETURN:%.*]]
; CGSCC:       if.end:
; CGSCC-NEXT:    br label [[RETURN]]
; CGSCC:       return:
; CGSCC-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ 2, [[IF_THEN]] ], [ 3, [[IF_END]] ]
; CGSCC-NEXT:    ret i32 [[RETVAL_0]]
;
entry:
  %call = tail call i32 @test2(ptr %p)
  %cmp = icmp slt i32 %call, 5
  br i1 %cmp, label %if.then, label %if.end

if.then:                                          ; preds = %entry
  br label %return

if.end:                                           ; preds = %entry
  br label %return

return:                                           ; preds = %if.end, %if.then
  %retval.0 = phi i32 [ 2, %if.then ], [ 3, %if.end ]
  ret i32 %retval.0
}

; TEST 3 SECV test

; void unkown();
; int r1(unsigned int u){
;   int sum = 0;
;   for(int i = 0; i<100;i++){
;     sum += i;
;   }
;   // sum = 50 * 49 / 2
;   if(sum > 10000){
;   // dead block
;     return 20;
;   }else {
;     return 10;
;   }
; }
; void f1(int u){
;   if(r1(u) > 15){
;   // deadblock
;     unkown();
;   }else {
;     return;
;   }
; }

declare dso_local void @unkown()

define internal i32 @r1(i32) local_unnamed_addr {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@r1
; TUNIT-SAME: () local_unnamed_addr #[[ATTR1]] {
; TUNIT-NEXT:    br label [[TMP4:%.*]]
; TUNIT:       1:
; TUNIT-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000
; TUNIT-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]]
; TUNIT:       3:
; TUNIT-NEXT:    ret i32 20
; TUNIT:       f:
; TUNIT-NEXT:    ret i32 10
; TUNIT:       4:
; TUNIT-NEXT:    [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ]
; TUNIT-NEXT:    [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ]
; TUNIT-NEXT:    [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]]
; TUNIT-NEXT:    [[TMP8]] = add nuw nsw i32 [[TMP5]], 1
; TUNIT-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100
; TUNIT-NEXT:    br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@r1
; CGSCC-SAME: () local_unnamed_addr #[[ATTR2:[0-9]+]] {
; CGSCC-NEXT:    br label [[TMP4:%.*]]
; CGSCC:       1:
; CGSCC-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000
; CGSCC-NEXT:    br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]]
; CGSCC:       3:
; CGSCC-NEXT:    ret i32 20
; CGSCC:       f:
; CGSCC-NEXT:    ret i32 10
; CGSCC:       4:
; CGSCC-NEXT:    [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ]
; CGSCC-NEXT:    [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ]
; CGSCC-NEXT:    [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]]
; CGSCC-NEXT:    [[TMP8]] = add nuw nsw i32 [[TMP5]], 1
; CGSCC-NEXT:    [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100
; CGSCC-NEXT:    br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]]
;
  br label %5

2:                                                ; preds = %5
  %3 = icmp sgt i32 %8, 10000
  br i1 %3, label %4, label %f
4:
  ret i32 20
f:
  ret i32 10
5:                                                ; preds = %5, %1
  %6 = phi i32 [ 0, %1 ], [ %9, %5 ]
  %7 = phi i32 [ 0, %1 ], [ %8, %5 ]
  %8 = add nuw nsw i32 %6, %7
  %9 = add nuw nsw i32 %6, 1
  %10 = icmp eq i32 %9, 100
  br i1 %10, label %2, label %5
}

define void @f1(i32){
; TUNIT-LABEL: define {{[^@]+}}@f1
; TUNIT-SAME: (i32 [[TMP0:%.*]]) {
; TUNIT-NEXT:    [[TMP2:%.*]] = tail call i32 @r1() #[[ATTR4:[0-9]+]]
; TUNIT-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 15
; TUNIT-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
; TUNIT:       4:
; TUNIT-NEXT:    tail call void @unkown()
; TUNIT-NEXT:    br label [[TMP5]]
; TUNIT:       5:
; TUNIT-NEXT:    ret void
;
; CGSCC-LABEL: define {{[^@]+}}@f1
; CGSCC-SAME: (i32 [[TMP0:%.*]]) {
; CGSCC-NEXT:    [[TMP2:%.*]] = tail call i32 @r1() #[[ATTR6:[0-9]+]]
; CGSCC-NEXT:    [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 15
; CGSCC-NEXT:    br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]]
; CGSCC:       4:
; CGSCC-NEXT:    tail call void @unkown()
; CGSCC-NEXT:    br label [[TMP5]]
; CGSCC:       5:
; CGSCC-NEXT:    ret void
;
  %2 = tail call i32 @r1(i32 %0)
  %3 = icmp sgt i32 %2, 15
  br i1 %3, label %4, label %5

4:                                                ; preds = %1
  tail call void @unkown()
  br label %5

5:                                                ; preds = %1, %4
  ret void
}

; TEST4 LVI test

; f1
; int test4-f1(int u){
;   if(u>=0) {
;     return u;
;   }else{
;     return 0;
;   }
; }
define dso_local i32 @test4-f1(i32 %u) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@test4-f1
; TUNIT-SAME: (i32 [[U:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[U]], -1
; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
; TUNIT:       if.then:
; TUNIT-NEXT:    br label [[RETURN]]
; TUNIT:       return:
; TUNIT-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[U]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
; TUNIT-NEXT:    ret i32 [[RETVAL_0]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@test4-f1
; CGSCC-SAME: (i32 [[U:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[U]], -1
; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
; CGSCC:       if.then:
; CGSCC-NEXT:    br label [[RETURN]]
; CGSCC:       return:
; CGSCC-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[U]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ]
; CGSCC-NEXT:    ret i32 [[RETVAL_0]]
;
; FIXME: RETVAL_0 >= 0
entry:
  %cmp = icmp sgt i32 %u, -1
  br i1 %cmp, label %if.then, label %return

if.then:                                          ; preds = %entry
  br label %return

return:                                           ; preds = %entry, %if.then
  %retval.0 = phi i32 [ %u, %if.then ], [ 0, %entry ]
  ret i32 %retval.0
}


define dso_local i32 @test4-g1(i32 %u) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@test4-g1
; TUNIT-SAME: (i32 [[U:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]]) #[[ATTR4]]
; TUNIT-NEXT:    ret i32 [[CALL]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@test4-g1
; CGSCC-SAME: (i32 [[U:%.*]]) #[[ATTR3:[0-9]+]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]]) #[[ATTR7:[0-9]+]]
; CGSCC-NEXT:    ret i32 [[CALL]]
;
; FIXME: %call should have range [0, inf]

entry:
  %call = tail call i32 @test4-f1(i32 %u)
  ret i32 %call
}

; f2
; int test4-f1(int u){
;   if(u>-1) {
;     return u+1;
;   }else{
;     return 1;
;   }
; }
define dso_local i32 @test4-f2(i32 %u) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@test4-f2
; TUNIT-SAME: (i32 [[U:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[U]], -1
; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; TUNIT:       if.then:
; TUNIT-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[U]], 1
; TUNIT-NEXT:    br label [[RETURN:%.*]]
; TUNIT:       if.else:
; TUNIT-NEXT:    br label [[RETURN]]
; TUNIT:       return:
; TUNIT-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[IF_ELSE]] ]
; TUNIT-NEXT:    ret i32 [[RETVAL_0]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@test4-f2
; CGSCC-SAME: (i32 [[U:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[U]], -1
; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
; CGSCC:       if.then:
; CGSCC-NEXT:    [[ADD:%.*]] = add nuw nsw i32 [[U]], 1
; CGSCC-NEXT:    br label [[RETURN:%.*]]
; CGSCC:       if.else:
; CGSCC-NEXT:    br label [[RETURN]]
; CGSCC:       return:
; CGSCC-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[IF_ELSE]] ]
; CGSCC-NEXT:    ret i32 [[RETVAL_0]]
;
entry:
  %cmp = icmp sgt i32 %u, -1
  br i1 %cmp, label %if.then, label %if.else

if.then:                                          ; preds = %entry
  %add = add nuw nsw i32 %u, 1
  br label %return

if.else:                                          ; preds = %entry
  br label %return

return:                                           ; preds = %if.else, %if.then
  %retval.0 = phi i32 [ %add, %if.then ], [ 1, %if.else ]
  ret i32 %retval.0
}


define dso_local i32 @test4-g2(i32 %u) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@test4-g2
; TUNIT-SAME: (i32 [[U:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) #[[ATTR4]], !range [[RNG3:![0-9]+]]
; TUNIT-NEXT:    ret i32 [[CALL]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@test4-g2
; CGSCC-SAME: (i32 [[U:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) #[[ATTR7]]
; CGSCC-NEXT:    ret i32 [[CALL]]
;
entry:
  %call = tail call i32 @test4-f2(i32 %u)
  ret i32 %call
}

define dso_local i32 @test-5() {
; TUNIT-LABEL: define {{[^@]+}}@test-5() {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    [[CALL:%.*]] = call i32 @rec(i32 noundef 0)
; TUNIT-NEXT:    ret i32 [[CALL]]
;
; CGSCC-LABEL: define {{[^@]+}}@test-5() {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    [[CALL:%.*]] = call noundef i32 @rec(i32 noundef 0)
; CGSCC-NEXT:    ret i32 [[CALL]]
;
entry:
  %call = call i32 @rec(i32 0)
  ret i32 %call
}
define internal i32 @rec(i32 %depth) {
; CHECK-LABEL: define {{[^@]+}}@rec
; CHECK-SAME: (i32 [[DEPTH:%.*]]) {
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[CALL:%.*]] = call i32 @foo(i32 [[DEPTH]])
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i32 [[CALL]], 0
; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK:       if.then:
; CHECK-NEXT:    br label [[RETURN:%.*]]
; CHECK:       if.end:
; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[DEPTH]], 10
; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_END3:%.*]]
; CHECK:       if.then1:
; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[DEPTH]], 1
; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @rec(i32 [[ADD]])
; CHECK-NEXT:    br label [[IF_END3]]
; CHECK:       if.end3:
; CHECK-NEXT:    br label [[RETURN]]
; CHECK:       return:
; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ 0, [[IF_THEN]] ], [ 1, [[IF_END3]] ]
; CHECK-NEXT:    ret i32 [[RETVAL_0]]
;
entry:
  %call = call i32 @foo(i32 %depth)
  %tobool = icmp ne i32 %call, 0
  br i1 %tobool, label %if.then, label %if.end

if.then:                                          ; preds = %entry
  br label %return

if.end:                                           ; preds = %entry
  %cmp = icmp slt i32 %depth, 10
  br i1 %cmp, label %if.then1, label %if.end3

if.then1:                                         ; preds = %if.end
  %add = add nsw i32 %depth, 1
  %call2 = call i32 @rec(i32 %add)
  br label %if.end3

if.end3:                                          ; preds = %if.then1, %if.end
  br label %return

return:                                           ; preds = %if.end3, %if.then
  %retval.0 = phi i32 [ 0, %if.then ], [ 1, %if.end3 ]
  ret i32 %retval.0
}
declare dso_local i32 @foo(i32)


; Examples taken from https://llvm.discourse.group/t/impossible-condition-optimization/461/1
;
; The important part is that we return a constant (false)
;
; {

; FIXME: All but the return is not needed anymore
define dso_local zeroext i1 @phi(i32 %arg) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@phi
; TUNIT-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:  bb:
; TUNIT-NEXT:    [[TMP:%.*]] = icmp sgt i32 [[ARG]], 5
; TUNIT-NEXT:    br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]]
; TUNIT:       bb1:
; TUNIT-NEXT:    br label [[BB3:%.*]]
; TUNIT:       bb2:
; TUNIT-NEXT:    br label [[BB3]]
; TUNIT:       bb3:
; TUNIT-NEXT:    [[TMP4:%.*]] = icmp sgt i32 [[ARG]], 10
; TUNIT-NEXT:    br i1 [[TMP4]], label [[BB5:%.*]], label [[BB7:%.*]]
; TUNIT:       bb5:
; TUNIT-NEXT:    br label [[BB9:%.*]]
; TUNIT:       bb7:
; TUNIT-NEXT:    br label [[BB9]]
; TUNIT:       bb9:
; TUNIT-NEXT:    br label [[BB12:%.*]]
; TUNIT:       bb11:
; TUNIT-NEXT:    unreachable
; TUNIT:       bb12:
; TUNIT-NEXT:    br label [[BB13:%.*]]
; TUNIT:       bb13:
; TUNIT-NEXT:    ret i1 false
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@phi
; CGSCC-SAME: (i32 [[ARG:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:  bb:
; CGSCC-NEXT:    [[TMP:%.*]] = icmp sgt i32 [[ARG]], 5
; CGSCC-NEXT:    br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]]
; CGSCC:       bb1:
; CGSCC-NEXT:    br label [[BB3:%.*]]
; CGSCC:       bb2:
; CGSCC-NEXT:    br label [[BB3]]
; CGSCC:       bb3:
; CGSCC-NEXT:    [[TMP4:%.*]] = icmp sgt i32 [[ARG]], 10
; CGSCC-NEXT:    br i1 [[TMP4]], label [[BB5:%.*]], label [[BB7:%.*]]
; CGSCC:       bb5:
; CGSCC-NEXT:    br label [[BB9:%.*]]
; CGSCC:       bb7:
; CGSCC-NEXT:    br label [[BB9]]
; CGSCC:       bb9:
; CGSCC-NEXT:    br label [[BB12:%.*]]
; CGSCC:       bb11:
; CGSCC-NEXT:    unreachable
; CGSCC:       bb12:
; CGSCC-NEXT:    br label [[BB13:%.*]]
; CGSCC:       bb13:
; CGSCC-NEXT:    ret i1 false
;
bb:
  %tmp = icmp sgt i32 %arg, 5
  br i1 %tmp, label %bb1, label %bb2

bb1:                                              ; preds = %bb
  br label %bb3

bb2:                                              ; preds = %bb
  br label %bb3

bb3:                                              ; preds = %bb2, %bb1
  %.02 = phi i32 [ 1, %bb1 ], [ 2, %bb2 ]
  %tmp4 = icmp sgt i32 %arg, 10
  br i1 %tmp4, label %bb5, label %bb7

bb5:                                              ; preds = %bb3
  %tmp6 = add nsw i32 %.02, 1
  br label %bb9

bb7:                                              ; preds = %bb3
  %tmp8 = add nsw i32 %.02, 2
  br label %bb9

bb9:                                              ; preds = %bb7, %bb5
  %.01 = phi i32 [ %tmp6, %bb5 ], [ %tmp8, %bb7 ]
  %tmp10 = icmp eq i32 %.01, 5
  br i1 %tmp10, label %bb11, label %bb12

bb11:                                             ; preds = %bb9
  br label %bb13

bb12:                                             ; preds = %bb9
  br label %bb13

bb13:                                             ; preds = %bb12, %bb11
  %.0 = phi i1 [ true, %bb11 ], [ false, %bb12 ]
  ret i1 %.0
}

define dso_local i1 @select(i32 %a) local_unnamed_addr #0 {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@select
; TUNIT-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR1]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    ret i1 false
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@select
; CGSCC-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR2]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    ret i1 false
;
entry:
  %cmp = icmp sgt i32 %a, 5
  %. = select i1 %cmp, i32 1, i32 2
  %cmp1 = icmp sgt i32 %a, 10
  %y.0.v = select i1 %cmp1, i32 1, i32 2
  %y.0 = add nuw nsw i32 %., %y.0.v
  %cmp6 = icmp eq i32 %y.0, 5
  ret i1 %cmp6
}

define dso_local i32 @select_zext(i32 %a) local_unnamed_addr #0 {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@select_zext
; TUNIT-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR1]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    ret i32 0
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@select_zext
; CGSCC-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR2]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    ret i32 0
;
entry:
  %cmp = icmp sgt i32 %a, 5
  %. = select i1 %cmp, i32 1, i32 2
  %cmp1 = icmp sgt i32 %a, 10
  %y.0.v = select i1 %cmp1, i32 1, i32 2
  %y.0 = add nuw nsw i32 %., %y.0.v
  %cmp6 = icmp eq i32 %y.0, 5
  %.13 = zext i1 %cmp6 to i32
  ret i32 %.13
}

define dso_local i64 @select_int2ptr_bitcast_ptr2int(i32 %a) local_unnamed_addr #0 {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@select_int2ptr_bitcast_ptr2int
; TUNIT-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR1]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], 5
; TUNIT-NEXT:    [[DOT:%.*]] = select i1 [[CMP]], i32 1, i32 2
; TUNIT-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[A]], 10
; TUNIT-NEXT:    [[Y_0_V:%.*]] = select i1 [[CMP1]], i32 1, i32 2
; TUNIT-NEXT:    [[Y_0:%.*]] = add nuw nsw i32 [[DOT]], [[Y_0_V]]
; TUNIT-NEXT:    [[CMP6:%.*]] = icmp eq i32 [[Y_0]], 5
; TUNIT-NEXT:    [[I2P:%.*]] = inttoptr i1 [[CMP6]] to ptr
; TUNIT-NEXT:    [[P2I:%.*]] = ptrtoint ptr [[I2P]] to i64
; TUNIT-NEXT:    ret i64 [[P2I]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@select_int2ptr_bitcast_ptr2int
; CGSCC-SAME: (i32 [[A:%.*]]) local_unnamed_addr #[[ATTR2]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], 5
; CGSCC-NEXT:    [[DOT:%.*]] = select i1 [[CMP]], i32 1, i32 2
; CGSCC-NEXT:    [[CMP1:%.*]] = icmp sgt i32 [[A]], 10
; CGSCC-NEXT:    [[Y_0_V:%.*]] = select i1 [[CMP1]], i32 1, i32 2
; CGSCC-NEXT:    [[Y_0:%.*]] = add nuw nsw i32 [[DOT]], [[Y_0_V]]
; CGSCC-NEXT:    [[CMP6:%.*]] = icmp eq i32 [[Y_0]], 5
; CGSCC-NEXT:    [[I2P:%.*]] = inttoptr i1 [[CMP6]] to ptr
; CGSCC-NEXT:    [[P2I:%.*]] = ptrtoint ptr [[I2P]] to i64
; CGSCC-NEXT:    ret i64 [[P2I]]
;
entry:
  %cmp = icmp sgt i32 %a, 5
  %. = select i1 %cmp, i32 1, i32 2
  %cmp1 = icmp sgt i32 %a, 10
  %y.0.v = select i1 %cmp1, i32 1, i32 2
  %y.0 = add nuw nsw i32 %., %y.0.v
  %cmp6 = icmp eq i32 %y.0, 5
  %i2p = inttoptr i1 %cmp6 to ptr
  %p2i = ptrtoint ptr %i2p to i64
  ret i64 %p2i
}

; }

define i1 @f_fcmp(float %a, float %b) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@f_fcmp
; TUNIT-SAME: (float [[A:%.*]], float [[B:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[R:%.*]] = fcmp uge float [[A]], [[B]]
; TUNIT-NEXT:    [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false
; TUNIT-NEXT:    ret i1 [[S]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@f_fcmp
; CGSCC-SAME: (float [[A:%.*]], float [[B:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[R:%.*]] = fcmp uge float [[A]], [[B]]
; CGSCC-NEXT:    [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false
; CGSCC-NEXT:    ret i1 [[S]]
;
  %r = fcmp uge float %a, %b
  %s = select i1 %r, i1 %r, i1 0
  ret i1 %s
}
define i1 @d_fcmp(double %a, double %b) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@d_fcmp
; TUNIT-SAME: (double [[A:%.*]], double [[B:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[R:%.*]] = fcmp oeq double [[A]], [[B]]
; TUNIT-NEXT:    [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false
; TUNIT-NEXT:    ret i1 [[S]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@d_fcmp
; CGSCC-SAME: (double [[A:%.*]], double [[B:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[R:%.*]] = fcmp oeq double [[A]], [[B]]
; CGSCC-NEXT:    [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false
; CGSCC-NEXT:    ret i1 [[S]]
;
  %r = fcmp oeq double %a, %b
  %s = select i1 %r, i1 %r, i1 0
  ret i1 %s
}
define i1 @dp_icmp(ptr %a, ptr %b) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@dp_icmp
; TUNIT-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone [[B:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[R:%.*]] = icmp sge ptr [[A]], [[B]]
; TUNIT-NEXT:    [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false
; TUNIT-NEXT:    ret i1 [[S]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@dp_icmp
; CGSCC-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone [[B:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[R:%.*]] = icmp sge ptr [[A]], [[B]]
; CGSCC-NEXT:    [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false
; CGSCC-NEXT:    ret i1 [[S]]
;
  %r = icmp sge ptr %a, %b
  %s = select i1 %r, i1 %r, i1 0
  ret i1 %s
}
define i1 @ip_icmp(ptr %a, ptr %b) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@ip_icmp
; TUNIT-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone [[B:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[R:%.*]] = icmp ult ptr [[A]], [[B]]
; TUNIT-NEXT:    [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false
; TUNIT-NEXT:    ret i1 [[S]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@ip_icmp
; CGSCC-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone [[B:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[R:%.*]] = icmp ult ptr [[A]], [[B]]
; CGSCC-NEXT:    [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false
; CGSCC-NEXT:    ret i1 [[S]]
;
  %r = icmp ult ptr %a, %b
  %s = select i1 %r, i1 %r, i1 0
  ret i1 %s
}
define i1 @fcmp_caller(float %fa, float %fb, double %da, double %db, ptr %dpa, ptr %dpb, ptr %ipa, ptr %ipb) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@fcmp_caller
; TUNIT-SAME: (float [[FA:%.*]], float [[FB:%.*]], double [[DA:%.*]], double [[DB:%.*]], ptr nofree readnone [[DPA:%.*]], ptr nofree readnone [[DPB:%.*]], ptr nofree readnone [[IPA:%.*]], ptr nofree readnone [[IPB:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[R1:%.*]] = call i1 @f_fcmp(float [[FA]], float [[FB]]) #[[ATTR4]]
; TUNIT-NEXT:    [[R2:%.*]] = call i1 @d_fcmp(double [[DA]], double [[DB]]) #[[ATTR4]]
; TUNIT-NEXT:    [[R3:%.*]] = call i1 @dp_icmp(ptr noalias nofree readnone [[DPA]], ptr noalias nofree readnone [[DPB]]) #[[ATTR4]]
; TUNIT-NEXT:    [[R4:%.*]] = call i1 @ip_icmp(ptr noalias nofree readnone [[IPA]], ptr noalias nofree readnone [[IPB]]) #[[ATTR4]]
; TUNIT-NEXT:    [[O1:%.*]] = or i1 [[R1]], [[R2]]
; TUNIT-NEXT:    [[O2:%.*]] = or i1 [[R3]], [[R4]]
; TUNIT-NEXT:    [[O3:%.*]] = or i1 [[O1]], [[O2]]
; TUNIT-NEXT:    ret i1 [[O3]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@fcmp_caller
; CGSCC-SAME: (float [[FA:%.*]], float [[FB:%.*]], double [[DA:%.*]], double [[DB:%.*]], ptr nofree readnone [[DPA:%.*]], ptr nofree readnone [[DPB:%.*]], ptr nofree readnone [[IPA:%.*]], ptr nofree readnone [[IPB:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:    [[R1:%.*]] = call i1 @f_fcmp(float [[FA]], float [[FB]]) #[[ATTR7]]
; CGSCC-NEXT:    [[R2:%.*]] = call i1 @d_fcmp(double [[DA]], double [[DB]]) #[[ATTR7]]
; CGSCC-NEXT:    [[R3:%.*]] = call i1 @dp_icmp(ptr noalias nofree readnone [[DPA]], ptr noalias nofree readnone [[DPB]]) #[[ATTR7]]
; CGSCC-NEXT:    [[R4:%.*]] = call i1 @ip_icmp(ptr noalias nofree readnone [[IPA]], ptr noalias nofree readnone [[IPB]]) #[[ATTR7]]
; CGSCC-NEXT:    [[O1:%.*]] = or i1 [[R1]], [[R2]]
; CGSCC-NEXT:    [[O2:%.*]] = or i1 [[R3]], [[R4]]
; CGSCC-NEXT:    [[O3:%.*]] = or i1 [[O1]], [[O2]]
; CGSCC-NEXT:    ret i1 [[O3]]
;
  %r1 = call i1 @f_fcmp(float %fa, float %fb)
  %r2 = call i1 @d_fcmp(double %da, double %db)
  %r3 = call i1 @dp_icmp(ptr %dpa, ptr %dpb)
  %r4 = call i1 @ip_icmp(ptr %ipa, ptr %ipb)
  %o1 = or i1 %r1, %r2
  %o2 = or i1 %r3, %r4
  %o3 = or i1 %o1, %o2
  ret i1 %o3
}

define i8 @ret_two() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@ret_two
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT:    ret i8 2
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@ret_two
; CGSCC-SAME: () #[[ATTR2]] {
; CGSCC-NEXT:    ret i8 2
;
  ret i8 2
}
define i8 @ret_undef() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@ret_undef
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT:    ret i8 undef
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@ret_undef
; CGSCC-SAME: () #[[ATTR2]] {
; CGSCC-NEXT:    ret i8 undef
;
  ret i8 undef
}

; Verify we collapse undef to a value and return something non-undef here.
define i8 @undef_collapse_1() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@undef_collapse_1
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT:    ret i8 0
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@undef_collapse_1
; CGSCC-SAME: () #[[ATTR3]] {
; CGSCC-NEXT:    [[C:%.*]] = call i8 @ret_undef() #[[ATTR7]]
; CGSCC-NEXT:    [[S:%.*]] = shl i8 [[C]], 2
; CGSCC-NEXT:    ret i8 [[S]]
;
  %c = call i8 @ret_undef()
  %s = shl i8 %c, 2
  ret i8 %s
}

; Verify we collapse undef to a value and return something non-undef here.
define i8 @undef_collapse_2() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@undef_collapse_2
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT:    ret i8 0
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@undef_collapse_2
; CGSCC-SAME: () #[[ATTR3]] {
; CGSCC-NEXT:    [[C:%.*]] = call i8 @ret_two() #[[ATTR7]]
; CGSCC-NEXT:    [[S:%.*]] = shl i8 undef, [[C]]
; CGSCC-NEXT:    ret i8 [[S]]
;
  %c = call i8 @ret_two()
  %s = shl i8 undef, %c
  ret i8 %s
}

define i8 @undef_collapse_caller() {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@undef_collapse_caller
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT:    ret i8 0
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@undef_collapse_caller
; CGSCC-SAME: () #[[ATTR3]] {
; CGSCC-NEXT:    [[C1:%.*]] = call i8 @undef_collapse_1() #[[ATTR7]]
; CGSCC-NEXT:    [[C2:%.*]] = call i8 @undef_collapse_2() #[[ATTR7]]
; CGSCC-NEXT:    [[A:%.*]] = add i8 [[C1]], [[C2]]
; CGSCC-NEXT:    ret i8 [[A]]
;
  %c1 = call i8 @undef_collapse_1()
  %c2 = call i8 @undef_collapse_2()
  %a = add i8 %c1, %c2
  ret i8 %a
}

define i32 @ret1or2(i1 %c) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@ret1or2
; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[S:%.*]] = select i1 [[C]], i32 1, i32 2
; TUNIT-NEXT:    ret i32 [[S]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@ret1or2
; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[S:%.*]] = select i1 [[C]], i32 1, i32 2
; CGSCC-NEXT:    ret i32 [[S]]
;
  %s = select i1 %c, i32 1, i32 2
  ret i32 %s
}
define i1 @callee_range_1(i1 %c1, i1 %c2, i1 %c3) {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@callee_range_1
; TUNIT-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #[[ATTR4]]
; TUNIT-NEXT:    [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #[[ATTR4]]
; TUNIT-NEXT:    [[INDIRECTION:%.*]] = select i1 [[C3]], i32 [[R1]], i32 [[R2]]
; TUNIT-NEXT:    [[A:%.*]] = add i32 [[R1]], [[INDIRECTION]]
; TUNIT-NEXT:    [[I1:%.*]] = icmp sle i32 [[A]], 4
; TUNIT-NEXT:    [[I2:%.*]] = icmp sge i32 [[A]], 2
; TUNIT-NEXT:    [[F:%.*]] = and i1 [[I1]], [[I2]]
; TUNIT-NEXT:    ret i1 [[F]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@callee_range_1
; CGSCC-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:    [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #[[ATTR7]]
; CGSCC-NEXT:    [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #[[ATTR7]]
; CGSCC-NEXT:    [[INDIRECTION:%.*]] = select i1 [[C3]], i32 [[R1]], i32 [[R2]]
; CGSCC-NEXT:    [[A:%.*]] = add i32 [[R1]], [[INDIRECTION]]
; CGSCC-NEXT:    [[I1:%.*]] = icmp sle i32 [[A]], 4
; CGSCC-NEXT:    [[I2:%.*]] = icmp sge i32 [[A]], 2
; CGSCC-NEXT:    [[F:%.*]] = and i1 [[I1]], [[I2]]
; CGSCC-NEXT:    ret i1 [[F]]
;
  %r1 = call i32 @ret1or2(i1 %c1)
  %r2 = call i32 @ret1or2(i1 %c2)
  %indirection = select i1 %c3, i32 %r1, i32 %r2
  %a = add i32 %r1, %indirection
  %i1 = icmp sle i32 %a, 4
  %i2 = icmp sge i32 %a, 2
  %f = and i1 %i1, %i2
  ret i1 %f
}

define i1 @callee_range_2(i1 %c1, i1 %c2) {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@callee_range_2
; TUNIT-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #[[ATTR4]]
; TUNIT-NEXT:    [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #[[ATTR4]]
; TUNIT-NEXT:    [[A:%.*]] = add i32 [[R1]], [[R2]]
; TUNIT-NEXT:    [[I1:%.*]] = icmp sle i32 [[A]], 3
; TUNIT-NEXT:    [[I2:%.*]] = icmp sge i32 [[A]], 2
; TUNIT-NEXT:    [[F:%.*]] = and i1 [[I1]], [[I2]]
; TUNIT-NEXT:    ret i1 [[F]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@callee_range_2
; CGSCC-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:    [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #[[ATTR7]]
; CGSCC-NEXT:    [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) #[[ATTR7]]
; CGSCC-NEXT:    [[A:%.*]] = add i32 [[R1]], [[R2]]
; CGSCC-NEXT:    [[I1:%.*]] = icmp sle i32 [[A]], 3
; CGSCC-NEXT:    [[I2:%.*]] = icmp sge i32 [[A]], 2
; CGSCC-NEXT:    [[F:%.*]] = and i1 [[I1]], [[I2]]
; CGSCC-NEXT:    ret i1 [[F]]
;
  %r1 = call i32 @ret1or2(i1 %c1)
  %r2 = call i32 @ret1or2(i1 %c2)
  %a = add i32 %r1, %r2
  %i1 = icmp sle i32 %a, 3
  %i2 = icmp sge i32 %a, 2
  %f = and i1 %i1, %i2
  ret i1 %f
}


define i32 @ret100() {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@ret100
; TUNIT-SAME: () #[[ATTR1]] {
; TUNIT-NEXT:    ret i32 100
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@ret100
; CGSCC-SAME: () #[[ATTR2]] {
; CGSCC-NEXT:    ret i32 100
;
  ret i32 100
}

define i1 @ctx_adjustment(i32 %V) {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@ctx_adjustment
; TUNIT-SAME: (i32 [[V:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[C1:%.*]] = icmp sge i32 [[V]], 100
; TUNIT-NEXT:    br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
; TUNIT:       if.true:
; TUNIT-NEXT:    br label [[END:%.*]]
; TUNIT:       if.false:
; TUNIT-NEXT:    br label [[END]]
; TUNIT:       end:
; TUNIT-NEXT:    [[PHI:%.*]] = phi i32 [ [[V]], [[IF_TRUE]] ], [ 100, [[IF_FALSE]] ]
; TUNIT-NEXT:    [[C2:%.*]] = icmp sge i32 [[PHI]], 100
; TUNIT-NEXT:    ret i1 [[C2]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@ctx_adjustment
; CGSCC-SAME: (i32 [[V:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:    [[C1:%.*]] = icmp sge i32 [[V]], 100
; CGSCC-NEXT:    br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
; CGSCC:       if.true:
; CGSCC-NEXT:    br label [[END:%.*]]
; CGSCC:       if.false:
; CGSCC-NEXT:    [[CALL:%.*]] = call i32 @ret100() #[[ATTR7]]
; CGSCC-NEXT:    br label [[END]]
; CGSCC:       end:
; CGSCC-NEXT:    [[PHI:%.*]] = phi i32 [ [[V]], [[IF_TRUE]] ], [ [[CALL]], [[IF_FALSE]] ]
; CGSCC-NEXT:    [[C2:%.*]] = icmp sge i32 [[PHI]], 100
; CGSCC-NEXT:    ret i1 [[C2]]
;
  %c1 = icmp sge i32 %V, 100
  br i1 %c1, label %if.true, label %if.false
if.true:
  br label %end
if.false:
  %call = call i32 @ret100()
  br label %end
end:
  %phi = phi i32 [ %V, %if.true ], [ %call, %if.false ]
  %c2 = icmp sge i32 %phi, 100
  ret i1 %c2
}


define i32 @func(i1 %c) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@func
; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[RET:%.*]] = select i1 [[C]], i32 0, i32 1
; TUNIT-NEXT:    ret i32 [[RET]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@func
; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[RET:%.*]] = select i1 [[C]], i32 0, i32 1
; CGSCC-NEXT:    ret i32 [[RET]]
;
  %ret = select i1 %c, i32 0, i32 1
  ret i32 %ret
}

define i32 @simplify_callsite_argument(i1 %d) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@simplify_callsite_argument
; TUNIT-SAME: (i1 [[D:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[C:%.*]] = select i1 [[D]], i1 true, i1 false
; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; TUNIT:       t:
; TUNIT-NEXT:    [[RET1:%.*]] = call i32 @func(i1 noundef [[C]]) #[[ATTR4]]
; TUNIT-NEXT:    ret i32 [[RET1]]
; TUNIT:       f:
; TUNIT-NEXT:    [[RET2:%.*]] = call i32 @func(i1 noundef false) #[[ATTR4]]
; TUNIT-NEXT:    ret i32 [[RET2]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@simplify_callsite_argument
; CGSCC-SAME: (i1 [[D:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:    [[C:%.*]] = select i1 [[D]], i1 true, i1 false
; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CGSCC:       t:
; CGSCC-NEXT:    [[RET1:%.*]] = call noundef i32 @func(i1 noundef [[C]]) #[[ATTR7]]
; CGSCC-NEXT:    ret i32 [[RET1]]
; CGSCC:       f:
; CGSCC-NEXT:    [[RET2:%.*]] = call noundef i32 @func(i1 noundef false) #[[ATTR7]]
; CGSCC-NEXT:    ret i32 [[RET2]]
;
  %c = select i1 %d, i1 true, i1 false
  br i1 %c, label %t, label %f
t:
  %ret1 = call i32 @func(i1 %c)
  ret i32 %ret1
f:
  %ret2 = call i32 @func(i1 false)
  ret i32 %ret2
}

define internal i32 @less_than_65536(i32 %arg) {
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@less_than_65536
; CGSCC-SAME: (i32 [[ARG:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[SHRINKED:%.*]] = udiv i32 [[ARG]], 65536
; CGSCC-NEXT:    ret i32 [[SHRINKED]]
;
  %shrinked = udiv i32 %arg, 65536
  ret i32 %shrinked
}

define internal i1 @is_less_than_65536(i32 %arg) {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@is_less_than_65536
; CGSCC-SAME: (i32 [[ARG:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[CMP:%.*]] = icmp ult i32 [[ARG]], 65536
; CGSCC-NEXT:    ret i1 [[CMP]]
;
  %cmp = icmp ult i32 %arg, 65536
  ret i1 %cmp
}

define i1 @check_divided_range(i32 %arg) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@check_divided_range
; TUNIT-SAME: (i32 [[ARG:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    ret i1 true
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@check_divided_range
; CGSCC-SAME: (i32 [[ARG:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:    [[CSRET1:%.*]] = call i32 @less_than_65536(i32 noundef 0) #[[ATTR7]]
; CGSCC-NEXT:    [[CSRET2:%.*]] = call i32 @less_than_65536(i32 [[ARG]]) #[[ATTR7]]
; CGSCC-NEXT:    [[TRUE1:%.*]] = call i1 @is_less_than_65536(i32 [[CSRET1]]) #[[ATTR7]]
; CGSCC-NEXT:    [[TRUE2:%.*]] = call i1 @is_less_than_65536(i32 [[CSRET2]]) #[[ATTR7]]
; CGSCC-NEXT:    [[RET:%.*]] = and i1 [[TRUE1]], [[TRUE2]]
; CGSCC-NEXT:    ret i1 [[RET]]
;
  %csret1 = call i32 @less_than_65536(i32 0)
  %csret2 = call i32 @less_than_65536(i32 %arg)
  %true1 = call i1 @is_less_than_65536(i32 %csret1)
  %true2 = call i1 @is_less_than_65536(i32 %csret2)
  %ret = and i1 %true1, %true2
  ret i1 %ret
}

define internal i32 @cast_and_return(i1 %c) {
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@cast_and_return
; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[RET:%.*]] = zext i1 [[C]] to i32
; CGSCC-NEXT:    ret i32 [[RET]]
;
  %ret = zext i1 %c to i32
  ret i32 %ret
}

define internal i1 @is_less_than_3(i32 %c) {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@is_less_than_3
; CGSCC-SAME: (i32 [[C:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[CMP:%.*]] = icmp slt i32 [[C]], 3
; CGSCC-NEXT:    ret i1 [[CMP]]
;
  %cmp = icmp slt i32 %c, 3
  ret i1 %cmp
}

define i1 @check_casted_range(i1 %c) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@check_casted_range
; TUNIT-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    ret i1 true
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@check_casted_range
; CGSCC-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:    [[CSRET1:%.*]] = call i32 @cast_and_return(i1 noundef true) #[[ATTR7]]
; CGSCC-NEXT:    [[CSRET2:%.*]] = call i32 @cast_and_return(i1 [[C]]) #[[ATTR7]]
; CGSCC-NEXT:    [[ADD:%.*]] = add i32 [[CSRET1]], [[CSRET2]]
; CGSCC-NEXT:    [[RET:%.*]] = call i1 @is_less_than_3(i32 [[ADD]]) #[[ATTR7]]
; CGSCC-NEXT:    ret i1 [[RET]]
;
  %csret1 = call i32 @cast_and_return(i1 true)
  %csret2 = call i32 @cast_and_return(i1 %c)
  %add = add i32 %csret1, %csret2
  %ret = call i1 @is_less_than_3(i32 %add)
  ret i1 %ret
}

define internal i32 @less_than_100_1(i32 %c) {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@less_than_100_1
; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    switch i32 [[C]], label [[OTHERWISE:%.*]] [
; CGSCC-NEXT:      i32 0, label [[ONZERO:%.*]]
; CGSCC-NEXT:      i32 1, label [[ONONE:%.*]]
; CGSCC-NEXT:      i32 2, label [[ONTWO:%.*]]
; CGSCC-NEXT:      i32 3, label [[ONTHREE:%.*]]
; CGSCC-NEXT:      i32 4, label [[ONFOUR:%.*]]
; CGSCC-NEXT:      i32 5, label [[ONFIVE:%.*]]
; CGSCC-NEXT:      i32 6, label [[ONSIX:%.*]]
; CGSCC-NEXT:    ]
; CGSCC:       onzero:
; CGSCC-NEXT:    ret i32 0
; CGSCC:       onone:
; CGSCC-NEXT:    ret i32 1
; CGSCC:       ontwo:
; CGSCC-NEXT:    ret i32 2
; CGSCC:       onthree:
; CGSCC-NEXT:    ret i32 3
; CGSCC:       onfour:
; CGSCC-NEXT:    ret i32 4
; CGSCC:       onfive:
; CGSCC-NEXT:    ret i32 5
; CGSCC:       onsix:
; CGSCC-NEXT:    ret i32 6
; CGSCC:       otherwise:
; CGSCC-NEXT:    ret i32 99
;
  switch i32 %c, label %otherwise [ i32 0, label %onzero
  i32 1, label %onone
  i32 2, label %ontwo
  i32 3, label %onthree
  i32 4, label %onfour
  i32 5, label %onfive
  i32 6, label %onsix]
onzero:
  ret i32 0
onone:
  ret i32 1
ontwo:
  ret i32 2
onthree:
  ret i32 3
onfour:
  ret i32 4
onfive:
  ret i32 5
onsix:
  ret i32 6
otherwise:
  ret i32 99
}

define internal i1 @is_less_than_100_1(i32 %c) {
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@is_less_than_100_1
; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[CMP:%.*]] = icmp slt i32 [[C]], 100
; CGSCC-NEXT:    ret i1 [[CMP]]
;
  %cmp = icmp slt i32 %c, 100
  ret i1 %cmp
}

define i1 @propagate_range1(i32 %c){
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@propagate_range1
; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    ret i1 true
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@propagate_range1
; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:    [[CSRET:%.*]] = call i32 @less_than_100_1(i32 noundef [[C]]) #[[ATTR7]]
; CGSCC-NEXT:    [[TRUE:%.*]] = call i1 @is_less_than_100_1(i32 noundef [[CSRET]]) #[[ATTR7]]
; CGSCC-NEXT:    ret i1 [[TRUE]]
;
  %csret = call i32 @less_than_100_1(i32 %c)
  %true = call i1 @is_less_than_100_1(i32 %csret)
  ret i1 %true
}

define internal i32 @less_than_100_2(i32 %c) {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@less_than_100_2
; TUNIT-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    switch i32 [[C]], label [[OTHERWISE:%.*]] [
; TUNIT-NEXT:      i32 0, label [[ONZERO:%.*]]
; TUNIT-NEXT:      i32 1, label [[ONONE:%.*]]
; TUNIT-NEXT:      i32 2, label [[ONTWO:%.*]]
; TUNIT-NEXT:      i32 3, label [[ONTHREE:%.*]]
; TUNIT-NEXT:      i32 4, label [[ONFOUR:%.*]]
; TUNIT-NEXT:      i32 5, label [[ONFIVE:%.*]]
; TUNIT-NEXT:      i32 6, label [[ONSIX:%.*]]
; TUNIT-NEXT:    ]
; TUNIT:       onzero:
; TUNIT-NEXT:    ret i32 0
; TUNIT:       onone:
; TUNIT-NEXT:    ret i32 1
; TUNIT:       ontwo:
; TUNIT-NEXT:    ret i32 2
; TUNIT:       onthree:
; TUNIT-NEXT:    ret i32 3
; TUNIT:       onfour:
; TUNIT-NEXT:    ret i32 4
; TUNIT:       onfive:
; TUNIT-NEXT:    ret i32 5
; TUNIT:       onsix:
; TUNIT-NEXT:    ret i32 6
; TUNIT:       otherwise:
; TUNIT-NEXT:    ret i32 99
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@less_than_100_2
; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    switch i32 [[C]], label [[OTHERWISE:%.*]] [
; CGSCC-NEXT:      i32 0, label [[ONZERO:%.*]]
; CGSCC-NEXT:      i32 1, label [[ONONE:%.*]]
; CGSCC-NEXT:      i32 2, label [[ONTWO:%.*]]
; CGSCC-NEXT:      i32 3, label [[ONTHREE:%.*]]
; CGSCC-NEXT:      i32 4, label [[ONFOUR:%.*]]
; CGSCC-NEXT:      i32 5, label [[ONFIVE:%.*]]
; CGSCC-NEXT:      i32 6, label [[ONSIX:%.*]]
; CGSCC-NEXT:    ]
; CGSCC:       onzero:
; CGSCC-NEXT:    ret i32 0
; CGSCC:       onone:
; CGSCC-NEXT:    ret i32 1
; CGSCC:       ontwo:
; CGSCC-NEXT:    ret i32 2
; CGSCC:       onthree:
; CGSCC-NEXT:    ret i32 3
; CGSCC:       onfour:
; CGSCC-NEXT:    ret i32 4
; CGSCC:       onfive:
; CGSCC-NEXT:    ret i32 5
; CGSCC:       onsix:
; CGSCC-NEXT:    ret i32 6
; CGSCC:       otherwise:
; CGSCC-NEXT:    ret i32 99
;
  switch i32 %c, label %otherwise [ i32 0, label %onzero
  i32 1, label %onone
  i32 2, label %ontwo
  i32 3, label %onthree
  i32 4, label %onfour
  i32 5, label %onfive
  i32 6, label %onsix]
onzero:
  ret i32 0
onone:
  ret i32 1
ontwo:
  ret i32 2
onthree:
  ret i32 3
onfour:
  ret i32 4
onfive:
  ret i32 5
onsix:
  ret i32 6
otherwise:
  ret i32 99
}

define internal i1 @is_less_than_100_2(i32 %c) {
;
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@is_less_than_100_2
; TUNIT-SAME: (i32 noundef [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[CMP:%.*]] = icmp slt i32 [[C]], 100
; TUNIT-NEXT:    ret i1 [[CMP]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@is_less_than_100_2
; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    [[CMP:%.*]] = icmp slt i32 [[C]], 100
; CGSCC-NEXT:    ret i1 [[CMP]]
;
  %cmp = icmp slt i32 %c, 100
  ret i1 %cmp
}

define i1 @propagate_range2(i32 %c) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@propagate_range2
; TUNIT-SAME: (i32 [[C:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[CSRET1:%.*]] = call noundef i32 @less_than_100_2(i32 noundef 0) #[[ATTR4]]
; TUNIT-NEXT:    [[TRUE1:%.*]] = call i1 @is_less_than_100_2(i32 noundef [[CSRET1]]) #[[ATTR4]]
; TUNIT-NEXT:    [[CSRET2:%.*]] = call noundef i32 @less_than_100_2(i32 noundef [[C]]) #[[ATTR4]]
; TUNIT-NEXT:    [[TRUE2:%.*]] = call i1 @is_less_than_100_2(i32 noundef [[CSRET2]]) #[[ATTR4]]
; TUNIT-NEXT:    [[TRUE:%.*]] = and i1 [[TRUE1]], [[TRUE2]]
; TUNIT-NEXT:    ret i1 [[TRUE]]
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@propagate_range2
; CGSCC-SAME: (i32 noundef [[C:%.*]]) #[[ATTR3]] {
; CGSCC-NEXT:    [[CSRET1:%.*]] = call i32 @less_than_100_2(i32 noundef 0) #[[ATTR7]]
; CGSCC-NEXT:    [[TRUE1:%.*]] = call i1 @is_less_than_100_2(i32 noundef [[CSRET1]]) #[[ATTR7]]
; CGSCC-NEXT:    [[CSRET2:%.*]] = call i32 @less_than_100_2(i32 noundef [[C]]) #[[ATTR7]]
; CGSCC-NEXT:    [[TRUE2:%.*]] = call i1 @is_less_than_100_2(i32 noundef [[CSRET2]]) #[[ATTR7]]
; CGSCC-NEXT:    [[TRUE:%.*]] = and i1 [[TRUE1]], [[TRUE2]]
; CGSCC-NEXT:    ret i1 [[TRUE]]
;
  %csret1 = call i32 @less_than_100_2(i32 0)
  %true1 = call i1 @is_less_than_100_2(i32 %csret1)
  %csret2 = call i32 @less_than_100_2(i32 %c)
  %true2 = call i1 @is_less_than_100_2(i32 %csret2)
  %true = and i1 %true1, %true2
  ret i1 %true
}

define internal i1 @non_zero(i8 %v) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; TUNIT-LABEL: define {{[^@]+}}@non_zero
; TUNIT-SAME: (i8 [[V:%.*]]) #[[ATTR1]] {
; TUNIT-NEXT:    [[R:%.*]] = icmp ne i8 [[V]], 0
; TUNIT-NEXT:    ret i1 [[R]]
;
; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
; CGSCC-LABEL: define {{[^@]+}}@non_zero
; CGSCC-SAME: (i8 [[V:%.*]]) #[[ATTR2]] {
; CGSCC-NEXT:    ret i1 true
;
  %r = icmp ne i8 %v, 0
  ret i1 %r
}

; Avoid range metadata for %l below
define i1 @context(ptr %p) {
; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
; TUNIT-LABEL: define {{[^@]+}}@context
; TUNIT-SAME: (ptr nocapture nofree noundef nonnull readonly dereferenceable(1) [[P:%.*]]) #[[ATTR0]] {
; TUNIT-NEXT:    [[L:%.*]] = load i8, ptr [[P]], align 1
; TUNIT-NEXT:    [[C:%.*]] = icmp slt i8 0, [[L]]
; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; TUNIT:       t:
; TUNIT-NEXT:    [[R:%.*]] = call i1 @non_zero(i8 [[L]]) #[[ATTR4]]
; TUNIT-NEXT:    ret i1 [[R]]
; TUNIT:       f:
; TUNIT-NEXT:    ret i1 false
;
; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)
; CGSCC-LABEL: define {{[^@]+}}@context
; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly dereferenceable(1) [[P:%.*]]) #[[ATTR1]] {
; CGSCC-NEXT:    [[L:%.*]] = load i8, ptr [[P]], align 1
; CGSCC-NEXT:    [[C:%.*]] = icmp slt i8 0, [[L]]
; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CGSCC:       t:
; CGSCC-NEXT:    [[R:%.*]] = call noundef i1 @non_zero(i8 [[L]]) #[[ATTR7]]
; CGSCC-NEXT:    ret i1 [[R]]
; CGSCC:       f:
; CGSCC-NEXT:    ret i1 false
;
  %l = load i8, ptr %p
  %c = icmp slt i8 0, %l
  br i1 %c, label %t, label %f
t:
  %r = call i1 @non_zero(i8 %l)
  ret i1 %r
f:
  ret i1 false
}


define void @spam(ptr %arg, ptr %arg1) {
; CHECK-LABEL: define {{[^@]+}}@spam
; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 8 dereferenceable(4) [[ARG:%.*]], ptr nocapture nofree readnone [[ARG1:%.*]]) {
; CHECK-NEXT:  bb:
; CHECK-NEXT:    [[TMP:%.*]] = load i32, ptr [[ARG]], align 8
; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[TMP]], 4
; CHECK-NEXT:    br i1 [[TMP2]], label [[BB3:%.*]], label [[BB4:%.*]]
; CHECK:       bb3:
; CHECK-NEXT:    call fastcc void @wobble(i32 signext [[TMP]])
; CHECK-NEXT:    br label [[BB5:%.*]]
; CHECK:       bb4:
; CHECK-NEXT:    call void @ham(i32 [[TMP]])
; CHECK-NEXT:    br label [[BB5]]
; CHECK:       bb5:
; CHECK-NEXT:    ret void
;
bb:
  %tmp = load i32, ptr %arg, align 8
  %tmp2 = icmp ult i32 %tmp, 4
  br i1 %tmp2, label %bb3, label %bb4

bb3:                                              ; preds = %bb
  call fastcc void @wobble(i32 signext %tmp)
  br label %bb5

bb4:                                              ; preds = %bb
  call void @ham(i32 %tmp)
  br label %bb5

bb5:                                              ; preds = %bb4, %bb3
  ret void
}

define internal fastcc void @wobble(i32 signext %arg) {
; CHECK-LABEL: define {{[^@]+}}@wobble
; CHECK-SAME: (i32 signext [[ARG:%.*]]) {
; CHECK-NEXT:  bb:
; CHECK-NEXT:    [[TMP:%.*]] = icmp ult i32 [[ARG]], 2
; CHECK-NEXT:    br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]]
; CHECK:       bb1:
; CHECK-NEXT:    call void @barney(i32 noundef signext 32, i32 noundef signext 0)
; CHECK-NEXT:    br label [[BB3:%.*]]
; CHECK:       bb2:
; CHECK-NEXT:    br label [[BB3]]
; CHECK:       bb3:
; CHECK-NEXT:    ret void
;
bb:
  %tmp = icmp ult i32 %arg, 2
  br i1 %tmp, label %bb1, label %bb2

bb1:                                              ; preds = %bb
  call void @barney(i32 signext 32, i32 signext 0)
  br label %bb3

bb2:                                              ; preds = %bb
  br label %bb3

bb3:                                              ; preds = %bb2, %bb1
  ret void
}

define i1 @loop_1(i32 %N) {
; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none)
; TUNIT-LABEL: define {{[^@]+}}@loop_1
; TUNIT-SAME: (i32 [[N:%.*]]) #[[ATTR2:[0-9]+]] {
; TUNIT-NEXT:  entry:
; TUNIT-NEXT:    br label [[HEADER:%.*]]
; TUNIT:       header:
; TUNIT-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[AND:%.*]], [[HEADER]] ]
; TUNIT-NEXT:    [[INC:%.*]] = add i32 [[I]], 1
; TUNIT-NEXT:    [[AND]] = and i32 [[INC]], 9999
; TUNIT-NEXT:    [[CMP:%.*]] = icmp ne i32 [[N]], [[AND]]
; TUNIT-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; TUNIT:       exit:
; TUNIT-NEXT:    [[R:%.*]] = icmp sle i32 [[I]], 5
; TUNIT-NEXT:    ret i1 [[R]]
;
; CGSCC: Function Attrs: nofree norecurse nosync nounwind memory(none)
; CGSCC-LABEL: define {{[^@]+}}@loop_1
; CGSCC-SAME: (i32 [[N:%.*]]) #[[ATTR4:[0-9]+]] {
; CGSCC-NEXT:  entry:
; CGSCC-NEXT:    br label [[HEADER:%.*]]
; CGSCC:       header:
; CGSCC-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[AND:%.*]], [[HEADER]] ]
; CGSCC-NEXT:    [[INC:%.*]] = add i32 [[I]], 1
; CGSCC-NEXT:    [[AND]] = and i32 [[INC]], 9999
; CGSCC-NEXT:    [[CMP:%.*]] = icmp ne i32 [[N]], [[AND]]
; CGSCC-NEXT:    br i1 [[CMP]], label [[HEADER]], label [[EXIT:%.*]]
; CGSCC:       exit:
; CGSCC-NEXT:    [[R:%.*]] = icmp sle i32 [[I]], 5
; CGSCC-NEXT:    ret i1 [[R]]
;
entry:
  br label %header
header:
  %i = phi i32 [0, %entry], [%and, %header]
  %inc = add i32 %i, 1
  %and = and i32 %inc, 9999
  %cmp = icmp ne i32 %N, %and
  br i1 %cmp, label %header, label %exit
exit:
  %r = icmp sle i32 %i, 5
  ret i1 %r
}

declare void @ham(i32)

declare void @barney(i32 signext, i32 signext)


!0 = !{i32 0, i32 10}
!1 = !{i32 10, i32 100}
;.
; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; TUNIT: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind memory(none) }
; TUNIT: attributes #[[ATTR3]] = { nofree nosync nounwind willreturn memory(read) }
; TUNIT: attributes #[[ATTR4]] = { nofree nosync nounwind willreturn memory(none) }
;.
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: read) }
; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR3]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
; CGSCC: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind memory(none) }
; CGSCC: attributes #[[ATTR5]] = { nofree willreturn memory(read) }
; CGSCC: attributes #[[ATTR6]] = { nofree willreturn }
; CGSCC: attributes #[[ATTR7]] = { nofree nosync willreturn }
;.
; TUNIT: [[RNG0]] = !{i32 0, i32 10}
; TUNIT: [[RNG1]] = !{i32 10, i32 100}
; TUNIT: [[RNG2]] = !{i32 200, i32 1091}
; TUNIT: [[RNG3]] = !{i32 1, i32 -2147483648}
;.
; CGSCC: [[RNG0]] = !{i32 0, i32 10}
; CGSCC: [[RNG1]] = !{i32 10, i32 100}
;.