Compiler projects using llvm
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

; Test cases specifically designed for the "undefined behavior" abstract function attribute.
; We want to verify that whenever undefined behavior is assumed, the code becomes unreachable.
; We use FIXME's to indicate problems and missing attributes.

; -- Load tests --

define void @load_wholly_unreachable() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@load_wholly_unreachable
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT:    unreachable
;
  %a = load i32, i32* null
  ret void
}

define void @loads_wholly_unreachable() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@loads_wholly_unreachable
; CHECK-SAME: () #[[ATTR0]] {
; CHECK-NEXT:    unreachable
;
  %a = load i32, i32* null
  %b = load i32, i32* null
  ret void
}


define void @load_single_bb_unreachable(i1 %cond) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@load_single_bb_unreachable
; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; CHECK:       t:
; CHECK-NEXT:    unreachable
; CHECK:       e:
; CHECK-NEXT:    ret void
;
  br i1 %cond, label %t, label %e
t:
  %b = load i32, i32* null
  br label %e
e:
  ret void
}

; Note that while the load is removed (because it's unused), the block
; is not changed to unreachable
define void @load_null_pointer_is_defined() null_pointer_is_valid {
; CHECK: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@load_null_pointer_is_defined
; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
; CHECK-NEXT:    ret void
;
  %a = load i32, i32* null
  ret void
}

define internal i32* @ret_null() {
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_null
; IS__CGSCC____-SAME: () #[[ATTR0]] {
; IS__CGSCC____-NEXT:    ret i32* null
;
  ret i32* null
}

define void @load_null_propagated() {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@load_null_propagated
; IS__TUNIT____-SAME: () #[[ATTR0]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@load_null_propagated
; IS__CGSCC____-SAME: () #[[ATTR2:[0-9]+]] {
; IS__CGSCC____-NEXT:    ret void
;
  %ptr = call i32* @ret_null()
  %a = load i32, i32* %ptr
  ret void
}

; -- Store tests --

define void @store_wholly_unreachable() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@store_wholly_unreachable
; CHECK-SAME: () #[[ATTR0]] {
; CHECK-NEXT:    unreachable
;
  store i32 5, i32* null
  ret void
}

define void @store_wholly_unreachable_volatile() {
; IS__TUNIT____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@store_wholly_unreachable_volatile
; IS__TUNIT____-SAME: () #[[ATTR2:[0-9]+]] {
; IS__TUNIT____-NEXT:    store volatile i32 5, i32* null, align 4294967296
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@store_wholly_unreachable_volatile
; IS__CGSCC____-SAME: () #[[ATTR3:[0-9]+]] {
; IS__CGSCC____-NEXT:    store volatile i32 5, i32* null, align 4294967296
; IS__CGSCC____-NEXT:    ret void
;
  store volatile i32 5, i32* null
  ret void
}

define void @store_single_bb_unreachable(i1 %cond) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@store_single_bb_unreachable
; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; CHECK:       t:
; CHECK-NEXT:    unreachable
; CHECK:       e:
; CHECK-NEXT:    ret void
;
  br i1 %cond, label %t, label %e
t:
  store i32 5, i32* null
  br label %e
e:
  ret void
}

define void @store_null_pointer_is_defined() null_pointer_is_valid {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@store_null_pointer_is_defined
; IS__TUNIT____-SAME: () #[[ATTR3:[0-9]+]] {
; IS__TUNIT____-NEXT:    store i32 5, i32* null, align 4294967296
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@store_null_pointer_is_defined
; IS__CGSCC____-SAME: () #[[ATTR4:[0-9]+]] {
; IS__CGSCC____-NEXT:    store i32 5, i32* null, align 4294967296
; IS__CGSCC____-NEXT:    ret void
;
  store i32 5, i32* null
  ret void
}

define void @store_null_propagated() {
; ATTRIBUTOR-LABEL: @store_null_propagated(
; ATTRIBUTOR-NEXT:    unreachable
;
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@store_null_propagated
; IS__TUNIT____-SAME: () #[[ATTR0]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@store_null_propagated
; IS__CGSCC____-SAME: () #[[ATTR5:[0-9]+]] {
; IS__CGSCC____-NEXT:    [[PTR:%.*]] = call noalias align 4294967296 i32* @ret_null() #[[ATTR10:[0-9]+]]
; IS__CGSCC____-NEXT:    ret void
;
  %ptr = call i32* @ret_null()
  store i32 5, i32* %ptr
  ret void
}

; -- AtomicRMW tests --

define void @atomicrmw_wholly_unreachable() {
; IS__TUNIT____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable
; IS__TUNIT____-SAME: () #[[ATTR2]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable
; IS__CGSCC____-SAME: () #[[ATTR3]] {
; IS__CGSCC____-NEXT:    unreachable
;
  %a = atomicrmw add i32* null, i32 1 acquire
  ret void
}

define void @atomicrmw_single_bb_unreachable(i1 %cond) {
; IS__TUNIT____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable
; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) #[[ATTR2]] {
; IS__TUNIT____-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       e:
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable
; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) #[[ATTR3]] {
; IS__CGSCC____-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       e:
; IS__CGSCC____-NEXT:    ret void
;
  br i1 %cond, label %t, label %e
t:
  %a = atomicrmw add i32* null, i32 1 acquire
  br label %e
e:
  ret void
}

define void @atomicrmw_null_pointer_is_defined() null_pointer_is_valid {
; IS__TUNIT____: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@atomicrmw_null_pointer_is_defined
; IS__TUNIT____-SAME: () #[[ATTR4:[0-9]+]] {
; IS__TUNIT____-NEXT:    [[A:%.*]] = atomicrmw add i32* null, i32 1 acquire, align 4
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@atomicrmw_null_pointer_is_defined
; IS__CGSCC____-SAME: () #[[ATTR6:[0-9]+]] {
; IS__CGSCC____-NEXT:    [[A:%.*]] = atomicrmw add i32* null, i32 1 acquire, align 4
; IS__CGSCC____-NEXT:    ret void
;
  %a = atomicrmw add i32* null, i32 1 acquire
  ret void
}

define void @atomicrmw_null_propagated() {
; ATTRIBUTOR-LABEL: @atomicrmw_null_propagated(
; ATTRIBUTOR-NEXT:    unreachable
;
; IS__TUNIT____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@atomicrmw_null_propagated
; IS__TUNIT____-SAME: () #[[ATTR2]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nounwind willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@atomicrmw_null_propagated
; IS__CGSCC____-SAME: () #[[ATTR7:[0-9]+]] {
; IS__CGSCC____-NEXT:    [[PTR:%.*]] = call noalias i32* @ret_null() #[[ATTR10]]
; IS__CGSCC____-NEXT:    [[A:%.*]] = atomicrmw add i32* [[PTR]], i32 1 acquire, align 4
; IS__CGSCC____-NEXT:    ret void
;
  %ptr = call i32* @ret_null()
  %a = atomicrmw add i32* %ptr, i32 1 acquire
  ret void
}

; -- AtomicCmpXchg tests --

define void @atomiccmpxchg_wholly_unreachable() {
; IS__TUNIT____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable
; IS__TUNIT____-SAME: () #[[ATTR2]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable
; IS__CGSCC____-SAME: () #[[ATTR3]] {
; IS__CGSCC____-NEXT:    unreachable
;
  %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic
  ret void
}

define void @atomiccmpxchg_single_bb_unreachable(i1 %cond) {
; IS__TUNIT____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable
; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) #[[ATTR2]] {
; IS__TUNIT____-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       e:
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable
; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) #[[ATTR3]] {
; IS__CGSCC____-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       e:
; IS__CGSCC____-NEXT:    ret void
;
  br i1 %cond, label %t, label %e
t:
  %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic
  br label %e
e:
  ret void
}

define void @atomiccmpxchg_null_pointer_is_defined() null_pointer_is_valid {
; IS__TUNIT____: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@atomiccmpxchg_null_pointer_is_defined
; IS__TUNIT____-SAME: () #[[ATTR4]] {
; IS__TUNIT____-NEXT:    [[A:%.*]] = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic, align 4
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@atomiccmpxchg_null_pointer_is_defined
; IS__CGSCC____-SAME: () #[[ATTR6]] {
; IS__CGSCC____-NEXT:    [[A:%.*]] = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic, align 4
; IS__CGSCC____-NEXT:    ret void
;
  %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic
  ret void
}

define void @atomiccmpxchg_null_propagated() {
; ATTRIBUTOR-LABEL: @atomiccmpxchg_null_propagated(
; ATTRIBUTOR-NEXT:    unreachable
;
; IS__TUNIT____: Function Attrs: nofree norecurse nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@atomiccmpxchg_null_propagated
; IS__TUNIT____-SAME: () #[[ATTR2]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nounwind willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@atomiccmpxchg_null_propagated
; IS__CGSCC____-SAME: () #[[ATTR7]] {
; IS__CGSCC____-NEXT:    [[PTR:%.*]] = call noalias i32* @ret_null() #[[ATTR10]]
; IS__CGSCC____-NEXT:    [[A:%.*]] = cmpxchg i32* [[PTR]], i32 2, i32 3 acq_rel monotonic, align 4
; IS__CGSCC____-NEXT:    ret void
;
  %ptr = call i32* @ret_null()
  %a = cmpxchg i32* %ptr, i32 2, i32 3 acq_rel monotonic
  ret void
}

; -- Conditional branching tests --

; Note: The unreachable on %t and %e is _not_ from AAUndefinedBehavior

define i32 @cond_br_on_undef() {
; IS__TUNIT____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef
; IS__TUNIT____-SAME: () #[[ATTR5:[0-9]+]] {
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       e:
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef
; IS__CGSCC____-SAME: () #[[ATTR8:[0-9]+]] {
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       e:
; IS__CGSCC____-NEXT:    unreachable
;
  br i1 undef, label %t, label %e
t:
  ret i32 1
e:
  ret i32 2
}

; More complicated branching
  ; Valid branch - verify that this is not converted
  ; to unreachable.
define void @cond_br_on_undef2(i1 %cond) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef2
; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    br i1 [[COND]], label [[T1:%.*]], label [[E1:%.*]]
; CHECK:       t1:
; CHECK-NEXT:    unreachable
; CHECK:       t2:
; CHECK-NEXT:    unreachable
; CHECK:       e2:
; CHECK-NEXT:    unreachable
; CHECK:       e1:
; CHECK-NEXT:    ret void
;
  br i1 %cond, label %t1, label %e1
t1:
  br i1 undef, label %t2, label %e2
t2:
  ret void
e2:
  ret void
e1:
  ret void
}

define i1 @ret_undef() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@ret_undef
; CHECK-SAME: () #[[ATTR0]] {
; CHECK-NEXT:    ret i1 undef
;
  ret i1 undef
}

define void @cond_br_on_undef_interproc() {
; IS__TUNIT____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc
; IS__TUNIT____-SAME: () #[[ATTR5]] {
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       e:
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc
; IS__CGSCC____-SAME: () #[[ATTR2]] {
; IS__CGSCC____-NEXT:    [[COND:%.*]] = call i1 @ret_undef() #[[ATTR10]]
; IS__CGSCC____-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    ret void
; IS__CGSCC____:       e:
; IS__CGSCC____-NEXT:    ret void
;
  %cond = call i1 @ret_undef()
  br i1 %cond, label %t, label %e
t:
  ret void
e:
  ret void
}

define i1 @ret_undef2() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@ret_undef2
; CHECK-SAME: () #[[ATTR0]] {
; CHECK-NEXT:    br i1 true, label [[T:%.*]], label [[E:%.*]]
; CHECK:       t:
; CHECK-NEXT:    ret i1 undef
; CHECK:       e:
; CHECK-NEXT:    unreachable
;
  br i1 true, label %t, label %e
t:
  ret i1 undef
e:
  ret i1 undef
}

; More complicated interproc deduction of undef
define void @cond_br_on_undef_interproc2() {
; IS__TUNIT____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc2
; IS__TUNIT____-SAME: () #[[ATTR5]] {
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       e:
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc2
; IS__CGSCC____-SAME: () #[[ATTR2]] {
; IS__CGSCC____-NEXT:    [[COND:%.*]] = call i1 @ret_undef2() #[[ATTR10]]
; IS__CGSCC____-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    ret void
; IS__CGSCC____:       e:
; IS__CGSCC____-NEXT:    ret void
;
  %cond = call i1 @ret_undef2()
  br i1 %cond, label %t, label %e
t:
  ret void
e:
  ret void
}

; Branch on undef that depends on propagation of
; undef of a previous instruction.
define i32 @cond_br_on_undef3() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef3
; CHECK-SAME: () #[[ATTR0]] {
; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 1, undef
; CHECK-NEXT:    br i1 [[COND]], label [[T:%.*]], label [[E:%.*]]
; CHECK:       t:
; CHECK-NEXT:    ret i32 1
; CHECK:       e:
; CHECK-NEXT:    ret i32 2
;
  %cond = icmp ne i32 1, undef
  br i1 %cond, label %t, label %e
t:
  ret i32 1
e:
  ret i32 2
}

; Branch on undef because of uninitialized value.
; FIXME: Currently it doesn't propagate the undef.
define i32 @cond_br_on_undef_uninit() {
; IS__TUNIT____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef_uninit
; IS__TUNIT____-SAME: () #[[ATTR5]] {
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       e:
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef_uninit
; IS__CGSCC____-SAME: () #[[ATTR8]] {
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       e:
; IS__CGSCC____-NEXT:    unreachable
;
  %alloc = alloca i1
  %cond = load i1, i1* %alloc
  br i1 %cond, label %t, label %e
t:
  ret i32 1
e:
  ret i32 2
}

; Note that the `load` has UB (so it will be changed to unreachable)
; and the branch is a terminator that can be constant-folded.
; We want to test that doing both won't cause a segfault.
; MODULE-NOT: @callee(
define internal i32 @callee(i1 %C, i32* %A) {
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@callee
; IS__CGSCC____-SAME: () #[[ATTR0]] {
; IS__CGSCC____-NEXT:  entry:
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       T:
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       F:
; IS__CGSCC____-NEXT:    ret i32 1
;
entry:
  %A.0 = load i32, i32* null
  br i1 %C, label %T, label %F

T:
  ret i32 %A.0

F:
  ret i32 1
}

define i32 @foo() {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@foo
; IS__TUNIT____-SAME: () #[[ATTR0]] {
; IS__TUNIT____-NEXT:    ret i32 1
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@foo
; IS__CGSCC____-SAME: () #[[ATTR2]] {
; IS__CGSCC____-NEXT:    [[X:%.*]] = call noundef i32 @callee() #[[ATTR10]]
; IS__CGSCC____-NEXT:    ret i32 [[X]]
;
  %X = call i32 @callee(i1 false, i32* null)
  ret i32 %X
}

; Tests for nonnull noundef attribute violation.
;
; Tests for argument position

define void @arg_nonnull_1(i32* nonnull %a) {
; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_1
; IS__TUNIT____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6:[0-9]+]] {
; IS__TUNIT____-NEXT:    store i32 0, i32* [[A]], align 4
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_1
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR9:[0-9]+]] {
; IS__CGSCC____-NEXT:    store i32 0, i32* [[A]], align 4
; IS__CGSCC____-NEXT:    ret void
;
  store i32 0, i32* %a
  ret void
}

define void @arg_nonnull_1_noundef_1(i32* nonnull noundef %a) {
; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_1_noundef_1
; IS__TUNIT____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR6]] {
; IS__TUNIT____-NEXT:    store i32 0, i32* [[A]], align 4
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_1_noundef_1
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR9]] {
; IS__CGSCC____-NEXT:    store i32 0, i32* [[A]], align 4
; IS__CGSCC____-NEXT:    ret void
;
  store i32 0, i32* %a
  ret void
}

