forked from OSchip/llvm-project
[FunctionAttrs] Regenerate test checks (NFC)
This commit is contained in:
parent
cbae57c0e1
commit
dbd29ed54b
|
@ -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( ) ; <i32> [#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( ) ; <i32> [#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
|
||||
}
|
||||
|
|
|
@ -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( ) ; <i32> [#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 ; <i32> [#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
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 ; <i8*> [#uses=1]
|
||||
@s = external constant i8
|
||||
|
||||
; CHECK: define i8 @f() #0
|
||||
define i8 @f() {
|
||||
%tmp = load i8, i8* @s ; <i8> [#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
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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> <i1 true, i1 false, i1 true, i1 false>)
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*> %ptrs, i32 4, <4 x i1><i1 true, i1 false, i1 true, i1 false>)
|
||||
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> <i1 true, i1 false, i1 true, i1 false>, <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><i1 true, i1 false, i1 true, i1 false>, <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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue