258 lines
9.6 KiB
LLVM
258 lines
9.6 KiB
LLVM
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
|
||
|
; RUN: opt < %s -aa-pipeline=basic-aa -passes='cgscc(function-attrs),rpo-function-attrs' -S | FileCheck --check-prefixes=COMMON,FNATTRS %s
|
||
|
; RUN: opt -passes=attributor-light -S < %s | FileCheck --check-prefixes=COMMON,ATTRIBUTOR %s
|
||
|
|
||
|
|
||
|
define i32 @leaf() {
|
||
|
; COMMON: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
|
||
|
; COMMON-LABEL: define {{[^@]+}}@leaf
|
||
|
; COMMON-SAME: () #[[ATTR0:[0-9]+]] {
|
||
|
; COMMON-NEXT: ret i32 1
|
||
|
;
|
||
|
ret i32 1
|
||
|
}
|
||
|
|
||
|
define i32 @self_rec() {
|
||
|
; FNATTRS: Function Attrs: nofree nosync nounwind memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@self_rec
|
||
|
; FNATTRS-SAME: () #[[ATTR1:[0-9]+]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @self_rec()
|
||
|
; FNATTRS-NEXT: ret i32 4
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@self_rec
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR1:[0-9]+]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @self_rec() #[[ATTR1]]
|
||
|
; ATTRIBUTOR-NEXT: ret i32 4
|
||
|
;
|
||
|
%a = call i32 @self_rec()
|
||
|
ret i32 4
|
||
|
}
|
||
|
|
||
|
define i32 @indirect_rec() {
|
||
|
; FNATTRS: Function Attrs: nofree nosync nounwind memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@indirect_rec
|
||
|
; FNATTRS-SAME: () #[[ATTR1]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @indirect_rec2()
|
||
|
; FNATTRS-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@indirect_rec
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR1]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @indirect_rec2() #[[ATTR1]]
|
||
|
; ATTRIBUTOR-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
%a = call i32 @indirect_rec2()
|
||
|
ret i32 %a
|
||
|
}
|
||
|
|
||
|
define i32 @indirect_rec2() {
|
||
|
; FNATTRS: Function Attrs: nofree nosync nounwind memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@indirect_rec2
|
||
|
; FNATTRS-SAME: () #[[ATTR1]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @indirect_rec()
|
||
|
; FNATTRS-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@indirect_rec2
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR1]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @indirect_rec() #[[ATTR1]]
|
||
|
; ATTRIBUTOR-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
%a = call i32 @indirect_rec()
|
||
|
ret i32 %a
|
||
|
}
|
||
|
|
||
|
define i32 @extern() {
|
||
|
; FNATTRS: Function Attrs: nofree nosync memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@extern
|
||
|
; FNATTRS-SAME: () #[[ATTR2:[0-9]+]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @k()
|
||
|
; FNATTRS-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: nosync memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@extern
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR2:[0-9]+]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @k() #[[ATTR7:[0-9]+]]
|
||
|
; ATTRIBUTOR-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
%a = call i32 @k()
|
||
|
ret i32 %a
|
||
|
}
|
||
|
|
||
|
declare i32 @k() readnone
|
||
|
|
||
|
define void @intrinsic(ptr %dest, ptr %src, i32 %len) {
|
||
|
; FNATTRS: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@intrinsic
|
||
|
; FNATTRS-SAME: (ptr nocapture writeonly [[DEST:%.*]], ptr nocapture readonly [[SRC:%.*]], i32 [[LEN:%.*]]) #[[ATTR4:[0-9]+]] {
|
||
|
; FNATTRS-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[DEST]], ptr [[SRC]], i32 [[LEN]], i1 false)
|
||
|
; FNATTRS-NEXT: ret void
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@intrinsic
|
||
|
; ATTRIBUTOR-SAME: (ptr nocapture nofree writeonly [[DEST:%.*]], ptr nocapture nofree readonly [[SRC:%.*]], i32 [[LEN:%.*]]) #[[ATTR4:[0-9]+]] {
|
||
|
; ATTRIBUTOR-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr nocapture writeonly [[DEST]], ptr nocapture readonly [[SRC]], i32 [[LEN]], i1 false) #[[ATTR8:[0-9]+]]
|
||
|
; ATTRIBUTOR-NEXT: ret void
|
||
|
;
|
||
|
call void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 %len, i1 false)
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1)
|
||
|
|
||
|
define internal i32 @called_by_norecurse() {
|
||
|
; FNATTRS: Function Attrs: nofree norecurse nosync memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@called_by_norecurse
|
||
|
; FNATTRS-SAME: () #[[ATTR6:[0-9]+]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @k()
|
||
|
; FNATTRS-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: nosync memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@called_by_norecurse
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR2]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @k() #[[ATTR7]]
|
||
|
; ATTRIBUTOR-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
%a = call i32 @k()
|
||
|
ret i32 %a
|
||
|
}
|
||
|
|
||
|
define void @m() norecurse {
|
||
|
; FNATTRS: Function Attrs: nofree norecurse nosync memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@m
|
||
|
; FNATTRS-SAME: () #[[ATTR6]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @called_by_norecurse()
|
||
|
; FNATTRS-NEXT: ret void
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: norecurse nosync memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@m
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR6:[0-9]+]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @called_by_norecurse() #[[ATTR2]]
|
||
|
; ATTRIBUTOR-NEXT: ret void
|
||
|
;
|
||
|
%a = call i32 @called_by_norecurse()
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define internal i32 @called_by_norecurse_indirectly() {
|
||
|
; FNATTRS: Function Attrs: nofree norecurse nosync memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@called_by_norecurse_indirectly
|
||
|
; FNATTRS-SAME: () #[[ATTR6]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @k()
|
||
|
; FNATTRS-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: nosync memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@called_by_norecurse_indirectly
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR2]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @k() #[[ATTR7]]
|
||
|
; ATTRIBUTOR-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
%a = call i32 @k()
|
||
|
ret i32 %a
|
||
|
}
|
||
|
|
||
|
define internal void @o() {
|
||
|
; FNATTRS: Function Attrs: nofree norecurse nosync memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@o
|
||
|
; FNATTRS-SAME: () #[[ATTR6]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @called_by_norecurse_indirectly()
|
||
|
; FNATTRS-NEXT: ret void
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: nosync memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@o
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR2]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @called_by_norecurse_indirectly() #[[ATTR2]]
|
||
|
; ATTRIBUTOR-NEXT: ret void
|
||
|
;
|
||
|
%a = call i32 @called_by_norecurse_indirectly()
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @p() norecurse {
|
||
|
; FNATTRS: Function Attrs: nofree norecurse nosync memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@p
|
||
|
; FNATTRS-SAME: () #[[ATTR6]] {
|
||
|
; FNATTRS-NEXT: call void @o()
|
||
|
; FNATTRS-NEXT: ret void
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: norecurse nosync memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@p
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR6]] {
|
||
|
; ATTRIBUTOR-NEXT: call void @o() #[[ATTR2]]
|
||
|
; ATTRIBUTOR-NEXT: ret void
|
||
|
;
|
||
|
call void @o()
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define internal i32 @escapes_as_parameter(ptr %p) {
|
||
|
; FNATTRS: Function Attrs: nofree nosync memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@escapes_as_parameter
|
||
|
; FNATTRS-SAME: (ptr nocapture readnone [[P:%.*]]) #[[ATTR2]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @k()
|
||
|
; FNATTRS-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: nosync memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@escapes_as_parameter
|
||
|
; ATTRIBUTOR-SAME: (ptr nocapture nofree readnone [[P:%.*]]) #[[ATTR2]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @k() #[[ATTR7]]
|
||
|
; ATTRIBUTOR-NEXT: ret i32 [[A]]
|
||
|
;
|
||
|
%a = call i32 @k()
|
||
|
ret i32 %a
|
||
|
}
|
||
|
|
||
|
define internal void @q() {
|
||
|
; FNATTRS: Function Attrs: nofree norecurse nosync memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@q
|
||
|
; FNATTRS-SAME: () #[[ATTR6]] {
|
||
|
; FNATTRS-NEXT: [[A:%.*]] = call i32 @escapes_as_parameter(ptr @escapes_as_parameter)
|
||
|
; FNATTRS-NEXT: ret void
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: norecurse nosync memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@q
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR6]] {
|
||
|
; ATTRIBUTOR-NEXT: [[A:%.*]] = call i32 @escapes_as_parameter(ptr nonnull @escapes_as_parameter) #[[ATTR2]]
|
||
|
; ATTRIBUTOR-NEXT: ret void
|
||
|
;
|
||
|
%a = call i32 @escapes_as_parameter(ptr @escapes_as_parameter)
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define void @r() norecurse {
|
||
|
; FNATTRS: Function Attrs: nofree norecurse nosync memory(none)
|
||
|
; FNATTRS-LABEL: define {{[^@]+}}@r
|
||
|
; FNATTRS-SAME: () #[[ATTR6]] {
|
||
|
; FNATTRS-NEXT: call void @q()
|
||
|
; FNATTRS-NEXT: ret void
|
||
|
;
|
||
|
; ATTRIBUTOR: Function Attrs: norecurse nosync memory(none)
|
||
|
; ATTRIBUTOR-LABEL: define {{[^@]+}}@r
|
||
|
; ATTRIBUTOR-SAME: () #[[ATTR6]] {
|
||
|
; ATTRIBUTOR-NEXT: call void @q() #[[ATTR2]]
|
||
|
; ATTRIBUTOR-NEXT: ret void
|
||
|
;
|
||
|
call void @q()
|
||
|
ret void
|
||
|
}
|
||
|
;.
|
||
|
; FNATTRS: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
|
||
|
; FNATTRS: attributes #[[ATTR1]] = { nofree nosync nounwind memory(none) }
|
||
|
; FNATTRS: attributes #[[ATTR2]] = { nofree nosync memory(none) }
|
||
|
; FNATTRS: attributes #[[ATTR3:[0-9]+]] = { memory(none) }
|
||
|
; FNATTRS: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
|
||
|
; FNATTRS: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
|
||
|
; FNATTRS: attributes #[[ATTR6]] = { nofree norecurse nosync memory(none) }
|
||
|
;.
|
||
|
; ATTRIBUTOR: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
|
||
|
; ATTRIBUTOR: attributes #[[ATTR1]] = { nofree nosync nounwind memory(none) }
|
||
|
; ATTRIBUTOR: attributes #[[ATTR2]] = { nosync memory(none) }
|
||
|
; ATTRIBUTOR: attributes #[[ATTR3:[0-9]+]] = { memory(none) }
|
||
|
; ATTRIBUTOR: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
|
||
|
; ATTRIBUTOR: attributes #[[ATTR5:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
|
||
|
; ATTRIBUTOR: attributes #[[ATTR6]] = { norecurse nosync memory(none) }
|
||
|
; ATTRIBUTOR: attributes #[[ATTR7]] = { nosync }
|
||
|
; ATTRIBUTOR: attributes #[[ATTR8]] = { nofree willreturn }
|
||
|
;.
|