define void @arg_nonnull_12(i32* nonnull %a, i32* nonnull %b, i32* %c) {
; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_12
; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]]) #[[ATTR6]] {
; IS__TUNIT____-NEXT:    [[D:%.*]] = icmp eq i32* [[C]], null
; IS__TUNIT____-NEXT:    br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    store i32 0, i32* [[A]], align 4
; IS__TUNIT____-NEXT:    br label [[RET:%.*]]
; IS__TUNIT____:       f:
; IS__TUNIT____-NEXT:    store i32 1, i32* [[B]], align 4
; IS__TUNIT____-NEXT:    br label [[RET]]
; IS__TUNIT____:       ret:
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_12
; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]]) #[[ATTR9]] {
; IS__CGSCC____-NEXT:    [[D:%.*]] = icmp eq i32* [[C]], null
; IS__CGSCC____-NEXT:    br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    store i32 0, i32* [[A]], align 4
; IS__CGSCC____-NEXT:    br label [[RET:%.*]]
; IS__CGSCC____:       f:
; IS__CGSCC____-NEXT:    store i32 1, i32* [[B]], align 4
; IS__CGSCC____-NEXT:    br label [[RET]]
; IS__CGSCC____:       ret:
; IS__CGSCC____-NEXT:    ret void
;
  %d = icmp eq i32* %c, null
  br i1 %d, label %t, label %f
t:
  store i32 0, i32* %a
  br label %ret
f:
  store i32 1, i32* %b
  br label %ret
ret:
  ret void
}

define void @arg_nonnull_12_noundef_2(i32* nonnull %a, i32* noundef nonnull %b, i32* %c) {
; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_12_noundef_2
; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree noundef nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]]) #[[ATTR6]] {
; IS__TUNIT____-NEXT:    [[D:%.*]] = icmp eq i32* [[C]], null
; IS__TUNIT____-NEXT:    br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    store i32 0, i32* [[A]], align 4
; IS__TUNIT____-NEXT:    br label [[RET:%.*]]
; IS__TUNIT____:       f:
; IS__TUNIT____-NEXT:    store i32 1, i32* [[B]], align 4
; IS__TUNIT____-NEXT:    br label [[RET]]
; IS__TUNIT____:       ret:
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_12_noundef_2
; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly [[A:%.*]], i32* nocapture nofree noundef nonnull writeonly [[B:%.*]], i32* nofree writeonly [[C:%.*]]) #[[ATTR9]] {
; IS__CGSCC____-NEXT:    [[D:%.*]] = icmp eq i32* [[C]], null
; IS__CGSCC____-NEXT:    br i1 [[D]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    store i32 0, i32* [[A]], align 4
; IS__CGSCC____-NEXT:    br label [[RET:%.*]]
; IS__CGSCC____:       f:
; IS__CGSCC____-NEXT:    store i32 1, i32* [[B]], align 4
; IS__CGSCC____-NEXT:    br label [[RET]]
; IS__CGSCC____:       ret:
; IS__CGSCC____-NEXT:    ret void
;
  %d = icmp eq i32* %c, null
  br i1 %d, label %t, label %f
t:
  store i32 0, i32* %a
  br label %ret
f:
  store i32 1, i32* %b
  br label %ret
ret:
  ret void
}

; Pass null directly to argument with nonnull attribute
define void @arg_nonnull_violation1_1() {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation1_1
; IS__TUNIT____-SAME: () #[[ATTR0]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation1_1
; IS__CGSCC____-SAME: () #[[ATTR2]] {
; IS__CGSCC____-NEXT:    unreachable
;
  call void @arg_nonnull_1(i32* null)
  ret void
}

define void @arg_nonnull_violation1_2() {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation1_2
; IS__TUNIT____-SAME: () #[[ATTR0]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation1_2
; IS__CGSCC____-SAME: () #[[ATTR2]] {
; IS__CGSCC____-NEXT:    unreachable
;
  call void @arg_nonnull_1_noundef_1(i32* null)
  ret void
}

