From: Nikita Popov Date: Wed, 12 Oct 2022 14:59:42 +0000 (+0200) Subject: [FunctionAttrs] Regenerate test checks (NFC) X-Git-Tag: upstream/17.0.6~30827 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dbd29ed54b090546624b3215cbc58c92acdcc233;p=platform%2Fupstream%2Fllvm.git [FunctionAttrs] Regenerate test checks (NFC) --- diff --git a/llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll b/llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll index 1d75248..13d7682 100644 --- a/llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll +++ b/llvm/test/Transforms/FunctionAttrs/2008-09-03-Mutual.ll @@ -1,18 +1,24 @@ -; RUN: opt < %s -function-attrs -S | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes ; RUN: opt < %s -passes=function-attrs -S | FileCheck %s -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NEXT: define i32 @a define i32 @a() { - %tmp = call i32 @b( ) ; [#uses=1] - ret i32 %tmp +; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK-LABEL: define {{[^@]+}}@a +; CHECK-SAME: () #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: [[TMP:%.*]] = call i32 @b() +; CHECK-NEXT: ret i32 [[TMP]] +; + %tmp = call i32 @b() + ret i32 %tmp } -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NEXT: define i32 @b define i32 @b() { - %tmp = call i32 @a( ) ; [#uses=1] - ret i32 %tmp +; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK-LABEL: define {{[^@]+}}@b +; CHECK-SAME: () #[[ATTR0]] { +; CHECK-NEXT: [[TMP:%.*]] = call i32 @a() +; CHECK-NEXT: ret i32 [[TMP]] +; + %tmp = call i32 @a() + ret i32 %tmp } diff --git a/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll b/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll index 2c5758a..b8c0d6c 100644 --- a/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll +++ b/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadNone.ll @@ -1,32 +1,34 @@ -; RUN: opt < %s -function-attrs -S | FileCheck %s -; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes +; RUN: opt < %s -passes=function-attrs -S | FileCheck %s @x = global i32 0 -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NEXT: declare i32 @e declare i32 @e() readnone -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NEXT: define i32 @f define i32 @f() { - %tmp = call i32 @e( ) ; [#uses=1] - ret i32 %tmp +; CHECK: Function Attrs: nofree nosync readnone +; CHECK-LABEL: @f( +; CHECK-NEXT: [[TMP:%.*]] = call i32 @e() +; CHECK-NEXT: ret i32 [[TMP]] +; + %tmp = call i32 @e() + ret i32 %tmp } -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NEXT: define i32 @g define i32 @g() readonly { - ret i32 0 +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK-LABEL: @g( +; CHECK-NEXT: ret i32 0 +; + ret i32 0 } -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NEXT: define i32 @h define i32 @h() readnone { - %tmp = load i32, i32* @x ; [#uses=1] - ret i32 %tmp +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK-LABEL: @h( +; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* @x, align 4 +; CHECK-NEXT: ret i32 [[TMP]] +; + %tmp = load i32, i32* @x + ret i32 %tmp } diff --git a/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll b/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll index 9c773f8..e37667d 100644 --- a/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll +++ b/llvm/test/Transforms/FunctionAttrs/2008-09-03-ReadOnly.ll @@ -1,14 +1,16 @@ -; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes +; RUN: opt < %s -passes=function-attrs -S | FileCheck %s -; CHECK: define i32 @f() #0 define i32 @f() { +; CHECK: Function Attrs: nofree readonly +; CHECK-LABEL: @f( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP:%.*]] = call i32 @e() +; CHECK-NEXT: ret i32 [[TMP]] +; entry: %tmp = call i32 @e( ) ret i32 %tmp } -; CHECK: declare i32 @e() #1 declare i32 @e() readonly - -; CHECK: attributes #0 = { nofree readonly } -; CHECK: attributes #1 = { readonly } diff --git a/llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll b/llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll index ed4fdab..f6207fc 100644 --- a/llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll +++ b/llvm/test/Transforms/FunctionAttrs/2008-12-29-Constant.ll @@ -1,12 +1,14 @@ -; RUN: opt < %s -function-attrs -S | FileCheck %s -; RUN: opt < %s -aa-pipeline=basic-aa -passes=function-attrs -S | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes +; RUN: opt < %s -passes=function-attrs -S | FileCheck %s -@s = external constant i8 ; [#uses=1] +@s = external constant i8 -; CHECK: define i8 @f() #0 define i8 @f() { - %tmp = load i8, i8* @s ; [#uses=1] - ret i8 %tmp +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK-LABEL: @f( +; CHECK-NEXT: [[TMP:%.*]] = load i8, i8* @s, align 1 +; CHECK-NEXT: ret i8 [[TMP]] +; + %tmp = load i8, i8* @s + ret i8 %tmp } - -; CHECK: attributes #0 = { {{.*}} readnone diff --git a/llvm/test/Transforms/FunctionAttrs/atomic.ll b/llvm/test/Transforms/FunctionAttrs/atomic.ll index b90e09b..50d9263 100644 --- a/llvm/test/Transforms/FunctionAttrs/atomic.ll +++ b/llvm/test/Transforms/FunctionAttrs/atomic.ll @@ -1,10 +1,17 @@ -; RUN: opt -function-attrs -S < %s | FileCheck %s -; RUN: opt -aa-pipeline=basic-aa -passes=function-attrs -S < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes +; RUN: opt -passes=function-attrs -S < %s | FileCheck %s ; Atomic load/store to local doesn't affect whether a function is ; readnone/readonly. define i32 @test1(i32 %x) uwtable ssp { -; CHECK: define i32 @test1(i32 %x) #0 { +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone ssp willreturn uwtable +; CHECK-LABEL: @test1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store atomic i32 [[X:%.*]], i32* [[X_ADDR]] seq_cst, align 4 +; CHECK-NEXT: [[R:%.*]] = load atomic i32, i32* [[X_ADDR]] seq_cst, align 4 +; CHECK-NEXT: ret i32 [[R]] +; entry: %x.addr = alloca i32, align 4 store atomic i32 %x, i32* %x.addr seq_cst, align 4 @@ -14,11 +21,13 @@ entry: ; A function with an Acquire load is not readonly. define i32 @test2(i32* %x) uwtable ssp { -; CHECK: define i32 @test2(i32* nocapture readonly %x) #1 { +; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind ssp willreturn uwtable +; CHECK-LABEL: @test2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = load atomic i32, i32* [[X:%.*]] seq_cst, align 4 +; CHECK-NEXT: ret i32 [[R]] +; entry: %r = load atomic i32, i32* %x seq_cst, align 4 ret i32 %r } - -; CHECK: attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone ssp willreturn uwtable } -; CHECK: attributes #1 = { argmemonly mustprogress nofree norecurse nounwind ssp willreturn uwtable } diff --git a/llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll b/llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll index 4c33116..98a36ac 100644 --- a/llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll +++ b/llvm/test/Transforms/FunctionAttrs/int_sideeffect.ll @@ -1,29 +1,32 @@ -; RUN: opt -S < %s -function-attrs | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes ; RUN: opt -S < %s -passes=function-attrs | FileCheck %s -; CHECK: Function Attrs -; CHECK-SAME: inaccessiblememonly -; CHECK-NEXT: declare void @llvm.sideeffect() declare void @llvm.sideeffect() ; Don't add readnone or similar attributes when an @llvm.sideeffect() intrinsic ; is present. -; CHECK: Function Attrs -; CHECK-NOT: readnone -; CHECK: define void @test() define void @test() { - call void @llvm.sideeffect() - ret void +; CHECK: Function Attrs: inaccessiblememonly mustprogress nofree nosync nounwind willreturn +; CHECK-LABEL: @test( +; CHECK-NEXT: call void @llvm.sideeffect() +; CHECK-NEXT: ret void +; + call void @llvm.sideeffect() + ret void } -; CHECK: Function Attrs -; CHECK-NOT: readnone -; CHECK: define void @loop() define void @loop() { - br label %loop +; CHECK: Function Attrs: inaccessiblememonly nofree noreturn nosync nounwind +; CHECK-LABEL: @loop( +; CHECK-NEXT: br label [[LOOP:%.*]] +; CHECK: loop: +; CHECK-NEXT: call void @llvm.sideeffect() +; CHECK-NEXT: br label [[LOOP]] +; + br label %loop loop: - call void @llvm.sideeffect() - br label %loop + call void @llvm.sideeffect() + br label %loop } diff --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll index 8ea47cf..798378e 100644 --- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -1,121 +1,186 @@ -; RUN: opt < %s -function-attrs -S | FileCheck %s -; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs)' -S | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes +; RUN: opt < %s -passes=function-attrs -S | FileCheck %s @x = global i32 0 declare void @test1_1(i8* %x1_1, i8* nocapture readonly %y1_1, ...) -; CHECK: define void @test1_2(i8* %x1_2, i8* nocapture readonly %y1_2, i8* %z1_2) define void @test1_2(i8* %x1_2, i8* %y1_2, i8* %z1_2) { +; CHECK-LABEL: define {{[^@]+}}@test1_2 +; CHECK-SAME: (i8* [[X1_2:%.*]], i8* nocapture readonly [[Y1_2:%.*]], i8* [[Z1_2:%.*]]) { +; CHECK-NEXT: call void (i8*, i8*, ...) @test1_1(i8* [[X1_2]], i8* [[Y1_2]], i8* [[Z1_2]]) +; CHECK-NEXT: store i32 0, i32* @x, align 4 +; CHECK-NEXT: ret void +; call void (i8*, i8*, ...) @test1_1(i8* %x1_2, i8* %y1_2, i8* %z1_2) store i32 0, i32* @x ret void } -; CHECK: define i8* @test2(i8* readnone returned %p) define i8* @test2(i8* %p) { +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@test2 +; CHECK-SAME: (i8* readnone returned [[P:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: store i32 0, i32* @x, align 4 +; CHECK-NEXT: ret i8* [[P]] +; store i32 0, i32* @x ret i8* %p } -; CHECK: define i1 @test3(i8* readnone %p, i8* readnone %q) define i1 @test3(i8* %p, i8* %q) { +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK-LABEL: define {{[^@]+}}@test3 +; CHECK-SAME: (i8* readnone [[P:%.*]], i8* readnone [[Q:%.*]]) #[[ATTR1:[0-9]+]] { +; CHECK-NEXT: [[A:%.*]] = icmp ult i8* [[P]], [[Q]] +; CHECK-NEXT: ret i1 [[A]] +; %A = icmp ult i8* %p, %q ret i1 %A } declare void @test4_1(i8* nocapture) readonly -; CHECK: define void @test4_2(i8* nocapture readonly %p) define void @test4_2(i8* %p) { +; CHECK: Function Attrs: nofree readonly +; CHECK-LABEL: define {{[^@]+}}@test4_2 +; CHECK-SAME: (i8* nocapture readonly [[P:%.*]]) #[[ATTR3:[0-9]+]] { +; CHECK-NEXT: call void @test4_1(i8* [[P]]) +; CHECK-NEXT: ret void +; call void @test4_1(i8* %p) ret void } -; CHECK: define void @test5(i8** nocapture writeonly %p, i8* %q) ; Missed optz'n: we could make %q readnone, but don't break test6! define void @test5(i8** %p, i8* %q) { +; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@test5 +; CHECK-SAME: (i8** nocapture writeonly [[P:%.*]], i8* [[Q:%.*]]) #[[ATTR4:[0-9]+]] { +; CHECK-NEXT: store i8* [[Q]], i8** [[P]], align 8 +; CHECK-NEXT: ret void +; store i8* %q, i8** %p ret void } declare void @test6_1() -; CHECK: define void @test6_2(i8** nocapture writeonly %p, i8* %q) + ; This is not a missed optz'n. define void @test6_2(i8** %p, i8* %q) { +; CHECK-LABEL: define {{[^@]+}}@test6_2 +; CHECK-SAME: (i8** nocapture writeonly [[P:%.*]], i8* [[Q:%.*]]) { +; CHECK-NEXT: store i8* [[Q]], i8** [[P]], align 8 +; CHECK-NEXT: call void @test6_1() +; CHECK-NEXT: ret void +; store i8* %q, i8** %p call void @test6_1() ret void } -; CHECK: define void @test7_1(i32* nocapture inalloca(i32) %a) ; inalloca parameters are always considered written define void @test7_1(i32* inalloca(i32) %a) { +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK-LABEL: define {{[^@]+}}@test7_1 +; CHECK-SAME: (i32* nocapture inalloca(i32) [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: ret void +; ret void } -; CHECK: define void @test7_2(i32* nocapture preallocated(i32) %a) ; preallocated parameters are always considered written define void @test7_2(i32* preallocated(i32) %a) { +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK-LABEL: define {{[^@]+}}@test7_2 +; CHECK-SAME: (i32* nocapture preallocated(i32) [[A:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: ret void +; ret void } -; CHECK: define i32* @test8_1(i32* readnone returned %p) define i32* @test8_1(i32* %p) { +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn +; CHECK-LABEL: define {{[^@]+}}@test8_1 +; CHECK-SAME: (i32* readnone returned [[P:%.*]]) #[[ATTR1]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32* [[P]] +; entry: ret i32* %p } -; CHECK: define void @test8_2(i32* writeonly %p) define void @test8_2(i32* %p) { +; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@test8_2 +; CHECK-SAME: (i32* writeonly [[P:%.*]]) #[[ATTR4]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CALL:%.*]] = call i32* @test8_1(i32* [[P]]) +; CHECK-NEXT: store i32 10, i32* [[CALL]], align 4 +; CHECK-NEXT: ret void +; entry: %call = call i32* @test8_1(i32* %p) store i32 10, i32* %call, align 4 ret void } -; CHECK: declare void @llvm.masked.scatter declare void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*>, i32, <4 x i1>) -; CHECK-NOT: readnone -; CHECK-NOT: readonly -; CHECK: define void @test9 define void @test9(<4 x i32*> %ptrs, <4 x i32>%val) { +; CHECK: Function Attrs: mustprogress nofree nosync nounwind willreturn writeonly +; CHECK-LABEL: define {{[^@]+}}@test9 +; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) #[[ATTR6:[0-9]+]] { +; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 4, <4 x i1> ) +; CHECK-NEXT: ret void +; call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*> %ptrs, i32 4, <4 x i1>) ret void } -; CHECK: declare <4 x i32> @llvm.masked.gather declare <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>) -; CHECK: readonly -; CHECK: define <4 x i32> @test10 define <4 x i32> @test10(<4 x i32*> %ptrs) { +; CHECK: Function Attrs: mustprogress nofree nosync nounwind readonly willreturn +; CHECK-LABEL: define {{[^@]+}}@test10 +; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR8:[0-9]+]] { +; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 4, <4 x i1> , <4 x i32> undef) +; CHECK-NEXT: ret <4 x i32> [[RES]] +; %res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %ptrs, i32 4, <4 x i1>, <4 x i32>undef) ret <4 x i32> %res } -; CHECK: declare <4 x i32> @test11_1 declare <4 x i32> @test11_1(<4 x i32*>) argmemonly nounwind readonly -; CHECK: readonly -; CHECK-NOT: readnone -; CHECK: define <4 x i32> @test11_2 define <4 x i32> @test11_2(<4 x i32*> %ptrs) { +; CHECK: Function Attrs: argmemonly nofree nounwind readonly +; CHECK-LABEL: define {{[^@]+}}@test11_2 +; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR10:[0-9]+]] { +; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @test11_1(<4 x i32*> [[PTRS]]) +; CHECK-NEXT: ret <4 x i32> [[RES]] +; %res = call <4 x i32> @test11_1(<4 x i32*> %ptrs) ret <4 x i32> %res } declare <4 x i32> @test12_1(<4 x i32*>) argmemonly nounwind -; CHECK-NOT: readnone -; CHECK: define <4 x i32> @test12_2 define <4 x i32> @test12_2(<4 x i32*> %ptrs) { +; CHECK: Function Attrs: argmemonly nounwind +; CHECK-LABEL: define {{[^@]+}}@test12_2 +; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) #[[ATTR11:[0-9]+]] { +; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x i32*> [[PTRS]]) +; CHECK-NEXT: ret <4 x i32> [[RES]] +; %res = call <4 x i32> @test12_1(<4 x i32*> %ptrs) ret <4 x i32> %res } -; CHECK: define i32 @volatile_load( -; CHECK-NOT: readonly -; CHECK: ret define i32 @volatile_load(i32* %p) { +; CHECK: Function Attrs: argmemonly mustprogress nofree norecurse nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@volatile_load +; CHECK-SAME: (i32* [[P:%.*]]) #[[ATTR12:[0-9]+]] { +; CHECK-NEXT: [[LOAD:%.*]] = load volatile i32, i32* [[P]], align 4 +; CHECK-NEXT: ret i32 [[LOAD]] +; %load = load volatile i32, i32* %p ret i32 %load } @@ -127,11 +192,15 @@ declare void @escape_readonly_ptr(i8** %addr, i8* readonly %ptr) ; though the only direct use, in @escape_readnone_ptr/@escape_readonly_ptr, ; is marked as readnone/only. However, the functions can write the pointer into ; %addr, causing the store to write to %escaped_then_written. -; -; CHECK: define void @unsound_readnone(i8* nocapture readnone %ignored, i8* %escaped_then_written) -; CHECK: define void @unsound_readonly(i8* nocapture readnone %ignored, i8* %escaped_then_written) -; define void @unsound_readnone(i8* %ignored, i8* %escaped_then_written) { +; CHECK-LABEL: define {{[^@]+}}@unsound_readnone +; CHECK-SAME: (i8* nocapture readnone [[IGNORED:%.*]], i8* [[ESCAPED_THEN_WRITTEN:%.*]]) { +; CHECK-NEXT: [[ADDR:%.*]] = alloca i8*, align 8 +; CHECK-NEXT: call void @escape_readnone_ptr(i8** [[ADDR]], i8* [[ESCAPED_THEN_WRITTEN]]) +; CHECK-NEXT: [[ADDR_LD:%.*]] = load i8*, i8** [[ADDR]], align 8 +; CHECK-NEXT: store i8 0, i8* [[ADDR_LD]], align 1 +; CHECK-NEXT: ret void +; %addr = alloca i8* call void @escape_readnone_ptr(i8** %addr, i8* %escaped_then_written) %addr.ld = load i8*, i8** %addr @@ -140,6 +209,14 @@ define void @unsound_readnone(i8* %ignored, i8* %escaped_then_written) { } define void @unsound_readonly(i8* %ignored, i8* %escaped_then_written) { +; CHECK-LABEL: define {{[^@]+}}@unsound_readonly +; CHECK-SAME: (i8* nocapture readnone [[IGNORED:%.*]], i8* [[ESCAPED_THEN_WRITTEN:%.*]]) { +; CHECK-NEXT: [[ADDR:%.*]] = alloca i8*, align 8 +; CHECK-NEXT: call void @escape_readonly_ptr(i8** [[ADDR]], i8* [[ESCAPED_THEN_WRITTEN]]) +; CHECK-NEXT: [[ADDR_LD:%.*]] = load i8*, i8** [[ADDR]], align 8 +; CHECK-NEXT: store i8 0, i8* [[ADDR_LD]], align 1 +; CHECK-NEXT: ret void +; %addr = alloca i8* call void @escape_readonly_ptr(i8** %addr, i8* %escaped_then_written) %addr.ld = load i8*, i8** %addr @@ -147,41 +224,66 @@ define void @unsound_readonly(i8* %ignored, i8* %escaped_then_written) { ret void } - -; CHECK: define void @fptr_test1a(i8* nocapture readnone %p, void (i8*)* nocapture readonly %f) define void @fptr_test1a(i8* %p, void (i8*)* %f) { +; CHECK-LABEL: define {{[^@]+}}@fptr_test1a +; CHECK-SAME: (i8* nocapture readnone [[P:%.*]], void (i8*)* nocapture readonly [[F:%.*]]) { +; CHECK-NEXT: call void [[F]](i8* nocapture readnone [[P]]) +; CHECK-NEXT: ret void +; call void %f(i8* nocapture readnone %p) ret void } -; CHECK: define void @fptr_test1b(i8* %p, void (i8*)* nocapture readonly %f) +; Can't infer readnone here because call might capture %p define void @fptr_test1b(i8* %p, void (i8*)* %f) { - ; Can't infer readnone here because call might capture %p +; CHECK-LABEL: define {{[^@]+}}@fptr_test1b +; CHECK-SAME: (i8* [[P:%.*]], void (i8*)* nocapture readonly [[F:%.*]]) { +; CHECK-NEXT: call void [[F]](i8* readnone [[P]]) +; CHECK-NEXT: ret void +; call void %f(i8* readnone %p) ret void } -; CHECK: define void @fptr_test1c(i8* readnone %p, void (i8*)* nocapture readonly %f) define void @fptr_test1c(i8* %p, void (i8*)* %f) { +; CHECK: Function Attrs: nofree readonly +; CHECK-LABEL: define {{[^@]+}}@fptr_test1c +; CHECK-SAME: (i8* readnone [[P:%.*]], void (i8*)* nocapture readonly [[F:%.*]]) #[[ATTR3]] { +; CHECK-NEXT: call void [[F]](i8* readnone [[P]]) #[[ATTR2:[0-9]+]] +; CHECK-NEXT: ret void +; call void %f(i8* readnone %p) readonly ret void } -; CHECK: define void @fptr_test2a(i8* nocapture readonly %p, void (i8*)* nocapture readonly %f) define void @fptr_test2a(i8* %p, void (i8*)* %f) { +; CHECK-LABEL: define {{[^@]+}}@fptr_test2a +; CHECK-SAME: (i8* nocapture readonly [[P:%.*]], void (i8*)* nocapture readonly [[F:%.*]]) { +; CHECK-NEXT: call void [[F]](i8* nocapture readonly [[P]]) +; CHECK-NEXT: ret void +; call void %f(i8* nocapture readonly %p) ret void } -; CHECK: define void @fptr_test2b(i8* %p, void (i8*)* nocapture readonly %f) define void @fptr_test2b(i8* %p, void (i8*)* %f) { ; Can't infer readonly here because call might capture %p +; CHECK-LABEL: define {{[^@]+}}@fptr_test2b +; CHECK-SAME: (i8* [[P:%.*]], void (i8*)* nocapture readonly [[F:%.*]]) { +; CHECK-NEXT: call void [[F]](i8* readonly [[P]]) +; CHECK-NEXT: ret void +; call void %f(i8* readonly %p) ret void } -; CHECK: define void @fptr_test2c(i8* readonly %p, void (i8*)* nocapture readonly %f) define void @fptr_test2c(i8* %p, void (i8*)* %f) { +; CHECK: Function Attrs: nofree readonly +; CHECK-LABEL: define {{[^@]+}}@fptr_test2c +; CHECK-SAME: (i8* readonly [[P:%.*]], void (i8*)* nocapture readonly [[F:%.*]]) #[[ATTR3]] { +; CHECK-NEXT: call void [[F]](i8* readonly [[P]]) #[[ATTR2]] +; CHECK-NEXT: ret void +; call void %f(i8* readonly %p) readonly ret void }