
AANonNull is now the first AA that is always queried via the new APIs and not created manually. Others will follow shortly to avoid trivial AAs whenever possible. This commit introduced some helper logic that will make it simpler to port the next one. It also untangles AADereferenceable and AANonNull such that the former does not keep a handle on the latter. Finally, we stop deducing `nonnull` for `undef`, which was incorrect.
109 lines
4.4 KiB
LLVM
109 lines
4.4 KiB
LLVM
; 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
|
|
;
|
|
; Mostly check we do not crash on these uses
|
|
|
|
define internal void @internal(ptr %fp) {
|
|
;
|
|
;
|
|
; TUNIT-LABEL: define {{[^@]+}}@internal
|
|
; TUNIT-SAME: (ptr nonnull [[FP:%.*]]) {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
|
|
; TUNIT-NEXT: call void @foo(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR1:[0-9]+]]
|
|
; TUNIT-NEXT: call void [[FP]](ptr nonnull @foo)
|
|
; TUNIT-NEXT: call void @callback1(ptr noundef nonnull @foo)
|
|
; TUNIT-NEXT: call void @callback2(ptr noundef nonnull @foo)
|
|
; TUNIT-NEXT: call void @callback2(ptr nonnull [[FP]])
|
|
; TUNIT-NEXT: call void [[FP]](ptr [[A]])
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC-LABEL: define {{[^@]+}}@internal
|
|
; CGSCC-SAME: (ptr noundef nonnull [[FP:%.*]]) {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
|
|
; CGSCC-NEXT: call void @foo(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR1:[0-9]+]]
|
|
; CGSCC-NEXT: call void [[FP]](ptr nonnull @foo)
|
|
; CGSCC-NEXT: call void @callback1(ptr noundef nonnull @foo)
|
|
; CGSCC-NEXT: call void @callback2(ptr noundef nonnull @foo)
|
|
; CGSCC-NEXT: call void @callback2(ptr noundef nonnull [[FP]])
|
|
; CGSCC-NEXT: call void [[FP]](ptr [[A]])
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
entry:
|
|
%a = alloca i32, align 4
|
|
call void @foo(ptr nonnull %a)
|
|
call void %fp(ptr @foo)
|
|
call void @callback1(ptr nonnull @foo)
|
|
call void @callback2(ptr @foo)
|
|
call void @callback2(ptr %fp)
|
|
call void %fp(ptr %a)
|
|
ret void
|
|
}
|
|
|
|
define void @external(ptr %fp) {
|
|
;
|
|
;
|
|
; TUNIT-LABEL: define {{[^@]+}}@external
|
|
; TUNIT-SAME: (ptr [[FP:%.*]]) {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: [[A:%.*]] = alloca i32, align 4
|
|
; TUNIT-NEXT: call void @foo(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR1]]
|
|
; TUNIT-NEXT: call void @callback1(ptr noundef nonnull @foo)
|
|
; TUNIT-NEXT: call void @callback2(ptr noundef nonnull @foo)
|
|
; TUNIT-NEXT: call void @callback2(ptr [[FP]])
|
|
; TUNIT-NEXT: call void [[FP]](ptr @foo)
|
|
; TUNIT-NEXT: call void [[FP]](ptr [[A]])
|
|
; TUNIT-NEXT: call void @internal(ptr nonnull [[FP]])
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC-LABEL: define {{[^@]+}}@external
|
|
; CGSCC-SAME: (ptr [[FP:%.*]]) {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: [[A:%.*]] = alloca i32, align 4
|
|
; CGSCC-NEXT: call void @foo(ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A]]) #[[ATTR1]]
|
|
; CGSCC-NEXT: call void @callback1(ptr noundef nonnull @foo)
|
|
; CGSCC-NEXT: call void @callback2(ptr noundef nonnull @foo)
|
|
; CGSCC-NEXT: call void @callback2(ptr [[FP]])
|
|
; CGSCC-NEXT: call void [[FP]](ptr @foo)
|
|
; CGSCC-NEXT: call void [[FP]](ptr [[A]])
|
|
; CGSCC-NEXT: call void @internal(ptr noundef nonnull [[FP]])
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
entry:
|
|
%a = alloca i32, align 4
|
|
call void @foo(ptr nonnull %a)
|
|
call void @callback1(ptr nonnull @foo)
|
|
call void @callback2(ptr @foo)
|
|
call void @callback2(ptr %fp)
|
|
call void %fp(ptr @foo)
|
|
call void %fp(ptr %a)
|
|
call void @internal(ptr %fp)
|
|
ret void
|
|
}
|
|
|
|
define internal void @foo(ptr %a) {
|
|
;
|
|
; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
|
|
; CHECK-LABEL: define {{[^@]+}}@foo
|
|
; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: store i32 0, ptr [[A]], align 4
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry:
|
|
store i32 0, ptr %a
|
|
ret void
|
|
}
|
|
|
|
declare void @callback1(ptr)
|
|
declare void @callback2(ptr)
|
|
;.
|
|
; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
|
|
; TUNIT: attributes #[[ATTR1]] = { nofree nosync nounwind willreturn memory(write) }
|
|
;.
|
|
; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
|
|
; CGSCC: attributes #[[ATTR1]] = { nofree nounwind willreturn memory(write) }
|
|
;.
|