; A case that depends on value simplification
define void @arg_nonnull_violation2_1(i1 %c) {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation2_1
; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation2_1
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
; IS__CGSCC____-NEXT:    unreachable
;
  %null = getelementptr i32, i32* null, i32 0
  %mustnull = select i1 %c, i32* null, i32* %null
  call void @arg_nonnull_1(i32* %mustnull)
  ret void
}

define void @arg_nonnull_violation2_2(i1 %c) {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation2_2
; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT:    unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation2_2
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
; IS__CGSCC____-NEXT:    unreachable
;
  %null = getelementptr i32, i32* null, i32 0
  %mustnull = select i1 %c, i32* null, i32* %null
  call void @arg_nonnull_1_noundef_1(i32* %mustnull)
  ret void
}

; Cases for single and multiple violation at a callsite
define void @arg_nonnull_violation3_1(i1 %c) {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_1
; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT:    [[PTR:%.*]] = alloca i32, align 4
; IS__TUNIT____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR7:[0-9]+]]
; IS__TUNIT____-NEXT:    call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR7]]
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       f:
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       ret:
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_1
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
; IS__CGSCC____-NEXT:    [[PTR:%.*]] = alloca i32, align 4
; IS__CGSCC____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR11:[0-9]+]]
; IS__CGSCC____-NEXT:    call void @arg_nonnull_12(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR11]]
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       f:
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       ret:
; IS__CGSCC____-NEXT:    ret void
;
  %ptr = alloca i32
  br i1 %c, label %t, label %f
t:
  call void @arg_nonnull_12(i32* %ptr, i32* %ptr, i32* %ptr)
  call void @arg_nonnull_12(i32* %ptr, i32* %ptr, i32* null)
  call void @arg_nonnull_12(i32* %ptr, i32* null, i32* %ptr)
  call void @arg_nonnull_12(i32* %ptr, i32* null, i32* null)
  br label %ret
f:
  call void @arg_nonnull_12(i32* null, i32* %ptr, i32* %ptr)
  call void @arg_nonnull_12(i32* null, i32* %ptr, i32* null)
  call void @arg_nonnull_12(i32* null, i32* null, i32* %ptr)
  call void @arg_nonnull_12(i32* null, i32* null, i32* null)
  br label %ret
ret:
  ret void
}

define void @arg_nonnull_violation3_2(i1 %c) {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_2
; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT:    [[PTR:%.*]] = alloca i32, align 4
; IS__TUNIT____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__TUNIT____:       t:
; IS__TUNIT____-NEXT:    call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR7]]
; IS__TUNIT____-NEXT:    call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR7]]
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       f:
; IS__TUNIT____-NEXT:    unreachable
; IS__TUNIT____:       ret:
; IS__TUNIT____-NEXT:    ret void
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@arg_nonnull_violation3_2
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
; IS__CGSCC____-NEXT:    [[PTR:%.*]] = alloca i32, align 4
; IS__CGSCC____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____:       t:
; IS__CGSCC____-NEXT:    call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]]) #[[ATTR11]]
; IS__CGSCC____-NEXT:    call void @arg_nonnull_12_noundef_2(i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[PTR]], i32* noalias nocapture nofree noundef writeonly align 4294967296 null) #[[ATTR11]]
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       f:
; IS__CGSCC____-NEXT:    unreachable
; IS__CGSCC____:       ret:
; IS__CGSCC____-NEXT:    ret void
;
  %ptr = alloca i32
  br i1 %c, label %t, label %f
t:
  call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* %ptr, i32* %ptr)
  call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* %ptr, i32* null)
  call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* null, i32* %ptr)
  call void @arg_nonnull_12_noundef_2(i32* %ptr, i32* null, i32* null)
  br label %ret
f:
  call void @arg_nonnull_12_noundef_2(i32* null, i32* %ptr, i32* %ptr)
  call void @arg_nonnull_12_noundef_2(i32* null, i32* %ptr, i32* null)
  call void @arg_nonnull_12_noundef_2(i32* null, i32* null, i32* %ptr)
  call void @arg_nonnull_12_noundef_2(i32* null, i32* null, i32* null)
  br label %ret
