; 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 @Gstatic_int1 = internal global i32 zeroinitializer, align 4 @Gstatic_int2 = internal global i32 zeroinitializer, align 4 declare void @llvm.assume(i1) declare void @useI1p(ptr) declare void @unknown() ;. ; CHECK: @[[GSTATIC_INT1:[a-zA-Z0-9_$"\\.-]+]] = internal global i32 0, align 4 ; CHECK: @[[GSTATIC_INT2:[a-zA-Z0-9_$"\\.-]+]] = internal global i32 0, align 4 ;. define i1 @readI1p(ptr %p) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) ; CHECK-LABEL: define {{[^@]+}}@readI1p ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly dereferenceable(1) [[P:%.*]]) #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: [[L:%.*]] = load i1, ptr [[P]], align 1 ; CHECK-NEXT: ret i1 [[L]] ; %l = load i1, ptr %p ret i1 %l } define i1 @keep_assume_1c_nr() norecurse { ; CHECK: Function Attrs: norecurse ; CHECK-LABEL: define {{[^@]+}}@keep_assume_1c_nr ; CHECK-SAME: () #[[ATTR2:[0-9]+]] { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: store i1 true, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CHECK-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[L]]) ; CHECK-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 true, ptr %stack call void @useI1p(ptr %stack) %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define i1 @drop_assume_1c_nr() norecurse { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) ; TUNIT-LABEL: define {{[^@]+}}@drop_assume_1c_nr ; TUNIT-SAME: () #[[ATTR3:[0-9]+]] { ; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR7:[0-9]+]] ; TUNIT-NEXT: ret i1 true ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) ; CGSCC-LABEL: define {{[^@]+}}@drop_assume_1c_nr ; CGSCC-SAME: () #[[ATTR3:[0-9]+]] { ; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR8:[0-9]+]] ; CGSCC-NEXT: ret i1 true ; %stack = alloca i1 store i1 true, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define i1 @keep_assume_2c_nr() norecurse { ; CHECK: Function Attrs: norecurse ; CHECK-LABEL: define {{[^@]+}}@keep_assume_2c_nr ; CHECK-SAME: () #[[ATTR2]] { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: store i1 true, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CHECK-NEXT: [[L1:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[L1]]) ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: ret i1 [[L2]] ; %stack = alloca i1 store i1 true, ptr %stack call void @useI1p(ptr %stack) %l1 = load i1, ptr %stack call void @llvm.assume(i1 %l1) call void @unknown() %l2 = load i1, ptr %stack ret i1 %l2 } define i1 @keep_assume_3c_nr() norecurse { ; ; TUNIT: Function Attrs: norecurse ; TUNIT-LABEL: define {{[^@]+}}@keep_assume_3c_nr ; TUNIT-SAME: () #[[ATTR2]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]] ; TUNIT-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; TUNIT-NEXT: ret i1 [[L]] ; ; CGSCC: Function Attrs: norecurse ; CGSCC-LABEL: define {{[^@]+}}@keep_assume_3c_nr ; CGSCC-SAME: () #[[ATTR2]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CGSCC-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 true, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) call void @useI1p(ptr %stack) ret i1 %l } define i1 @keep_assume_4c_nr() norecurse { ; ; TUNIT: Function Attrs: norecurse ; TUNIT-LABEL: define {{[^@]+}}@keep_assume_4c_nr ; TUNIT-SAME: () #[[ATTR2]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR7]] ; TUNIT-NEXT: call void @useI1p(ptr noalias nocapture noundef nonnull dereferenceable(1) [[STACK]]) ; TUNIT-NEXT: ret i1 true ; ; CGSCC: Function Attrs: norecurse ; CGSCC-LABEL: define {{[^@]+}}@keep_assume_4c_nr ; CGSCC-SAME: () #[[ATTR2]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR8]] ; CGSCC-NEXT: call void @useI1p(ptr noalias nocapture noundef nonnull dereferenceable(1) [[STACK]]) ; CGSCC-NEXT: ret i1 true ; %stack = alloca i1 store i1 true, ptr %stack %l4 = load i1, ptr %stack call void @llvm.assume(i1 %l4) call void @useI1p(ptr nocapture %stack) ret i1 %l4 } define i1 @keep_assume_1_nr(i1 %arg) norecurse { ; CHECK: Function Attrs: norecurse ; CHECK-LABEL: define {{[^@]+}}@keep_assume_1_nr ; CHECK-SAME: (i1 [[ARG:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CHECK-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CHECK-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[L]]) ; CHECK-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 %arg, ptr %stack call void @useI1p(ptr %stack) %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define i1 @drop_assume_1_nr(i1 %arg) norecurse { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@drop_assume_1_nr ; TUNIT-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR4:[0-9]+]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]] ; TUNIT-NEXT: ret i1 [[ARG]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@drop_assume_1_nr ; CGSCC-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR4:[0-9]+]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]] ; CGSCC-NEXT: ret i1 [[ARG]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define i1 @keep_assume_2_nr(i1 %arg) norecurse { ; CHECK: Function Attrs: norecurse ; CHECK-LABEL: define {{[^@]+}}@keep_assume_2_nr ; CHECK-SAME: (i1 [[ARG:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CHECK-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CHECK-NEXT: [[L1:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[L1]]) ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: ret i1 [[L2]] ; %stack = alloca i1 store i1 %arg, ptr %stack call void @useI1p(ptr %stack) %l1 = load i1, ptr %stack call void @llvm.assume(i1 %l1) call void @unknown() %l2 = load i1, ptr %stack ret i1 %l2 } define i1 @keep_assume_3_nr(i1 %arg) norecurse { ; ; TUNIT: Function Attrs: norecurse ; TUNIT-LABEL: define {{[^@]+}}@keep_assume_3_nr ; TUNIT-SAME: (i1 [[ARG:%.*]]) #[[ATTR2]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]] ; TUNIT-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; TUNIT-NEXT: ret i1 [[L]] ; ; CGSCC: Function Attrs: norecurse ; CGSCC-LABEL: define {{[^@]+}}@keep_assume_3_nr ; CGSCC-SAME: (i1 [[ARG:%.*]]) #[[ATTR2]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CGSCC-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) call void @useI1p(ptr %stack) ret i1 %l } define i1 @keep_assume_4_nr(i1 %arg) norecurse { ; ; TUNIT: Function Attrs: norecurse ; TUNIT-LABEL: define {{[^@]+}}@keep_assume_4_nr ; TUNIT-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR2]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]] ; TUNIT-NEXT: call void @useI1p(ptr noalias nocapture noundef nonnull dereferenceable(1) [[STACK]]) ; TUNIT-NEXT: ret i1 [[ARG]] ; ; CGSCC: Function Attrs: norecurse ; CGSCC-LABEL: define {{[^@]+}}@keep_assume_4_nr ; CGSCC-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR2]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]] ; CGSCC-NEXT: call void @useI1p(ptr noalias nocapture noundef nonnull dereferenceable(1) [[STACK]]) ; CGSCC-NEXT: ret i1 [[ARG]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) call void @useI1p(ptr nocapture %stack) ret i1 %l } define i1 @assume_1_nr(i1 %arg, i1 %cond) norecurse { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_1_nr ; TUNIT-SAME: (i1 returned [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]] ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: ret i1 [[ARG]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_1_nr ; CGSCC-SAME: (i1 returned [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]] ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: ret i1 [[ARG]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: ret i1 %l } define void @assume_1b_nr(i1 %arg, i1 %cond) norecurse { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@assume_1b_nr ; CHECK-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4:[0-9]+]] { ; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CHECK: t: ; CHECK-NEXT: br label [[M:%.*]] ; CHECK: f: ; CHECK-NEXT: br label [[M]] ; CHECK: m: ; CHECK-NEXT: ret void ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: ret void } define i1 @assume_2_nr(i1 %arg, i1 %cond) norecurse { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_2_nr ; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]] ; TUNIT-NEXT: ret i1 [[L]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_2_nr ; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 %arg, ptr %stack br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define void @assume_2b_nr(i1 %arg, i1 %cond) norecurse { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@assume_2b_nr ; CHECK-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CHECK: t: ; CHECK-NEXT: br label [[M:%.*]] ; CHECK: f: ; CHECK-NEXT: br label [[M]] ; CHECK: m: ; CHECK-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: ret void ; %stack = alloca i1 store i1 %arg, ptr %stack br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret void } define i1 @assume_3_nr(i1 %arg, i1 %cond) norecurse { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_3_nr ; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR8:[0-9]+]] ; TUNIT-NEXT: ret i1 [[R]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_3_nr ; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR9:[0-9]+]] ; CGSCC-NEXT: ret i1 [[R]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: %r = call i1 @readI1p(ptr %stack) ret i1 %r } define i1 @assume_4_nr(i1 %arg, i1 %cond) norecurse { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_4_nr ; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]] ; TUNIT-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR8]] ; TUNIT-NEXT: ret i1 [[R]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_4_nr ; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR9]] ; CGSCC-NEXT: ret i1 [[R]] ; %stack = alloca i1 store i1 %arg, ptr %stack br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: %l = load i1, ptr %stack call void @llvm.assume(i1 %l) %r = call i1 @readI1p(ptr %stack) ret i1 %r } define i1 @assume_5_nr(i1 %arg, i1 %cond) norecurse { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_5_nr ; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR7]] ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L3:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR7]] ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR9:[0-9]+]] ; TUNIT-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR8]] ; TUNIT-NEXT: ret i1 [[R]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_5_nr ; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L1:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L1]]) #[[ATTR8]] ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR10:[0-9]+]] ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L3:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR10]] ; CGSCC-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR10]] ; CGSCC-NEXT: ret i1 [[R]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l1 = load i1, ptr %stack call void @llvm.assume(i1 %l1) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack %l2 = load i1, ptr %stack call void @llvm.assume(i1 %l2) br label %m f: store i1 false, ptr %stack %l3 = load i1, ptr %stack call void @llvm.assume(i1 %l3) br label %m m: %l4 = load i1, ptr %stack call void @llvm.assume(i1 %l4) %r = call i1 @readI1p(ptr %stack) ret i1 %r } define i1 @assume_5c_nr(i1 %cond) norecurse { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_5c_nr ; TUNIT-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR7]] ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR7]] ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L3:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR7]] ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR9]] ; TUNIT-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR8]] ; TUNIT-NEXT: ret i1 [[R]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_5c_nr ; CGSCC-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L1:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L1]]) #[[ATTR8]] ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L3:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR10]] ; CGSCC-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR10]] ; CGSCC-NEXT: ret i1 [[R]] ; %stack = alloca i1 store i1 true, ptr %stack %l1 = load i1, ptr %stack call void @llvm.assume(i1 %l1) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack %l2 = load i1, ptr %stack call void @llvm.assume(i1 %l2) br label %m f: store i1 false, ptr %stack %l3 = load i1, ptr %stack call void @llvm.assume(i1 %l3) br label %m m: %l4 = load i1, ptr %stack call void @llvm.assume(i1 %l4) %r = call i1 @readI1p(ptr %stack) ret i1 %r } define i1 @keep_assume_1c() { ; CHECK-LABEL: define {{[^@]+}}@keep_assume_1c() { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: store i1 true, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CHECK-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[L]]) ; CHECK-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 true, ptr %stack call void @useI1p(ptr %stack) %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define i1 @drop_assume_1c() { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) ; TUNIT-LABEL: define {{[^@]+}}@drop_assume_1c ; TUNIT-SAME: () #[[ATTR3]] { ; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR7]] ; TUNIT-NEXT: ret i1 true ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) ; CGSCC-LABEL: define {{[^@]+}}@drop_assume_1c ; CGSCC-SAME: () #[[ATTR3]] { ; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR8]] ; CGSCC-NEXT: ret i1 true ; %stack = alloca i1 store i1 true, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define i1 @keep_assume_2c() { ; CHECK-LABEL: define {{[^@]+}}@keep_assume_2c() { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: store i1 true, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CHECK-NEXT: [[L1:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[L1]]) ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: ret i1 [[L2]] ; %stack = alloca i1 store i1 true, ptr %stack call void @useI1p(ptr %stack) %l1 = load i1, ptr %stack call void @llvm.assume(i1 %l1) call void @unknown() %l2 = load i1, ptr %stack ret i1 %l2 } define i1 @keep_assume_3c() { ; ; TUNIT-LABEL: define {{[^@]+}}@keep_assume_3c() { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]] ; TUNIT-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; TUNIT-NEXT: ret i1 [[L]] ; ; CGSCC-LABEL: define {{[^@]+}}@keep_assume_3c() { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CGSCC-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 true, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) call void @useI1p(ptr %stack) ret i1 %l } define i1 @keep_assume_4c() { ; ; TUNIT-LABEL: define {{[^@]+}}@keep_assume_4c() { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR7]] ; TUNIT-NEXT: call void @useI1p(ptr noalias nocapture noundef nonnull dereferenceable(1) [[STACK]]) ; TUNIT-NEXT: ret i1 [[L4]] ; ; CGSCC-LABEL: define {{[^@]+}}@keep_assume_4c() { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR8]] ; CGSCC-NEXT: call void @useI1p(ptr noalias nocapture noundef nonnull dereferenceable(1) [[STACK]]) ; CGSCC-NEXT: ret i1 [[L4]] ; %stack = alloca i1 store i1 true, ptr %stack %l4 = load i1, ptr %stack call void @llvm.assume(i1 %l4) call void @useI1p(ptr nocapture %stack) ret i1 %l4 } define i1 @keep_assume_1(i1 %arg) { ; CHECK-LABEL: define {{[^@]+}}@keep_assume_1 ; CHECK-SAME: (i1 [[ARG:%.*]]) { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CHECK-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CHECK-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[L]]) ; CHECK-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 %arg, ptr %stack call void @useI1p(ptr %stack) %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define i1 @drop_assume_1(i1 %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@drop_assume_1 ; TUNIT-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]] ; TUNIT-NEXT: ret i1 [[ARG]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@drop_assume_1 ; CGSCC-SAME: (i1 returned [[ARG:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]] ; CGSCC-NEXT: ret i1 [[ARG]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define i1 @keep_assume_2(i1 %arg) { ; CHECK-LABEL: define {{[^@]+}}@keep_assume_2 ; CHECK-SAME: (i1 [[ARG:%.*]]) { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CHECK-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CHECK-NEXT: [[L1:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: call void @llvm.assume(i1 noundef [[L1]]) ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: ret i1 [[L2]] ; %stack = alloca i1 store i1 %arg, ptr %stack call void @useI1p(ptr %stack) %l1 = load i1, ptr %stack call void @llvm.assume(i1 %l1) call void @unknown() %l2 = load i1, ptr %stack ret i1 %l2 } define i1 @keep_assume_3(i1 %arg) { ; ; TUNIT-LABEL: define {{[^@]+}}@keep_assume_3 ; TUNIT-SAME: (i1 [[ARG:%.*]]) { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]] ; TUNIT-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; TUNIT-NEXT: ret i1 [[L]] ; ; CGSCC-LABEL: define {{[^@]+}}@keep_assume_3 ; CGSCC-SAME: (i1 [[ARG:%.*]]) { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: call void @useI1p(ptr noundef nonnull dereferenceable(1) [[STACK]]) ; CGSCC-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) call void @useI1p(ptr %stack) ret i1 %l } define i1 @keep_assume_4(i1 %arg) { ; ; TUNIT-LABEL: define {{[^@]+}}@keep_assume_4 ; TUNIT-SAME: (i1 [[ARG:%.*]]) { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]] ; TUNIT-NEXT: call void @useI1p(ptr noalias nocapture noundef nonnull dereferenceable(1) [[STACK]]) ; TUNIT-NEXT: ret i1 [[L]] ; ; CGSCC-LABEL: define {{[^@]+}}@keep_assume_4 ; CGSCC-SAME: (i1 [[ARG:%.*]]) { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: call void @useI1p(ptr noalias nocapture noundef nonnull dereferenceable(1) [[STACK]]) ; CGSCC-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) call void @useI1p(ptr nocapture %stack) ret i1 %l } define i1 @assume_1(i1 %arg, i1 %cond) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_1 ; TUNIT-SAME: (i1 returned [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR7]] ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: ret i1 [[ARG]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_1 ; CGSCC-SAME: (i1 returned [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[ARG]]) #[[ATTR8]] ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: ret i1 [[ARG]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: ret i1 %l } define void @assume_1b(i1 %arg, i1 %cond) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@assume_1b ; CHECK-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CHECK: t: ; CHECK-NEXT: br label [[M:%.*]] ; CHECK: f: ; CHECK-NEXT: br label [[M]] ; CHECK: m: ; CHECK-NEXT: ret void ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: ret void } define i1 @assume_2(i1 %arg, i1 %cond) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_2 ; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]] ; TUNIT-NEXT: ret i1 [[L]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_2 ; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: ret i1 [[L]] ; %stack = alloca i1 store i1 %arg, ptr %stack br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret i1 %l } define void @assume_2b(i1 %arg, i1 %cond) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CHECK-LABEL: define {{[^@]+}}@assume_2b ; CHECK-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; CHECK-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CHECK: t: ; CHECK-NEXT: br label [[M:%.*]] ; CHECK: f: ; CHECK-NEXT: br label [[M]] ; CHECK: m: ; CHECK-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CHECK-NEXT: ret void ; %stack = alloca i1 store i1 %arg, ptr %stack br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: %l = load i1, ptr %stack call void @llvm.assume(i1 %l) ret void } define i1 @assume_3(i1 %arg, i1 %cond) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_3 ; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR8]] ; TUNIT-NEXT: ret i1 [[R]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_3 ; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR5:[0-9]+]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR9]] ; CGSCC-NEXT: ret i1 [[R]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l = load i1, ptr %stack call void @llvm.assume(i1 %l) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: %r = call i1 @readI1p(ptr %stack) ret i1 %r } define i1 @assume_4(i1 %arg, i1 %cond) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_4 ; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR7]] ; TUNIT-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR8]] ; TUNIT-NEXT: ret i1 [[R]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_4 ; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR5]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[L:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L]]) #[[ATTR8]] ; CGSCC-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR9]] ; CGSCC-NEXT: ret i1 [[R]] ; %stack = alloca i1 store i1 %arg, ptr %stack br i1 %cond, label %t, label %f t: store i1 true, ptr %stack br label %m f: store i1 false, ptr %stack br label %m m: %l = load i1, ptr %stack call void @llvm.assume(i1 %l) %r = call i1 @readI1p(ptr %stack) ret i1 %r } define i1 @assume_5(i1 %arg, i1 %cond) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_5 ; TUNIT-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR7]] ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L3:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR7]] ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR9]] ; TUNIT-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR8]] ; TUNIT-NEXT: ret i1 [[R]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_5 ; CGSCC-SAME: (i1 [[ARG:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR5]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 [[ARG]], ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L1:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L1]]) #[[ATTR8]] ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L3:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR10]] ; CGSCC-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR10]] ; CGSCC-NEXT: ret i1 [[R]] ; %stack = alloca i1 store i1 %arg, ptr %stack %l1 = load i1, ptr %stack call void @llvm.assume(i1 %l1) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack %l2 = load i1, ptr %stack call void @llvm.assume(i1 %l2) br label %m f: store i1 false, ptr %stack %l3 = load i1, ptr %stack call void @llvm.assume(i1 %l3) br label %m m: %l4 = load i1, ptr %stack call void @llvm.assume(i1 %l4) %r = call i1 @readI1p(ptr %stack) ret i1 %r } define i1 @assume_5c(i1 %cond) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; TUNIT-LABEL: define {{[^@]+}}@assume_5c ; TUNIT-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR4]] { ; TUNIT-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR7]] ; TUNIT-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; TUNIT: t: ; TUNIT-NEXT: store i1 true, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR7]] ; TUNIT-NEXT: br label [[M:%.*]] ; TUNIT: f: ; TUNIT-NEXT: store i1 false, ptr [[STACK]], align 1 ; TUNIT-NEXT: [[L3:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR7]] ; TUNIT-NEXT: br label [[M]] ; TUNIT: m: ; TUNIT-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR9]] ; TUNIT-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR8]] ; TUNIT-NEXT: ret i1 [[R]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) ; CGSCC-LABEL: define {{[^@]+}}@assume_5c ; CGSCC-SAME: (i1 noundef [[COND:%.*]]) #[[ATTR5]] { ; CGSCC-NEXT: [[STACK:%.*]] = alloca i1, align 1 ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L1:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L1]]) #[[ATTR8]] ; CGSCC-NEXT: br i1 [[COND]], label [[T:%.*]], label [[F:%.*]] ; CGSCC: t: ; CGSCC-NEXT: store i1 true, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L2:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L2]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[M:%.*]] ; CGSCC: f: ; CGSCC-NEXT: store i1 false, ptr [[STACK]], align 1 ; CGSCC-NEXT: [[L3:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L3]]) #[[ATTR10]] ; CGSCC-NEXT: br label [[M]] ; CGSCC: m: ; CGSCC-NEXT: [[L4:%.*]] = load i1, ptr [[STACK]], align 1 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[L4]]) #[[ATTR10]] ; CGSCC-NEXT: [[R:%.*]] = call i1 @readI1p(ptr noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[STACK]]) #[[ATTR10]] ; CGSCC-NEXT: ret i1 [[R]] ; %stack = alloca i1 store i1 true, ptr %stack %l1 = load i1, ptr %stack call void @llvm.assume(i1 %l1) br i1 %cond, label %t, label %f t: store i1 true, ptr %stack %l2 = load i1, ptr %stack call void @llvm.assume(i1 %l2) br label %m f: store i1 false, ptr %stack %l3 = load i1, ptr %stack call void @llvm.assume(i1 %l3) br label %m m: %l4 = load i1, ptr %stack call void @llvm.assume(i1 %l4) %r = call i1 @readI1p(ptr %stack) ret i1 %r } define i32 @assume_read_global_good() { ; ; ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn ; TUNIT-LABEL: define {{[^@]+}}@assume_read_global_good ; TUNIT-SAME: () #[[ATTR5:[0-9]+]] { ; TUNIT-NEXT: [[LGS1:%.*]] = load i32, ptr @Gstatic_int1, align 4 ; TUNIT-NEXT: [[C:%.*]] = icmp eq i32 [[LGS1]], 42 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[C]]) #[[ATTR7]] ; TUNIT-NEXT: [[LGS2:%.*]] = load i32, ptr @Gstatic_int1, align 4 ; TUNIT-NEXT: store i32 17, ptr @Gstatic_int1, align 4 ; TUNIT-NEXT: [[LGS3:%.*]] = load i32, ptr @Gstatic_int1, align 4 ; TUNIT-NEXT: [[ADD:%.*]] = add i32 [[LGS2]], [[LGS3]] ; TUNIT-NEXT: ret i32 [[ADD]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn ; CGSCC-LABEL: define {{[^@]+}}@assume_read_global_good ; CGSCC-SAME: () #[[ATTR6:[0-9]+]] { ; CGSCC-NEXT: [[LGS1:%.*]] = load i32, ptr @Gstatic_int1, align 4 ; CGSCC-NEXT: [[C:%.*]] = icmp eq i32 [[LGS1]], 42 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[C]]) #[[ATTR8]] ; CGSCC-NEXT: [[LGS2:%.*]] = load i32, ptr @Gstatic_int1, align 4 ; CGSCC-NEXT: store i32 17, ptr @Gstatic_int1, align 4 ; CGSCC-NEXT: [[LGS3:%.*]] = load i32, ptr @Gstatic_int1, align 4 ; CGSCC-NEXT: [[ADD:%.*]] = add i32 [[LGS2]], [[LGS3]] ; CGSCC-NEXT: ret i32 [[ADD]] ; %lgs1 = load i32, ptr @Gstatic_int1 %c = icmp eq i32 %lgs1, 42 call void @llvm.assume(i1 %c) %lgs2 = load i32, ptr @Gstatic_int1 store i32 13, ptr @Gstatic_int1, align 4 store i32 17, ptr @Gstatic_int1, align 4 %lgs3 = load i32, ptr @Gstatic_int1 %add = add i32 %lgs2, %lgs3 ret i32 %add } ; TODO: Technically we could still utilize the assumption if we employ AA. define i32 @assume_read_global_bad(ptr %p) { ; ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn ; TUNIT-LABEL: define {{[^@]+}}@assume_read_global_bad ; TUNIT-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR5]] { ; TUNIT-NEXT: [[LGS1:%.*]] = load i32, ptr @Gstatic_int2, align 4 ; TUNIT-NEXT: [[C:%.*]] = icmp eq i32 [[LGS1]], 42 ; TUNIT-NEXT: store i32 13, ptr [[P]], align 4 ; TUNIT-NEXT: call void @llvm.assume(i1 noundef [[C]]) #[[ATTR7]] ; TUNIT-NEXT: [[LGS2:%.*]] = load i32, ptr @Gstatic_int2, align 4 ; TUNIT-NEXT: store i32 17, ptr @Gstatic_int2, align 4 ; TUNIT-NEXT: ret i32 [[LGS2]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn ; CGSCC-LABEL: define {{[^@]+}}@assume_read_global_bad ; CGSCC-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR6]] { ; CGSCC-NEXT: [[LGS1:%.*]] = load i32, ptr @Gstatic_int2, align 4 ; CGSCC-NEXT: [[C:%.*]] = icmp eq i32 [[LGS1]], 42 ; CGSCC-NEXT: store i32 13, ptr [[P]], align 4 ; CGSCC-NEXT: call void @llvm.assume(i1 noundef [[C]]) #[[ATTR8]] ; CGSCC-NEXT: [[LGS2:%.*]] = load i32, ptr @Gstatic_int2, align 4 ; CGSCC-NEXT: store i32 17, ptr @Gstatic_int2, align 4 ; CGSCC-NEXT: ret i32 [[LGS2]] ; %lgs1 = load i32, ptr @Gstatic_int2 %c = icmp eq i32 %lgs1, 42 store i32 13, ptr %p, align 4 call void @llvm.assume(i1 %c) %lgs2 = load i32, ptr @Gstatic_int2 store i32 17, ptr @Gstatic_int2, align 4 ret i32 %lgs2 } define void @assume_write_globals() { ; ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; TUNIT-LABEL: define {{[^@]+}}@assume_write_globals ; TUNIT-SAME: () #[[ATTR6:[0-9]+]] { ; TUNIT-NEXT: store i32 42, ptr @Gstatic_int1, align 4 ; TUNIT-NEXT: store i32 42, ptr @Gstatic_int2, align 4 ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; CGSCC-LABEL: define {{[^@]+}}@assume_write_globals ; CGSCC-SAME: () #[[ATTR7:[0-9]+]] { ; CGSCC-NEXT: store i32 42, ptr @Gstatic_int1, align 4 ; CGSCC-NEXT: store i32 42, ptr @Gstatic_int2, align 4 ; CGSCC-NEXT: ret void ; store i32 42, ptr @Gstatic_int1, align 4 store i32 42, ptr @Gstatic_int2, align 4 ret void } ;. ; TUNIT: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) } ; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } ; TUNIT: attributes #[[ATTR2]] = { norecurse } ; TUNIT: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) } ; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) } ; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn } ; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } ; TUNIT: attributes #[[ATTR7]] = { nofree willreturn memory(write) } ; TUNIT: attributes #[[ATTR8]] = { nofree nosync nounwind willreturn memory(read) } ; TUNIT: attributes #[[ATTR9]] = { nofree willreturn } ;. ; CGSCC: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) } ; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } ; CGSCC: attributes #[[ATTR2]] = { norecurse } ; CGSCC: attributes #[[ATTR3]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: write) } ; CGSCC: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(inaccessiblemem: readwrite) } ; CGSCC: attributes #[[ATTR5]] = { mustprogress nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) } ; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn } ; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } ; CGSCC: attributes #[[ATTR8]] = { nofree willreturn memory(write) } ; CGSCC: attributes #[[ATTR9]] = { nofree willreturn memory(read) } ; CGSCC: attributes #[[ATTR10]] = { nofree willreturn } ;.