Now that the legacy PM is no longer tested, the huge matrix of test prefixes used by attributor tests is no longer needed and very confusing for the casual reader. Reduce the prefixes down to just CHECK, TUNIT and CGSCC.
138 lines
5.5 KiB
LLVM
138 lines
5.5 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-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -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
|
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
target triple = "x86_64-unknown-linux-gnu"
|
|
|
|
define void @fn2(i32* %P, i1 %C) {
|
|
;
|
|
; TUNIT: Function Attrs: argmemonly nofree norecurse nosync nounwind
|
|
; TUNIT-LABEL: define {{[^@]+}}@fn2
|
|
; TUNIT-SAME: (i32* nocapture nofree [[P:%.*]], i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: br label [[IF_END:%.*]]
|
|
; TUNIT: for.cond1:
|
|
; TUNIT-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]]
|
|
; TUNIT: if.end:
|
|
; TUNIT-NEXT: [[E_2:%.*]] = phi i32* [ [[P]], [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ]
|
|
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, i32* [[E_2]], align 4
|
|
; TUNIT-NEXT: store i32 [[TMP0]], i32* [[P]], align 4
|
|
; TUNIT-NEXT: br label [[FOR_COND1]]
|
|
; TUNIT: exit:
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: argmemonly nofree nosync nounwind
|
|
; CGSCC-LABEL: define {{[^@]+}}@fn2
|
|
; CGSCC-SAME: (i32* nocapture nofree nonnull align 4 dereferenceable(4) [[P:%.*]], i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: br label [[IF_END:%.*]]
|
|
; CGSCC: for.cond1:
|
|
; CGSCC-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]]
|
|
; CGSCC: if.end:
|
|
; CGSCC-NEXT: [[E_2:%.*]] = phi i32* [ [[P]], [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ]
|
|
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, i32* [[E_2]], align 4
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]])
|
|
; CGSCC-NEXT: store i32 [[CALL]], i32* [[P]], align 4
|
|
; CGSCC-NEXT: br label [[FOR_COND1]]
|
|
; CGSCC: exit:
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %if.end
|
|
|
|
for.cond1: ; preds = %if.end
|
|
br i1 %C, label %if.end, label %exit
|
|
|
|
if.end: ; preds = %entry, %for.cond1
|
|
%e.2 = phi i32* [ %P, %entry ], [ null, %for.cond1 ]
|
|
%0 = load i32, i32* %e.2, align 4
|
|
%call = call i32 @fn1(i32 %0)
|
|
store i32 %call, i32* %P
|
|
br label %for.cond1
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define internal i32 @fn1(i32 %p1) {
|
|
; CGSCC: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
|
; CGSCC-LABEL: define {{[^@]+}}@fn1
|
|
; CGSCC-SAME: (i32 returned [[P1:%.*]]) #[[ATTR1:[0-9]+]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: ret i32 [[P1]]
|
|
;
|
|
entry:
|
|
%tobool = icmp ne i32 %p1, 0
|
|
%cond = select i1 %tobool, i32 %p1, i32 %p1
|
|
ret i32 %cond
|
|
}
|
|
|
|
define void @fn_no_null_opt(i32* %P, i1 %C) null_pointer_is_valid {
|
|
;
|
|
; TUNIT: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid
|
|
; TUNIT-LABEL: define {{[^@]+}}@fn_no_null_opt
|
|
; TUNIT-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] {
|
|
; TUNIT-NEXT: entry:
|
|
; TUNIT-NEXT: br label [[IF_END:%.*]]
|
|
; TUNIT: for.cond1:
|
|
; TUNIT-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]]
|
|
; TUNIT: if.end:
|
|
; TUNIT-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ]
|
|
; TUNIT-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4294967296
|
|
; TUNIT-NEXT: store i32 [[TMP0]], i32* [[P]], align 4
|
|
; TUNIT-NEXT: br label [[FOR_COND1]]
|
|
; TUNIT: exit:
|
|
; TUNIT-NEXT: ret void
|
|
;
|
|
; CGSCC: Function Attrs: nofree nosync nounwind null_pointer_is_valid
|
|
; CGSCC-LABEL: define {{[^@]+}}@fn_no_null_opt
|
|
; CGSCC-SAME: (i32* nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[P:%.*]], i1 [[C:%.*]]) #[[ATTR2:[0-9]+]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: br label [[IF_END:%.*]]
|
|
; CGSCC: for.cond1:
|
|
; CGSCC-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]]
|
|
; CGSCC: if.end:
|
|
; CGSCC-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ]
|
|
; CGSCC-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4294967296
|
|
; CGSCC-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]])
|
|
; CGSCC-NEXT: store i32 [[CALL]], i32* [[P]], align 4
|
|
; CGSCC-NEXT: br label [[FOR_COND1]]
|
|
; CGSCC: exit:
|
|
; CGSCC-NEXT: ret void
|
|
;
|
|
entry:
|
|
br label %if.end
|
|
|
|
for.cond1: ; preds = %if.end
|
|
br i1 %C, label %if.end, label %exit
|
|
|
|
if.end: ; preds = %entry, %for.cond1
|
|
%e.2 = phi i32* [ undef, %entry ], [ null, %for.cond1 ]
|
|
%0 = load i32, i32* %e.2, align 4
|
|
%call = call i32 @fn0(i32 %0)
|
|
store i32 %call, i32* %P
|
|
br label %for.cond1
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define internal i32 @fn0(i32 %p1) {
|
|
; CGSCC: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
|
|
; CGSCC-LABEL: define {{[^@]+}}@fn0
|
|
; CGSCC-SAME: (i32 returned [[P1:%.*]]) #[[ATTR1]] {
|
|
; CGSCC-NEXT: entry:
|
|
; CGSCC-NEXT: ret i32 [[P1]]
|
|
;
|
|
entry:
|
|
%tobool = icmp ne i32 %p1, 0
|
|
%cond = select i1 %tobool, i32 %p1, i32 %p1
|
|
ret i32 %cond
|
|
}
|
|
;.
|
|
; TUNIT: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind }
|
|
; TUNIT: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind null_pointer_is_valid }
|
|
;.
|
|
; CGSCC: attributes #[[ATTR0]] = { argmemonly nofree nosync nounwind }
|
|
; CGSCC: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
|
|
; CGSCC: attributes #[[ATTR2]] = { nofree nosync nounwind null_pointer_is_valid }
|
|
;.
|