ret:
  ret void
}

; Tests for returned position

define nonnull i32* @returned_nonnnull(i32 %c) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@returned_nonnnull
; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    switch i32 [[C]], label [[ONDEFAULT:%.*]] [
; CHECK-NEXT:    i32 0, label [[ONZERO:%.*]]
; CHECK-NEXT:    i32 1, label [[ONONE:%.*]]
; CHECK-NEXT:    ]
; CHECK:       onzero:
; CHECK-NEXT:    [[PTR:%.*]] = alloca i32, align 4
; CHECK-NEXT:    ret i32* [[PTR]]
; CHECK:       onone:
; CHECK-NEXT:    ret i32* null
; CHECK:       ondefault:
; CHECK-NEXT:    ret i32* undef
;
  switch i32 %c, label %ondefault [ i32 0, label %onzero
  i32 1, label %onone ]
onzero:
  %ptr = alloca i32
  ret i32* %ptr
onone:
  ret i32* null
ondefault:
  ret i32* undef
}

define noundef i32* @returned_noundef(i32 %c) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@returned_noundef
; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    switch i32 [[C]], label [[ONDEFAULT:%.*]] [
; CHECK-NEXT:    i32 0, label [[ONZERO:%.*]]
; CHECK-NEXT:    i32 1, label [[ONONE:%.*]]
; CHECK-NEXT:    ]
; CHECK:       onzero:
; CHECK-NEXT:    [[PTR:%.*]] = alloca i32, align 4
; CHECK-NEXT:    ret i32* [[PTR]]
; CHECK:       onone:
; CHECK-NEXT:    ret i32* null
; CHECK:       ondefault:
; CHECK-NEXT:    unreachable
;
  switch i32 %c, label %ondefault [ i32 0, label %onzero
  i32 1, label %onone ]
onzero:
  %ptr = alloca i32
  ret i32* %ptr
onone:
  ret i32* null
ondefault:
  ret i32* undef
}

