; 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 ; TEST 1 - negative. ; void *G; ; void *foo(){ ; void *V = malloc(4); ; G = V; ; return V; ; } @G = external global ptr ;. ; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = external global ptr ; CHECK: @[[ALIAS_OF_P:[a-zA-Z0-9_$"\\.-]+]] = external global ptr ;. define ptr @foo() { ; CHECK-LABEL: define {{[^@]+}}@foo() { ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: store ptr [[TMP1]], ptr @G, align 8 ; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = tail call noalias ptr @malloc(i64 4) store ptr %1, ptr @G, align 8 ret ptr %1 } declare noalias ptr @malloc(i64) ; TEST 2 ; call noalias function in return instruction. define ptr @return_noalias(){ ; CHECK-LABEL: define {{[^@]+}}@return_noalias() { ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = tail call noalias ptr @malloc(i64 4) ret ptr %1 } define void @nocapture(ptr %a){ ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@nocapture ; CHECK-SAME: (ptr nocapture nofree readnone [[A:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: ret void ; ret void } define ptr @return_noalias_looks_like_capture(){ ; CHECK-LABEL: define {{[^@]+}}@return_noalias_looks_like_capture() { ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = tail call noalias ptr @malloc(i64 4) call void @nocapture(ptr %1) ret ptr %1 } define ptr @return_noalias_casted(){ ; CHECK-LABEL: define {{[^@]+}}@return_noalias_casted() { ; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = tail call noalias ptr @malloc(i64 4) ret ptr %1 } declare ptr @alias() ; TEST 3 define ptr @call_alias(){ ; CHECK-LABEL: define {{[^@]+}}@call_alias() { ; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @alias() ; CHECK-NEXT: ret ptr [[TMP1]] ; %1 = tail call ptr @alias() ret ptr %1 } ; TEST 4 ; void *baz(); ; void *foo(int a); ; ; void *bar() { ; foo(0); ; return baz(); ; } ; ; void *foo(int a) { ; if (a) ; bar(); ; return malloc(4); ; } define ptr @bar() nounwind uwtable { ; TUNIT: Function Attrs: nounwind uwtable ; TUNIT-LABEL: define {{[^@]+}}@bar ; TUNIT-SAME: () #[[ATTR1:[0-9]+]] { ; TUNIT-NEXT: [[TMP1:%.*]] = tail call ptr (...) @baz() #[[ATTR2:[0-9]+]] ; TUNIT-NEXT: ret ptr [[TMP1]] ; ; CGSCC: Function Attrs: nounwind uwtable ; CGSCC-LABEL: define {{[^@]+}}@bar ; CGSCC-SAME: () #[[ATTR1:[0-9]+]] { ; CGSCC-NEXT: [[TMP1:%.*]] = tail call ptr (...) @baz() #[[ATTR3:[0-9]+]] ; CGSCC-NEXT: ret ptr [[TMP1]] ; %1 = tail call ptr (...) @baz() ret ptr %1 } define ptr @foo1(i32 %0) nounwind uwtable { ; TUNIT: Function Attrs: nounwind uwtable ; TUNIT-LABEL: define {{[^@]+}}@foo1 ; TUNIT-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] { ; TUNIT-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 ; TUNIT-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]] ; TUNIT: 3: ; TUNIT-NEXT: [[TMP4:%.*]] = tail call ptr (...) @baz() #[[ATTR2]] ; TUNIT-NEXT: br label [[TMP5]] ; TUNIT: 5: ; TUNIT-NEXT: [[TMP6:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; TUNIT-NEXT: ret ptr [[TMP6]] ; ; CGSCC: Function Attrs: nounwind uwtable ; CGSCC-LABEL: define {{[^@]+}}@foo1 ; CGSCC-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] { ; CGSCC-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 ; CGSCC-NEXT: br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]] ; CGSCC: 3: ; CGSCC-NEXT: [[TMP4:%.*]] = tail call ptr (...) @baz() #[[ATTR3]] ; CGSCC-NEXT: br label [[TMP5]] ; CGSCC: 5: ; CGSCC-NEXT: [[TMP6:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CGSCC-NEXT: ret ptr [[TMP6]] ; %2 = icmp eq i32 %0, 0 br i1 %2, label %5, label %3 3: ; preds = %1 %4 = tail call ptr (...) @baz() br label %5 5: ; preds = %1, %3 %6 = tail call noalias ptr @malloc(i64 4) ret ptr %6 } declare ptr @baz(...) nounwind uwtable ; TEST 5 ; Returning global pointer. Should not be noalias. define ptr @getter() { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@getter ; CHECK-SAME: () #[[ATTR0]] { ; CHECK-NEXT: ret ptr @G ; ret ptr @G } ; Returning global pointer. Should not be noalias. define ptr @calle1(){ ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define {{[^@]+}}@calle1 ; TUNIT-SAME: () #[[ATTR0]] { ; TUNIT-NEXT: ret ptr @G ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define {{[^@]+}}@calle1 ; CGSCC-SAME: () #[[ATTR2:[0-9]+]] { ; CGSCC-NEXT: [[TMP1:%.*]] = call noundef nonnull align 8 dereferenceable(8) ptr @getter() #[[ATTR12:[0-9]+]] ; CGSCC-NEXT: ret ptr [[TMP1]] ; %1 = call ptr @getter() ret ptr %1 } ; TEST 6 declare noalias ptr @strdup(ptr nocapture) nounwind define ptr @test6() nounwind uwtable ssp { ; TUNIT: Function Attrs: nounwind ssp uwtable ; TUNIT-LABEL: define {{[^@]+}}@test6 ; TUNIT-SAME: () #[[ATTR3:[0-9]+]] { ; TUNIT-NEXT: [[X:%.*]] = alloca [2 x i8], align 1 ; TUNIT-NEXT: store i8 97, ptr [[X]], align 1 ; TUNIT-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8], ptr [[X]], i64 0, i64 1 ; TUNIT-NEXT: store i8 0, ptr [[ARRAYIDX1]], align 1 ; TUNIT-NEXT: [[CALL:%.*]] = call noalias ptr @strdup(ptr noalias nocapture noundef nonnull dereferenceable(2) [[X]]) #[[ATTR2]] ; TUNIT-NEXT: ret ptr [[CALL]] ; ; CGSCC: Function Attrs: nounwind ssp uwtable ; CGSCC-LABEL: define {{[^@]+}}@test6 ; CGSCC-SAME: () #[[ATTR4:[0-9]+]] { ; CGSCC-NEXT: [[X:%.*]] = alloca [2 x i8], align 1 ; CGSCC-NEXT: store i8 97, ptr [[X]], align 1 ; CGSCC-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8], ptr [[X]], i64 0, i64 1 ; CGSCC-NEXT: store i8 0, ptr [[ARRAYIDX1]], align 1 ; CGSCC-NEXT: [[CALL:%.*]] = call noalias ptr @strdup(ptr noalias nocapture noundef nonnull dereferenceable(2) [[X]]) #[[ATTR3]] ; CGSCC-NEXT: ret ptr [[CALL]] ; %x = alloca [2 x i8], align 1 store i8 97, ptr %x, align 1 %arrayidx1 = getelementptr inbounds [2 x i8], ptr %x, i64 0, i64 1 store i8 0, ptr %arrayidx1, align 1 %call = call noalias ptr @strdup(ptr %x) nounwind ret ptr %call } ; TEST 7 define ptr @test7() nounwind { ; TUNIT: Function Attrs: nounwind ; TUNIT-LABEL: define {{[^@]+}}@test7 ; TUNIT-SAME: () #[[ATTR2]] { ; TUNIT-NEXT: entry: ; TUNIT-NEXT: [[A:%.*]] = call noalias ptr @malloc(i64 noundef 4) #[[ATTR2]] ; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[A]], null ; TUNIT-NEXT: br i1 [[TOBOOL]], label [[RETURN:%.*]], label [[IF_END:%.*]] ; TUNIT: if.end: ; TUNIT-NEXT: store i8 7, ptr [[A]], align 1 ; TUNIT-NEXT: br label [[RETURN]] ; TUNIT: return: ; TUNIT-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[A]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ] ; TUNIT-NEXT: ret ptr [[RETVAL_0]] ; ; CGSCC: Function Attrs: nounwind ; CGSCC-LABEL: define {{[^@]+}}@test7 ; CGSCC-SAME: () #[[ATTR3]] { ; CGSCC-NEXT: entry: ; CGSCC-NEXT: [[A:%.*]] = call noalias ptr @malloc(i64 noundef 4) #[[ATTR3]] ; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq ptr [[A]], null ; CGSCC-NEXT: br i1 [[TOBOOL]], label [[RETURN:%.*]], label [[IF_END:%.*]] ; CGSCC: if.end: ; CGSCC-NEXT: store i8 7, ptr [[A]], align 1 ; CGSCC-NEXT: br label [[RETURN]] ; CGSCC: return: ; CGSCC-NEXT: [[RETVAL_0:%.*]] = phi ptr [ [[A]], [[IF_END]] ], [ null, [[ENTRY:%.*]] ] ; CGSCC-NEXT: ret ptr [[RETVAL_0]] ; entry: %A = call noalias ptr @malloc(i64 4) nounwind %tobool = icmp eq ptr %A, null br i1 %tobool, label %return, label %if.end if.end: store i8 7, ptr %A br label %return return: %retval.0 = phi ptr [ %A, %if.end ], [ null, %entry ] ret ptr %retval.0 } ; TEST 8 define ptr @test8(ptr %0) nounwind uwtable { ; CHECK: Function Attrs: nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@test8 ; CHECK-SAME: (ptr [[TMP0:%.*]]) #[[ATTR1:[0-9]+]] { ; CHECK-NEXT: [[TMP2:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne ptr [[TMP0]], null ; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] ; CHECK: 4: ; CHECK-NEXT: store i8 10, ptr [[TMP2]], align 1 ; CHECK-NEXT: br label [[TMP5]] ; CHECK: 5: ; CHECK-NEXT: ret ptr [[TMP2]] ; %2 = tail call noalias ptr @malloc(i64 4) %3 = icmp ne ptr %0, null br i1 %3, label %4, label %5 4: ; preds = %1 store i8 10, ptr %2 br label %5 5: ; preds = %1, %4 ret ptr %2 } ; TEST 9 ; Simple Argument Test declare void @use_i8(ptr nocapture) define internal void @test9a(ptr %a, ptr %b) { ; TUNIT: Function Attrs: memory(readwrite, argmem: none) ; TUNIT-LABEL: define {{[^@]+}}@test9a ; TUNIT-SAME: () #[[ATTR4:[0-9]+]] { ; TUNIT-NEXT: call void @use_i8(ptr noundef align 4294967296 null) ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: memory(readwrite, argmem: none) ; CGSCC-LABEL: define {{[^@]+}}@test9a ; CGSCC-SAME: () #[[ATTR5:[0-9]+]] { ; CGSCC-NEXT: call void @use_i8(ptr noundef align 4294967296 null) ; CGSCC-NEXT: ret void ; call void @use_i8(ptr null) ret void } define internal void @test9b(ptr %a, ptr %b) { ; FIXME: %b should be noalias ; CHECK-LABEL: define {{[^@]+}}@test9b ; CHECK-SAME: (ptr noalias nocapture [[A:%.*]], ptr nocapture [[B:%.*]]) { ; CHECK-NEXT: call void @use_i8(ptr noalias nocapture [[A]]) ; CHECK-NEXT: call void @use_i8(ptr nocapture [[B]]) ; CHECK-NEXT: ret void ; call void @use_i8(ptr %a) call void @use_i8(ptr %b) ret void } define internal void @test9c(ptr %a, ptr %b, ptr %c) { ; CHECK-LABEL: define {{[^@]+}}@test9c ; CHECK-SAME: (ptr noalias nocapture [[A:%.*]], ptr nocapture [[B:%.*]], ptr nocapture [[C:%.*]]) { ; CHECK-NEXT: call void @use_i8(ptr noalias nocapture [[A]]) ; CHECK-NEXT: call void @use_i8(ptr nocapture [[B]]) ; CHECK-NEXT: call void @use_i8(ptr nocapture [[C]]) ; CHECK-NEXT: ret void ; call void @use_i8(ptr %a) call void @use_i8(ptr %b) call void @use_i8(ptr %c) ret void } define void @test9_helper(ptr %a, ptr %b) { ; CHECK-LABEL: define {{[^@]+}}@test9_helper ; CHECK-SAME: (ptr nocapture [[A:%.*]], ptr nocapture [[B:%.*]]) { ; CHECK-NEXT: tail call void @test9a() ; CHECK-NEXT: tail call void @test9a() ; CHECK-NEXT: tail call void @test9b(ptr noalias nocapture [[A]], ptr nocapture [[B]]) ; CHECK-NEXT: tail call void @test9b(ptr noalias nocapture [[B]], ptr noalias nocapture [[A]]) ; CHECK-NEXT: tail call void @test9c(ptr noalias nocapture [[A]], ptr nocapture [[B]], ptr nocapture [[B]]) ; CHECK-NEXT: tail call void @test9c(ptr noalias nocapture [[B]], ptr noalias nocapture [[A]], ptr noalias nocapture [[A]]) ; CHECK-NEXT: ret void ; tail call void @test9a(ptr noalias %a, ptr %b) tail call void @test9a(ptr noalias %b, ptr noalias %a) tail call void @test9b(ptr noalias %a, ptr %b) tail call void @test9b(ptr noalias %b, ptr noalias %a) tail call void @test9c(ptr noalias %a, ptr %b, ptr %b) tail call void @test9c(ptr noalias %b, ptr noalias %a, ptr noalias %a) ret void } ; TEST 10 ; Simple CallSite Test declare void @test10_helper_1(ptr %a) define void @test10_helper_2(ptr noalias %a) { ; CHECK-LABEL: define {{[^@]+}}@test10_helper_2 ; CHECK-SAME: (ptr noalias [[A:%.*]]) { ; CHECK-NEXT: tail call void @test10_helper_1(ptr [[A]]) ; CHECK-NEXT: ret void ; tail call void @test10_helper_1(ptr %a) ret void } define void @test10(ptr noalias %a) { ; CHECK-LABEL: define {{[^@]+}}@test10 ; CHECK-SAME: (ptr noalias [[A:%.*]]) { ; CHECK-NEXT: tail call void @test10_helper_1(ptr [[A]]) ; CHECK-NEXT: tail call void @test10_helper_2(ptr [[A]]) ; CHECK-NEXT: ret void ; ; FIXME: missing noalias tail call void @test10_helper_1(ptr %a) tail call void @test10_helper_2(ptr %a) ret void } ; TEST 11 ; CallSite Test declare void @test11_helper(ptr %a, ptr %b) define void @test11(ptr noalias %a) { ; CHECK-LABEL: define {{[^@]+}}@test11 ; CHECK-SAME: (ptr noalias [[A:%.*]]) { ; CHECK-NEXT: tail call void @test11_helper(ptr [[A]], ptr [[A]]) ; CHECK-NEXT: ret void ; tail call void @test11_helper(ptr %a, ptr %a) ret void } ; TEST 12 ; CallSite Argument declare void @use_nocapture(ptr nocapture) declare void @use(ptr) define void @test12_1() { ; CHECK-LABEL: define {{[^@]+}}@test12_1() { ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 4 ; CHECK-NEXT: [[B:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: tail call void @use_nocapture(ptr noalias nocapture noundef nonnull align 4 dereferenceable(1) [[A]]) ; CHECK-NEXT: tail call void @use_nocapture(ptr noalias nocapture noundef nonnull align 4 dereferenceable(1) [[A]]) ; CHECK-NEXT: tail call void @use_nocapture(ptr noalias nocapture [[B]]) ; CHECK-NEXT: tail call void @use_nocapture(ptr noalias nocapture [[B]]) ; CHECK-NEXT: ret void ; %A = alloca i8, align 4 %B = tail call noalias ptr @malloc(i64 4) tail call void @use_nocapture(ptr %A) tail call void @use_nocapture(ptr %A) tail call void @use_nocapture(ptr %B) tail call void @use_nocapture(ptr %B) ret void } define void @test12_2(){ ; CHECK-LABEL: define {{[^@]+}}@test12_2() { ; CHECK-NEXT: [[A:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: tail call void @use_nocapture(ptr nocapture [[A]]) ; CHECK-NEXT: tail call void @use_nocapture(ptr nocapture [[A]]) ; CHECK-NEXT: tail call void @use(ptr [[A]]) ; CHECK-NEXT: tail call void @use_nocapture(ptr nocapture [[A]]) ; CHECK-NEXT: ret void ; ; FIXME: This should be @use_nocapture(ptr noalias [[A]]) ; FIXME: This should be @use_nocapture(ptr noalias nocapture [[A]]) %A = tail call noalias ptr @malloc(i64 4) tail call void @use_nocapture(ptr %A) tail call void @use_nocapture(ptr %A) tail call void @use(ptr %A) tail call void @use_nocapture(ptr %A) ret void } declare void @two_args(ptr nocapture , ptr nocapture) define void @test12_3(){ ; CHECK-LABEL: define {{[^@]+}}@test12_3() { ; CHECK-NEXT: [[A:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: tail call void @two_args(ptr nocapture [[A]], ptr nocapture [[A]]) ; CHECK-NEXT: ret void ; %A = tail call noalias ptr @malloc(i64 4) tail call void @two_args(ptr %A, ptr %A) ret void } define void @test12_4(){ ; CHECK-LABEL: define {{[^@]+}}@test12_4() { ; CHECK-NEXT: [[A:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: [[B:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: [[A_1:%.*]] = getelementptr i8, ptr [[A]], i64 1 ; CHECK-NEXT: tail call void @two_args(ptr noalias nocapture [[A]], ptr noalias nocapture [[B]]) ; CHECK-NEXT: tail call void @two_args(ptr nocapture [[A]], ptr nocapture [[A]]) ; CHECK-NEXT: tail call void @two_args(ptr nocapture [[A]], ptr nocapture [[A_1]]) ; CHECK-NEXT: tail call void @two_args(ptr noalias nocapture [[A]], ptr noalias nocapture [[B]]) ; CHECK-NEXT: ret void ; %A = tail call noalias ptr @malloc(i64 4) %B = tail call noalias ptr @malloc(i64 4) %A_1 = getelementptr i8, ptr %A, i64 1 tail call void @two_args(ptr %A, ptr %B) tail call void @two_args(ptr %A, ptr %A) tail call void @two_args(ptr %A, ptr %A_1) ; FIXME: This should be @two_args(ptr noalias nocapture %A, ptr noalias nocapture %B) tail call void @two_args(ptr %A, ptr %B) ret void } ; TEST 13 define void @use_i8_internal(ptr %a) { ; CHECK-LABEL: define {{[^@]+}}@use_i8_internal ; CHECK-SAME: (ptr nocapture [[A:%.*]]) { ; CHECK-NEXT: call void @use_i8(ptr nocapture [[A]]) ; CHECK-NEXT: ret void ; call void @use_i8(ptr %a) ret void } define void @test13_use_noalias(){ ; CHECK-LABEL: define {{[^@]+}}@test13_use_noalias() { ; CHECK-NEXT: [[M1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: call void @use_i8_internal(ptr noalias nocapture [[M1]]) ; CHECK-NEXT: ret void ; ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test13_use_noalias() ; IS__CGSCC_OPM-NEXT: [[M1:%.*]] = tail call noalias ptr @malloc(i64 4) ; IS__CGSCC_OPM-NEXT: call void @use_i8_internal(ptr noalias [[M1]]) ; IS__CGSCC_OPM-NEXT: ret void %m1 = tail call noalias ptr @malloc(i64 4) call void @use_i8_internal(ptr %m1) ret void } define void @test13_use_alias(){ ; CHECK-LABEL: define {{[^@]+}}@test13_use_alias() { ; CHECK-NEXT: [[M1:%.*]] = tail call noalias ptr @malloc(i64 noundef 4) ; CHECK-NEXT: call void @use_i8_internal(ptr noalias nocapture [[M1]]) ; CHECK-NEXT: call void @use_i8_internal(ptr noalias nocapture [[M1]]) ; CHECK-NEXT: ret void ; %m1 = tail call noalias ptr @malloc(i64 4) call void @use_i8_internal(ptr %m1) call void @use_i8_internal(ptr %m1) ret void } ; TEST 14 i2p casts define internal i32 @p2i(ptr %arg) { ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CHECK-LABEL: define {{[^@]+}}@p2i ; CHECK-SAME: (ptr noalias nofree readnone [[ARG:%.*]]) #[[ATTR0]] { ; CHECK-NEXT: [[P2I:%.*]] = ptrtoint ptr [[ARG]] to i32 ; CHECK-NEXT: ret i32 [[P2I]] ; %p2i = ptrtoint ptr %arg to i32 ret i32 %p2i } define i32 @i2p(ptr %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(read) ; TUNIT-LABEL: define {{[^@]+}}@i2p ; TUNIT-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR5:[0-9]+]] { ; TUNIT-NEXT: [[C:%.*]] = call i32 @p2i(ptr noalias nofree readnone [[ARG]]) #[[ATTR11:[0-9]+]] ; TUNIT-NEXT: [[I2P:%.*]] = inttoptr i32 [[C]] to ptr ; TUNIT-NEXT: [[CALL:%.*]] = call i32 @ret(ptr nocapture nofree noundef readonly align 4 [[I2P]]) #[[ATTR12:[0-9]+]] ; TUNIT-NEXT: ret i32 [[CALL]] ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read) ; CGSCC-LABEL: define {{[^@]+}}@i2p ; CGSCC-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR6:[0-9]+]] { ; CGSCC-NEXT: [[C:%.*]] = call i32 @p2i(ptr noalias nofree readnone [[ARG]]) #[[ATTR12]] ; CGSCC-NEXT: [[I2P:%.*]] = inttoptr i32 [[C]] to ptr ; CGSCC-NEXT: [[CALL:%.*]] = call i32 @ret(ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[I2P]]) #[[ATTR13:[0-9]+]] ; CGSCC-NEXT: ret i32 [[CALL]] ; %c = call i32 @p2i(ptr %arg) %i2p = inttoptr i32 %c to ptr %call = call i32 @ret(ptr %i2p) ret i32 %call } define internal i32 @ret(ptr %arg) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) ; TUNIT-LABEL: define {{[^@]+}}@ret ; TUNIT-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR6:[0-9]+]] { ; TUNIT-NEXT: [[L:%.*]] = load i32, ptr [[ARG]], align 4 ; TUNIT-NEXT: ret i32 [[L]] ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) ; CGSCC-LABEL: define {{[^@]+}}@ret ; CGSCC-SAME: (ptr nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR7:[0-9]+]] { ; CGSCC-NEXT: [[L:%.*]] = load i32, ptr [[ARG]], align 4 ; CGSCC-NEXT: ret i32 [[L]] ; %l = load i32, ptr %arg ret i32 %l } ; Test to propagate noalias where value is assumed to be no-capture in all the ; uses possibly executed before this callsite. ; IR referred from musl/src/strtod.c file %struct._IO_FILE = type { i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i32, ptr, ptr, i32, i32, i32, i16, i8, i8, i32, i32, ptr, i64, ptr, ptr, ptr, [4 x i8], i64, i64, ptr, ptr, ptr, [4 x i8] } %struct.__locale_struct = type { [6 x ptr] } %struct.__locale_map = type opaque ; Function Attrs: nounwind optsize define internal fastcc double @strtox(ptr %s, ptr %p, i32 %prec) unnamed_addr { ; TUNIT-LABEL: define {{[^@]+}}@strtox ; TUNIT-SAME: (ptr [[S:%.*]]) unnamed_addr { ; TUNIT-NEXT: entry: ; TUNIT-NEXT: [[F:%.*]] = alloca [[STRUCT__IO_FILE:%.*]], align 8 ; TUNIT-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 144, ptr nocapture nofree noundef nonnull align 8 dereferenceable(240) [[F]]) #[[ATTR13:[0-9]+]] ; TUNIT-NEXT: [[CALL:%.*]] = call i32 @sh_fromstring(ptr noundef nonnull align 8 dereferenceable(240) [[F]], ptr [[S]]) ; TUNIT-NEXT: call void @__shlim(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i64 noundef 0) ; TUNIT-NEXT: [[CALL1:%.*]] = call double @__floatscan(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i32 noundef 1, i32 noundef 1) ; TUNIT-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 144, ptr nocapture nofree noundef nonnull align 8 dereferenceable(240) [[F]]) ; TUNIT-NEXT: ret double [[CALL1]] ; ; CGSCC-LABEL: define {{[^@]+}}@strtox ; CGSCC-SAME: (ptr [[S:%.*]]) unnamed_addr { ; CGSCC-NEXT: entry: ; CGSCC-NEXT: [[F:%.*]] = alloca [[STRUCT__IO_FILE:%.*]], align 8 ; CGSCC-NEXT: call void @llvm.lifetime.start.p0(i64 noundef 144, ptr nocapture nofree noundef nonnull align 8 dereferenceable(240) [[F]]) #[[ATTR14:[0-9]+]] ; CGSCC-NEXT: [[CALL:%.*]] = call i32 @sh_fromstring(ptr noundef nonnull align 8 dereferenceable(240) [[F]], ptr [[S]]) ; CGSCC-NEXT: call void @__shlim(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i64 noundef 0) ; CGSCC-NEXT: [[CALL1:%.*]] = call double @__floatscan(ptr noundef nonnull align 8 dereferenceable(240) [[F]], i32 noundef 1, i32 noundef 1) ; CGSCC-NEXT: call void @llvm.lifetime.end.p0(i64 noundef 144, ptr nocapture nofree noundef nonnull align 8 dereferenceable(240) [[F]]) ; CGSCC-NEXT: ret double [[CALL1]] ; entry: %f = alloca %struct._IO_FILE, align 8 call void @llvm.lifetime.start.p0(i64 144, ptr nonnull %f) %call = call i32 @sh_fromstring(ptr nonnull %f, ptr %s) call void @__shlim(ptr nonnull %f, i64 0) %call1 = call double @__floatscan(ptr nonnull %f, i32 %prec, i32 1) call void @llvm.lifetime.end.p0(i64 144, ptr nonnull %f) ret double %call1 } ; Function Attrs: nounwind optsize define dso_local double @strtod(ptr noalias %s, ptr noalias %p) { ; CHECK-LABEL: define {{[^@]+}}@strtod ; CHECK-SAME: (ptr noalias [[S:%.*]], ptr noalias nocapture nofree readnone [[P:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CALL:%.*]] = tail call fastcc double @strtox(ptr [[S]]) ; CHECK-NEXT: ret double [[CALL]] ; entry: %call = tail call fastcc double @strtox(ptr %s, ptr %p, i32 1) ret double %call } ; Function Attrs: argmemonly nounwind willreturn declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) ; Function Attrs: optsize declare dso_local i32 @sh_fromstring(...) local_unnamed_addr ; Function Attrs: optsize declare dso_local void @__shlim(ptr, i64) local_unnamed_addr ; Function Attrs: optsize declare dso_local double @__floatscan(ptr, i32, i32) local_unnamed_addr ; Function Attrs: argmemonly nounwind willreturn declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) ; Test 15 ; propagate noalias to some callsite arguments that there is no possibly reachable capture before it @alias_of_p = external global ptr define void @make_alias(ptr %p) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; TUNIT-LABEL: define {{[^@]+}}@make_alias ; TUNIT-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR8:[0-9]+]] { ; TUNIT-NEXT: store ptr [[P]], ptr @alias_of_p, align 8 ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; CGSCC-LABEL: define {{[^@]+}}@make_alias ; CGSCC-SAME: (ptr nofree writeonly [[P:%.*]]) #[[ATTR9:[0-9]+]] { ; CGSCC-NEXT: store ptr [[P]], ptr @alias_of_p, align 8 ; CGSCC-NEXT: ret void ; store ptr %p, ptr @alias_of_p ret void } define void @only_store(ptr %p) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) ; TUNIT-LABEL: define {{[^@]+}}@only_store ; TUNIT-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR9:[0-9]+]] { ; TUNIT-NEXT: store i32 0, ptr [[P]], align 4 ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) ; CGSCC-LABEL: define {{[^@]+}}@only_store ; CGSCC-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR10:[0-9]+]] { ; CGSCC-NEXT: store i32 0, ptr [[P]], align 4 ; CGSCC-NEXT: ret void ; store i32 0, ptr %p ret void } define void @test15_caller(ptr noalias %p, i32 %c) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; TUNIT-LABEL: define {{[^@]+}}@test15_caller ; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 ; TUNIT-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; TUNIT: if.then: ; TUNIT-NEXT: tail call void @only_store(ptr noalias nocapture nofree noundef writeonly align 4 [[P]]) #[[ATTR14:[0-9]+]] ; TUNIT-NEXT: br label [[IF_END]] ; TUNIT: if.end: ; TUNIT-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR14]] ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) ; CGSCC-LABEL: define {{[^@]+}}@test15_caller ; CGSCC-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11:[0-9]+]] { ; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 ; CGSCC-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; CGSCC: if.then: ; CGSCC-NEXT: tail call void @only_store(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15:[0-9]+]] ; CGSCC-NEXT: br label [[IF_END]] ; CGSCC: if.end: ; CGSCC-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR15]] ; CGSCC-NEXT: ret void ; %tobool = icmp eq i32 %c, 0 br i1 %tobool, label %if.end, label %if.then if.then: tail call void @only_store(ptr %p) br label %if.end if.end: tail call void @make_alias(ptr %p) ret void } ; Test 16 ; ; __attribute__((noinline)) static void test16_sub(int * restrict p, int c1, int c2) { ; if (c1) { ; only_store(p); ; make_alias(p); ; } ; if (!c2) { ; only_store(p); ; } ; } ; void test16_caller(int * restrict p, int c) { ; test16_sub(p, c, c); ; } ; ; FIXME: this should be tail @only_store(ptr noalias %p) ; when test16_caller is called, c1 always equals to c2. (Note that linkage is internal) ; Therefore, only one of the two conditions of if statementes will be fulfilled. define internal void @test16_sub(ptr noalias %p, i32 %c1, i32 %c2) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; TUNIT-LABEL: define {{[^@]+}}@test16_sub ; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C1:%.*]], i32 [[C2:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C1]], 0 ; TUNIT-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; TUNIT: if.then: ; TUNIT-NEXT: tail call void @only_store(ptr nocapture nofree noundef writeonly align 4 [[P]]) #[[ATTR14]] ; TUNIT-NEXT: tail call void @make_alias(ptr nofree writeonly align 4 [[P]]) #[[ATTR14]] ; TUNIT-NEXT: br label [[IF_END]] ; TUNIT: if.end: ; TUNIT-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C2]], 0 ; TUNIT-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]] ; TUNIT: if.then2: ; TUNIT-NEXT: tail call void @only_store(ptr nocapture nofree noundef writeonly align 4 [[P]]) #[[ATTR14]] ; TUNIT-NEXT: br label [[IF_END3]] ; TUNIT: if.end3: ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) ; CGSCC-LABEL: define {{[^@]+}}@test16_sub ; CGSCC-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C1:%.*]], i32 [[C2:%.*]]) #[[ATTR11]] { ; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C1]], 0 ; CGSCC-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; CGSCC: if.then: ; CGSCC-NEXT: tail call void @only_store(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]] ; CGSCC-NEXT: tail call void @make_alias(ptr nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]] ; CGSCC-NEXT: br label [[IF_END]] ; CGSCC: if.end: ; CGSCC-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C2]], 0 ; CGSCC-NEXT: br i1 [[TOBOOL1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]] ; CGSCC: if.then2: ; CGSCC-NEXT: tail call void @only_store(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]] ; CGSCC-NEXT: br label [[IF_END3]] ; CGSCC: if.end3: ; CGSCC-NEXT: ret void ; %tobool = icmp eq i32 %c1, 0 br i1 %tobool, label %if.end, label %if.then if.then: tail call void @only_store(ptr %p) tail call void @make_alias(ptr %p) br label %if.end if.end: %tobool1 = icmp eq i32 %c2, 0 br i1 %tobool1, label %if.then2, label %if.end3 if.then2: tail call void @only_store(ptr %p) br label %if.end3 if.end3: ret void } define void @test16_caller(ptr %p, i32 %c) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; TUNIT-LABEL: define {{[^@]+}}@test16_caller ; TUNIT-SAME: (ptr nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: tail call void @test16_sub(ptr nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR14]] ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) ; CGSCC-LABEL: define {{[^@]+}}@test16_caller ; CGSCC-SAME: (ptr nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11]] { ; CGSCC-NEXT: tail call void @test16_sub(ptr nofree writeonly [[P]], i32 [[C]], i32 [[C]]) #[[ATTR15]] ; CGSCC-NEXT: ret void ; tail call void @test16_sub(ptr %p, i32 %c, i32 %c) ret void } ; test 17 ; ; only_store is not called after make_alias is called. ; ; void test17_caller(int* p, int c) { ; if(c) { ; make_alias(p); ; if(0 == 0) { ; goto l3; ; } else { ; goto l2; ; } ; } ; l2: ; only_store(p); ; l3: ; return; ; } define void @test17_caller(ptr noalias %p, i32 %c) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; TUNIT-LABEL: define {{[^@]+}}@test17_caller ; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: entry: ; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 ; TUNIT-NEXT: br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]] ; TUNIT: l1: ; TUNIT-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR14]] ; TUNIT-NEXT: br label [[L3:%.*]] ; TUNIT: l2: ; TUNIT-NEXT: tail call void @only_store(ptr noalias nocapture nofree noundef writeonly align 4 [[P]]) #[[ATTR14]] ; TUNIT-NEXT: br label [[L3]] ; TUNIT: l3: ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) ; CGSCC-LABEL: define {{[^@]+}}@test17_caller ; CGSCC-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11]] { ; CGSCC-NEXT: entry: ; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 ; CGSCC-NEXT: br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]] ; CGSCC: l1: ; CGSCC-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR15]] ; CGSCC-NEXT: br label [[L3:%.*]] ; CGSCC: l2: ; CGSCC-NEXT: tail call void @only_store(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]] ; CGSCC-NEXT: br label [[L3]] ; CGSCC: l3: ; CGSCC-NEXT: ret void ; entry: %tobool = icmp eq i32 %c, 0 br i1 %tobool, label %l1, label %l2 l1: tail call void @make_alias(ptr %p) %tobool2 = icmp eq i32 0, 0 br i1 %tobool2, label %l3, label %l2 l2: tail call void @only_store(ptr %p) br label %l3 l3: ret void } ; test 18 ; void test18_caller(int* p, int c) { ; if(c) { ; make_alias(p); ; noreturn(); ; } ; only_store(p); ; return; ; } define void @noreturn() { ; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; TUNIT-LABEL: define {{[^@]+}}@noreturn ; TUNIT-SAME: () #[[ATTR10:[0-9]+]] { ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define {{[^@]+}}@noreturn ; CGSCC-SAME: () #[[ATTR2]] { ; CGSCC-NEXT: ret void ; call void @noreturn() ret void } define void @test18_caller(ptr noalias %p, i32 %c) { ; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(write) ; TUNIT-LABEL: define {{[^@]+}}@test18_caller ; TUNIT-SAME: (ptr noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: entry: ; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 ; TUNIT-NEXT: br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]] ; TUNIT: l1: ; TUNIT-NEXT: tail call void @make_alias(ptr nofree writeonly [[P]]) #[[ATTR14]] ; TUNIT-NEXT: br label [[L2]] ; TUNIT: l2: ; TUNIT-NEXT: tail call void @only_store(ptr nocapture nofree noundef writeonly align 4 [[P]]) #[[ATTR14]] ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(write) ; CGSCC-LABEL: define {{[^@]+}}@test18_caller ; CGSCC-SAME: (ptr noalias nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]], i32 [[C:%.*]]) #[[ATTR11]] { ; CGSCC-NEXT: entry: ; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 ; CGSCC-NEXT: br i1 [[TOBOOL]], label [[L1:%.*]], label [[L2:%.*]] ; CGSCC: l1: ; CGSCC-NEXT: tail call void @make_alias(ptr nofree nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]] ; CGSCC-NEXT: br label [[L2]] ; CGSCC: l2: ; CGSCC-NEXT: tail call void @only_store(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[P]]) #[[ATTR15]] ; CGSCC-NEXT: ret void ; entry: %tobool = icmp eq i32 %c, 0 br i1 %tobool, label %l1, label %l2 l1: tail call void @make_alias(ptr %p) tail call void @noreturn() br label %l2 l2: tail call void @only_store(ptr %p) ret void } ;. ; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } ; TUNIT: attributes #[[ATTR1]] = { nounwind uwtable } ; TUNIT: attributes #[[ATTR2]] = { nounwind } ; TUNIT: attributes #[[ATTR3]] = { nounwind ssp uwtable } ; TUNIT: attributes #[[ATTR4]] = { memory(readwrite, argmem: none) } ; TUNIT: attributes #[[ATTR5]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(read) } ; TUNIT: attributes #[[ATTR6]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } ; TUNIT: attributes #[[ATTR7:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } ; TUNIT: attributes #[[ATTR8]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } ; TUNIT: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) } ; TUNIT: attributes #[[ATTR10]] = { mustprogress nofree nosync nounwind willreturn memory(none) } ; TUNIT: attributes #[[ATTR11]] = { nofree nosync nounwind willreturn memory(none) } ; TUNIT: attributes #[[ATTR12]] = { nofree nosync nounwind willreturn memory(read) } ; TUNIT: attributes #[[ATTR13]] = { nofree willreturn memory(readwrite) } ; TUNIT: attributes #[[ATTR14]] = { nofree nosync nounwind willreturn memory(write) } ;. ; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } ; CGSCC: attributes #[[ATTR1]] = { nounwind uwtable } ; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree nosync nounwind willreturn memory(none) } ; CGSCC: attributes #[[ATTR3]] = { nounwind } ; CGSCC: attributes #[[ATTR4]] = { nounwind ssp uwtable } ; CGSCC: attributes #[[ATTR5]] = { memory(readwrite, argmem: none) } ; CGSCC: attributes #[[ATTR6]] = { mustprogress nofree nosync nounwind willreturn memory(read) } ; CGSCC: attributes #[[ATTR7]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) } ; CGSCC: attributes #[[ATTR8:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } ; CGSCC: attributes #[[ATTR9]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(write) } ; CGSCC: attributes #[[ATTR10]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) } ; CGSCC: attributes #[[ATTR11]] = { mustprogress nofree nosync nounwind willreturn memory(write) } ; CGSCC: attributes #[[ATTR12]] = { nofree nosync willreturn } ; CGSCC: attributes #[[ATTR13]] = { nofree willreturn memory(read) } ; CGSCC: attributes #[[ATTR14]] = { nofree willreturn memory(readwrite) } ; CGSCC: attributes #[[ATTR15]] = { nofree nounwind willreturn memory(write) } ;.