define nonnull noundef i32* @returned_nonnnull_noundef(i32 %c) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@returned_nonnnull_noundef
; CHECK-SAME: (i32 [[C:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    switch i32 [[C]], label [[ONDEFAULT:%.*]] [
; CHECK-NEXT:    i32 0, label [[ONZERO:%.*]]
; CHECK-NEXT:    i32 1, label [[ONONE:%.*]]
; CHECK-NEXT:    ]
; CHECK:       onzero:
; CHECK-NEXT:    [[PTR:%.*]] = alloca i32, align 4
; CHECK-NEXT:    ret i32* [[PTR]]
; CHECK:       onone:
; CHECK-NEXT:    unreachable
; CHECK:       ondefault:
; CHECK-NEXT:    unreachable
;
  switch i32 %c, label %ondefault [ i32 0, label %onzero
  i32 1, label %onone ]
onzero:
  %ptr = alloca i32
  ret i32* %ptr
onone:
  ret i32* null
ondefault:
  ret i32* undef
}

define noundef i32 @returned_nonnnull_noundef_int() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@returned_nonnnull_noundef_int
; CHECK-SAME: () #[[ATTR0]] {
; CHECK-NEXT:    ret i32 0
;
  ret i32 0
}

declare void @callee_int_arg(i32)

define void @callsite_noundef_1() {
; CHECK-LABEL: define {{[^@]+}}@callsite_noundef_1() {
; CHECK-NEXT:    call void @callee_int_arg(i32 noundef 0)
; CHECK-NEXT:    ret void
;
  call void @callee_int_arg(i32 noundef 0)
  ret void
}

declare void @callee_ptr_arg(i32*)

define void @callsite_noundef_2() {
; CHECK-LABEL: define {{[^@]+}}@callsite_noundef_2() {
; CHECK-NEXT:    unreachable
;
  call void @callee_ptr_arg(i32* noundef undef)
  ret void
}

define i32 @argument_noundef1(i32 noundef %c) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@argument_noundef1
; CHECK-SAME: (i32 noundef returned [[C:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    ret i32 [[C]]
;
  ret i32 %c
}

define i32 @violate_noundef_nonpointer() {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@violate_noundef_nonpointer
; IS__TUNIT____-SAME: () #[[ATTR0]] {
; IS__TUNIT____-NEXT:    ret i32 undef
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@violate_noundef_nonpointer
; IS__CGSCC____-SAME: () #[[ATTR2]] {
; IS__CGSCC____-NEXT:    unreachable
;
  %ret = call i32 @argument_noundef1(i32 undef)
  ret i32 %ret
}

define i32* @argument_noundef2(i32* noundef %c) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@argument_noundef2
; CHECK-SAME: (i32* nofree noundef readnone returned "no-capture-maybe-returned" [[C:%.*]]) #[[ATTR0]] {
; CHECK-NEXT:    ret i32* [[C]]
;
  ret i32* %c
}

define i32* @violate_noundef_pointer() {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@violate_noundef_pointer
; IS__TUNIT____-SAME: () #[[ATTR0]] {
; IS__TUNIT____-NEXT:    ret i32* undef
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@violate_noundef_pointer
; IS__CGSCC____-SAME: () #[[ATTR2]] {
; IS__CGSCC____-NEXT:    ret i32* undef
;
  %ret = call i32* @argument_noundef2(i32* undef)
  ret i32* %ret
}

define internal noundef i32 @assumed_undef_is_ok(i1 %c, i32 %arg) {
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@assumed_undef_is_ok
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
; IS__CGSCC____-NEXT:    br i1 [[C]], label [[REC:%.*]], label [[RET:%.*]]
; IS__CGSCC____:       rec:
; IS__CGSCC____-NEXT:    br label [[RET]]
; IS__CGSCC____:       ret:
; IS__CGSCC____-NEXT:    ret i32 0
;
  %stack = alloca i32
  store i32 %arg, i32* %stack
  br i1 %c, label %rec, label %ret
rec:
  %call = call i32 @assumed_undef_is_ok(i1 false, i32 0)
  store i32 %call, i32* %stack
  br label %ret
ret:
  %l = load i32, i32* %stack
  ret i32 %l
}

define noundef i32 @assumed_undef_is_ok_caller(i1 %c) {
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@assumed_undef_is_ok_caller
; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT:    ret i32 0
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@assumed_undef_is_ok_caller
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i32 @assumed_undef_is_ok(i1 [[C]]) #[[ATTR10]]
; IS__CGSCC____-NEXT:    ret i32 [[CALL]]
;
  %call = call i32 @assumed_undef_is_ok(i1 %c, i32 undef)
  ret i32 %call
}

;.
; IS__TUNIT____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__TUNIT____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn }
; IS__TUNIT____: attributes #[[ATTR2]] = { nofree norecurse nounwind readnone willreturn }
; IS__TUNIT____: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly }
; IS__TUNIT____: attributes #[[ATTR4]] = { nofree norecurse nounwind null_pointer_is_valid willreturn }
; IS__TUNIT____: attributes #[[ATTR5]] = { nofree norecurse noreturn nosync nounwind readnone willreturn }
; IS__TUNIT____: attributes #[[ATTR6]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
; IS__TUNIT____: attributes #[[ATTR7]] = { nofree nosync nounwind willreturn writeonly }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR3]] = { nofree norecurse nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR4]] = { nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly }
; IS__CGSCC____: attributes #[[ATTR5]] = { nofree nosync nounwind willreturn writeonly }
; IS__CGSCC____: attributes #[[ATTR6]] = { nofree norecurse nounwind null_pointer_is_valid willreturn }
; IS__CGSCC____: attributes #[[ATTR7]] = { nofree nounwind willreturn }
; IS__CGSCC____: attributes #[[ATTR8]] = { nofree norecurse noreturn nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR9]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
; IS__CGSCC____: attributes #[[ATTR10]] = { readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR11]] = { nounwind willreturn writeonly }
;.