210 changes: 70 additions & 140 deletions llvm/test/Transforms/Attributor/IPConstantProp/openmp_parallel_for.ll

Large diffs are not rendered by default.

50 changes: 34 additions & 16 deletions llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ define dso_local i32 @main() {
; IS__CGSCC____-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8
; IS__CGSCC____-NEXT: [[THREAD:%.*]] = alloca i64, align 8
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 4294967296 null, i8* (i8*)* noundef nonnull @foo, i8* noalias nocapture nofree noundef readnone align 4294967296 null)
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 4294967296 null, i8* (i8*)* noundef nonnull @bar, i8* noalias nocapture nofree noundef nonnull readnone align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*))
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 4294967296 null, i8* (i8*)* noundef nonnull @bar, i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*))
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 4294967296 null, i8* (i8*)* noundef nonnull @baz, i8* noalias nocapture nofree noundef nonnull readnone align 8 dereferenceable(1) [[ALLOC1]])
; IS__CGSCC____-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* noundef nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias nocapture noundef align 4294967296 null, i8* (i8*)* noundef nonnull @buz, i8* noalias nofree noundef nonnull readnone align 8 dereferenceable(1) [[ALLOC2]])
; IS__CGSCC____-NEXT: ret i32 0
Expand Down Expand Up @@ -81,33 +81,51 @@ entry:
}

define internal i8* @bar(i8* %arg) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@bar
; CHECK-SAME: (i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*)
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@bar
; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*)
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@bar
; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[ARG:%.*]]) #[[ATTR0]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*)
;
entry:
ret i8* %arg
}

define internal i8* @baz(i8* %arg) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@baz
; CHECK-SAME: (i8* noalias nofree noundef nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i8* [[ARG]]
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@baz
; IS__TUNIT____-SAME: (i8* noalias nofree noundef nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: ret i8* [[ARG]]
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@baz
; IS__CGSCC____-SAME: (i8* nofree noundef nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: ret i8* [[ARG]]
;
entry:
ret i8* %arg
}

define internal i8* @buz(i8* %arg) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@buz
; CHECK-SAME: (i8* noalias nofree noundef nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i8* [[ARG]]
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@buz
; IS__TUNIT____-SAME: (i8* noalias nofree noundef nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: ret i8* [[ARG]]
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@buz
; IS__CGSCC____-SAME: (i8* nofree noundef nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) #[[ATTR0]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: ret i8* [[ARG]]
;
entry:
ret i8* %arg
Expand Down
5 changes: 2 additions & 3 deletions llvm/test/Transforms/Attributor/IPConstantProp/recursion.ll
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ define void @bar() {
; IS__TUNIT____-SAME: () #[[ATTR0:[0-9]+]] {
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@bar
; IS__CGSCC____-SAME: () #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-SAME: () #[[ATTR0]] {
; IS__CGSCC____-NEXT: ret void
;
call i32 @foo( i32 17 ) ; <i32>:1 [#uses=0]
Expand All @@ -36,5 +36,4 @@ define void @bar() {
; IS__TUNIT____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
;.
20 changes: 14 additions & 6 deletions llvm/test/Transforms/Attributor/IPConstantProp/remove-call-inst.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,18 @@
; FIXME: Remove obsolete calls/instructions

define i32 @main() noreturn nounwind {
; CHECK: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@main
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i32 123
; IS__TUNIT____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@main
; IS__TUNIT____-SAME: () #[[ATTR0:[0-9]+]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: ret i32 123
;
; IS__CGSCC____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@main
; IS__CGSCC____-SAME: () #[[ATTR0:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = tail call noundef i32 @wwrite() #[[ATTR2:[0-9]+]]
; IS__CGSCC____-NEXT: ret i32 [[CALL2]]
;
entry:
%call2 = tail call i32 @wwrite(i64 0) nounwind
Expand Down Expand Up @@ -51,6 +58,7 @@ return:
;.
; IS__TUNIT____: attributes #[[ATTR0]] = { nofree norecurse noreturn nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse noreturn nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree noreturn nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2]] = { nounwind readnone willreturn }
;.
67 changes: 41 additions & 26 deletions llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,33 @@

;; This function returns its second argument on all return statements
define internal i32* @incdec(i1 %C, i32* %V) {
; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn
; CHECK-LABEL: define {{[^@]+}}@incdec
; CHECK-SAME: (i1 [[C:%.*]], i32* noalias nofree noundef nonnull returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[V:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[V]], align 4
; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CHECK: T:
; CHECK-NEXT: [[X1:%.*]] = add i32 [[X]], 1
; CHECK-NEXT: store i32 [[X1]], i32* [[V]], align 4
; CHECK-NEXT: ret i32* [[V]]
; CHECK: F:
; CHECK-NEXT: [[X2:%.*]] = sub i32 [[X]], 1
; CHECK-NEXT: store i32 [[X2]], i32* [[V]], align 4
; CHECK-NEXT: ret i32* [[V]]
; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@incdec
; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* noalias nofree noundef nonnull returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[V:%.*]]) #[[ATTR0:[0-9]+]] {
; IS__TUNIT____-NEXT: [[X:%.*]] = load i32, i32* [[V]], align 4
; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__TUNIT____: T:
; IS__TUNIT____-NEXT: [[X1:%.*]] = add i32 [[X]], 1
; IS__TUNIT____-NEXT: store i32 [[X1]], i32* [[V]], align 4
; IS__TUNIT____-NEXT: ret i32* [[V]]
; IS__TUNIT____: F:
; IS__TUNIT____-NEXT: [[X2:%.*]] = sub i32 [[X]], 1
; IS__TUNIT____-NEXT: store i32 [[X2]], i32* [[V]], align 4
; IS__TUNIT____-NEXT: ret i32* [[V]]
;
; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@incdec
; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nofree noundef nonnull returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[V:%.*]]) #[[ATTR0:[0-9]+]] {
; IS__CGSCC____-NEXT: [[X:%.*]] = load i32, i32* [[V]], align 4
; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____: T:
; IS__CGSCC____-NEXT: [[X1:%.*]] = add i32 [[X]], 1
; IS__CGSCC____-NEXT: store i32 [[X1]], i32* [[V]], align 4
; IS__CGSCC____-NEXT: ret i32* [[V]]
; IS__CGSCC____: F:
; IS__CGSCC____-NEXT: [[X2:%.*]] = sub i32 [[X]], 1
; IS__CGSCC____-NEXT: store i32 [[X2]], i32* [[V]], align 4
; IS__CGSCC____-NEXT: ret i32* [[V]]
;
%X = load i32, i32* %V
br i1 %C, label %T, label %F
Expand Down Expand Up @@ -90,14 +104,14 @@ define void @caller(i1 %C) personality i32 (...)* @__gxx_personality_v0 {
; IS__TUNIT_NPM: RET:
; IS__TUNIT_NPM-NEXT: ret void
;
; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@caller
; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] personality i32 (...)* @__gxx_personality_v0 {
; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]]) #[[ATTR2:[0-9]+]] personality i32 (...)* @__gxx_personality_v0 {
; IS__CGSCC_OPM-NEXT: [[Q:%.*]] = alloca i32, align 4
; IS__CGSCC_OPM-NEXT: [[W:%.*]] = call align 4 i32* @incdec(i1 [[C]], i32* noalias nofree noundef nonnull align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q]]) #[[ATTR2:[0-9]+]]
; IS__CGSCC_OPM-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 noundef 1, i32 noundef 2) #[[ATTR3:[0-9]+]]
; IS__CGSCC_OPM-NEXT: [[W:%.*]] = call align 4 i32* @incdec(i1 [[C]], i32* noalias nofree noundef nonnull align 4 dereferenceable(4) [[Q]]) #[[ATTR3:[0-9]+]]
; IS__CGSCC_OPM-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 noundef 1, i32 noundef 2) #[[ATTR4:[0-9]+]]
; IS__CGSCC_OPM-NEXT: [[X1:%.*]] = extractvalue { i32, i32 } [[S1]], 0
; IS__CGSCC_OPM-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 noundef 3, i32 noundef 4) #[[ATTR4:[0-9]+]]
; IS__CGSCC_OPM-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 noundef 3, i32 noundef 4) #[[ATTR5:[0-9]+]]
; IS__CGSCC_OPM-NEXT: br label [[OK:%.*]]
; IS__CGSCC_OPM: OK:
; IS__CGSCC_OPM-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0
Expand All @@ -109,14 +123,14 @@ define void @caller(i1 %C) personality i32 (...)* @__gxx_personality_v0 {
; IS__CGSCC_OPM: RET:
; IS__CGSCC_OPM-NEXT: ret void
;
; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@caller
; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR1]] personality i32 (...)* @__gxx_personality_v0 {
; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) #[[ATTR2:[0-9]+]] personality i32 (...)* @__gxx_personality_v0 {
; IS__CGSCC_NPM-NEXT: [[Q:%.*]] = alloca i32, align 4
; IS__CGSCC_NPM-NEXT: [[W:%.*]] = call align 4 i32* @incdec(i1 [[C]], i32* noalias nofree noundef nonnull align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q]]) #[[ATTR2:[0-9]+]]
; IS__CGSCC_NPM-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 noundef 1, i32 noundef 2) #[[ATTR3:[0-9]+]]
; IS__CGSCC_NPM-NEXT: [[W:%.*]] = call align 4 i32* @incdec(i1 [[C]], i32* noalias nofree noundef nonnull align 4 dereferenceable(4) [[Q]]) #[[ATTR3:[0-9]+]]
; IS__CGSCC_NPM-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 noundef 1, i32 noundef 2) #[[ATTR4:[0-9]+]]
; IS__CGSCC_NPM-NEXT: [[X1:%.*]] = extractvalue { i32, i32 } [[S1]], 0
; IS__CGSCC_NPM-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 noundef 3, i32 noundef 4) #[[ATTR4:[0-9]+]]
; IS__CGSCC_NPM-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 noundef 3, i32 noundef 4) #[[ATTR5:[0-9]+]]
; IS__CGSCC_NPM-NEXT: br label [[OK:%.*]]
; IS__CGSCC_NPM: OK:
; IS__CGSCC_NPM-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0
Expand Down Expand Up @@ -163,7 +177,8 @@ declare i32 @__gxx_personality_v0(...)
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { nounwind willreturn }
; IS__CGSCC____: attributes #[[ATTR3:[0-9]+]] = { readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR4:[0-9]+]] = { nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR3:[0-9]+]] = { nounwind willreturn }
; IS__CGSCC____: attributes #[[ATTR4:[0-9]+]] = { readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR5:[0-9]+]] = { nounwind readnone willreturn }
;.
55 changes: 39 additions & 16 deletions llvm/test/Transforms/Attributor/IPConstantProp/return-constant.ll
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,26 @@
; FIXME: icmp folding is missing

define i1 @invokecaller(i1 %C) personality i32 (...)* @__gxx_personality_v0 {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@invokecaller
; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] personality i32 (...)* @__gxx_personality_v0 {
; CHECK-NEXT: [[X:%.*]] = call i32 @foo(i1 [[C]]) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: br label [[OK:%.*]]
; CHECK: OK:
; CHECK-NEXT: ret i1 true
; CHECK: FAIL:
; CHECK-NEXT: unreachable
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@invokecaller
; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] personality i32 (...)* @__gxx_personality_v0 {
; IS__TUNIT____-NEXT: [[X:%.*]] = call i32 @foo(i1 [[C]]) #[[ATTR1:[0-9]+]]
; IS__TUNIT____-NEXT: br label [[OK:%.*]]
; IS__TUNIT____: OK:
; IS__TUNIT____-NEXT: ret i1 true
; IS__TUNIT____: FAIL:
; IS__TUNIT____-NEXT: unreachable
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@invokecaller
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] personality i32 (...)* @__gxx_personality_v0 {
; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @foo(i1 [[C]]) #[[ATTR2:[0-9]+]]
; IS__CGSCC____-NEXT: br label [[OK:%.*]]
; IS__CGSCC____: OK:
; IS__CGSCC____-NEXT: [[Y:%.*]] = icmp ne i32 [[X]], 0
; IS__CGSCC____-NEXT: ret i1 [[Y]]
; IS__CGSCC____: FAIL:
; IS__CGSCC____-NEXT: unreachable
;
%X = invoke i32 @foo( i1 %C ) to label %OK unwind label %FAIL ; <i32> [#uses=1]
OK:
Expand All @@ -39,7 +50,7 @@ define internal i32 @foo(i1 %C) {
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@foo
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; IS__CGSCC____: T:
; IS__CGSCC____-NEXT: ret i32 52
Expand All @@ -56,10 +67,17 @@ F: ; preds = %0
}

define i1 @caller(i1 %C) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@caller
; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: ret i1 true
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller
; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: ret i1 true
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @foo(i1 [[C]]) #[[ATTR3:[0-9]+]]
; IS__CGSCC____-NEXT: [[Y:%.*]] = icmp ne i32 [[X]], 0
; IS__CGSCC____-NEXT: ret i1 [[Y]]
;
%X = call i32 @foo( i1 %C ) ; <i32> [#uses=1]
%Y = icmp ne i32 %X, 0 ; <i1> [#uses=1]
Expand All @@ -68,6 +86,11 @@ define i1 @caller(i1 %C) {

declare i32 @__gxx_personality_v0(...)
;.
; CHECK: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; CHECK: attributes #[[ATTR1]] = { nounwind readnone }
; IS__TUNIT____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__TUNIT____: attributes #[[ATTR1]] = { nounwind readnone }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2]] = { nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR3]] = { readnone willreturn }
;.
59 changes: 40 additions & 19 deletions llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,17 @@ F: ; preds = %0
}

define %0 @caller(i1 %Q) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@caller
; CHECK-SAME: (i1 [[Q:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) #[[ATTR1:[0-9]+]]
; CHECK-NEXT: ret [[TMP0]] [[X]]
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller
; IS__TUNIT____-SAME: (i1 [[Q:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) #[[ATTR1:[0-9]+]]
; IS__TUNIT____-NEXT: ret [[TMP0]] [[X]]
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller
; IS__CGSCC____-SAME: (i1 [[Q:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) #[[ATTR2:[0-9]+]]
; IS__CGSCC____-NEXT: ret [[TMP0]] [[X]]
;
%X = call %0 @foo(i1 %Q)
%A = extractvalue %0 %X, 0
Expand All @@ -80,19 +86,33 @@ define %0 @caller(i1 %Q) {

; Similar to @caller but the result of both calls are actually used.
define i32 @caller2(i1 %Q) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@caller2
; CHECK-SAME: (i1 [[Q:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) #[[ATTR1]]
; CHECK-NEXT: [[A:%.*]] = extractvalue [[TMP0]] [[X]], 0
; CHECK-NEXT: [[B:%.*]] = extractvalue [[TMP0]] [[X]], 1
; CHECK-NEXT: [[Y:%.*]] = call [[TMP0]] @bar(i1 [[Q]]) #[[ATTR1]]
; CHECK-NEXT: [[C:%.*]] = extractvalue [[TMP0]] [[Y]], 0
; CHECK-NEXT: [[D:%.*]] = extractvalue [[TMP0]] [[Y]], 1
; CHECK-NEXT: [[M:%.*]] = add i32 [[A]], [[C]]
; CHECK-NEXT: [[N:%.*]] = add i32 [[B]], [[D]]
; CHECK-NEXT: [[R:%.*]] = add i32 [[N]], [[M]]
; CHECK-NEXT: ret i32 [[R]]
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@caller2
; IS__TUNIT____-SAME: (i1 [[Q:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) #[[ATTR1]]
; IS__TUNIT____-NEXT: [[A:%.*]] = extractvalue [[TMP0]] [[X]], 0
; IS__TUNIT____-NEXT: [[B:%.*]] = extractvalue [[TMP0]] [[X]], 1
; IS__TUNIT____-NEXT: [[Y:%.*]] = call [[TMP0]] @bar(i1 [[Q]]) #[[ATTR1]]
; IS__TUNIT____-NEXT: [[C:%.*]] = extractvalue [[TMP0]] [[Y]], 0
; IS__TUNIT____-NEXT: [[D:%.*]] = extractvalue [[TMP0]] [[Y]], 1
; IS__TUNIT____-NEXT: [[M:%.*]] = add i32 [[A]], [[C]]
; IS__TUNIT____-NEXT: [[N:%.*]] = add i32 [[B]], [[D]]
; IS__TUNIT____-NEXT: [[R:%.*]] = add i32 [[N]], [[M]]
; IS__TUNIT____-NEXT: ret i32 [[R]]
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller2
; IS__CGSCC____-SAME: (i1 [[Q:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) #[[ATTR2]]
; IS__CGSCC____-NEXT: [[A:%.*]] = extractvalue [[TMP0]] [[X]], 0
; IS__CGSCC____-NEXT: [[B:%.*]] = extractvalue [[TMP0]] [[X]], 1
; IS__CGSCC____-NEXT: [[Y:%.*]] = call [[TMP0]] @bar(i1 [[Q]]) #[[ATTR2]]
; IS__CGSCC____-NEXT: [[C:%.*]] = extractvalue [[TMP0]] [[Y]], 0
; IS__CGSCC____-NEXT: [[D:%.*]] = extractvalue [[TMP0]] [[Y]], 1
; IS__CGSCC____-NEXT: [[M:%.*]] = add i32 [[A]], [[C]]
; IS__CGSCC____-NEXT: [[N:%.*]] = add i32 [[B]], [[D]]
; IS__CGSCC____-NEXT: [[R:%.*]] = add i32 [[N]], [[M]]
; IS__CGSCC____-NEXT: ret i32 [[R]]
;
%X = call %0 @foo(i1 %Q)
%A = extractvalue %0 %X, 0
Expand All @@ -111,5 +131,6 @@ define i32 @caller2(i1 %Q) {
; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2]] = { readnone willreturn }
;.
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,19 @@ if.end: ; preds = %if.then1, %entry
}

define internal i32 @test1(i1 %c) {
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@test1
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR0]] {
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: br label [[IF_THEN:%.*]]
; IS__CGSCC____: if.then:
; IS__CGSCC____-NEXT: br label [[RET1:%.*]]
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @testf(i1 [[C]]) #[[ATTR2:[0-9]+]]
; IS__CGSCC____-NEXT: [[RES:%.*]] = icmp eq i32 [[CALL]], 10
; IS__CGSCC____-NEXT: br i1 [[RES]], label [[RET1:%.*]], label [[RET2:%.*]]
; IS__CGSCC____: ret1:
; IS__CGSCC____-NEXT: ret i32 99
; IS__CGSCC____: ret2:
; IS__CGSCC____-NEXT: unreachable
; IS__CGSCC____-NEXT: ret i32 0
;
entry:
br label %if.then
Expand All @@ -59,14 +61,24 @@ ret2: ; preds = %if.then, %entry
}

define i32 @main(i1 %c) {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@main
; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: ret i32 99
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@main
; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR0:[0-9]+]] {
; IS__TUNIT____-NEXT: ret i32 99
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@main
; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[RES:%.*]] = call noundef i32 @test1(i1 [[C]]) #[[ATTR2]]
; IS__CGSCC____-NEXT: ret i32 [[RES]]
;
%res = call i32 @test1(i1 %c)
ret i32 %res
}
;.
; CHECK: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__TUNIT____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2]] = { readnone willreturn }
;.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ define dso_local void @caller() {
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@caller() {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: call void @broker(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) @gtl, i32 (i32*, i32*)* noundef nonnull @callee, i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) @gsh)
; IS__CGSCC____-NEXT: call void @broker(i32* nofree noundef nonnull readonly align 4 dereferenceable(4) @gtl, i32 (i32*, i32*)* noundef nonnull @callee, i32* nofree noundef nonnull readonly align 4 dereferenceable(4) @gsh)
; IS__CGSCC____-NEXT: ret void
;
entry:
Expand Down
1,000 changes: 506 additions & 494 deletions llvm/test/Transforms/Attributor/align.ll

Large diffs are not rendered by default.

94 changes: 63 additions & 31 deletions llvm/test/Transforms/Attributor/alwaysinline.ll
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@ entry:
}

define void @outer1() {
; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; CHECK-LABEL: define {{[^@]+}}@outer1
; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: ret void
; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__TUNIT____-LABEL: define {{[^@]+}}@outer1
; IS__TUNIT____-SAME: () #[[ATTR1:[0-9]+]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@outer1
; IS__CGSCC____-SAME: () #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: ret void
;
entry:
call void @inner1()
Expand All @@ -45,12 +51,17 @@ entry:

; CHECK-NOT: Function Attrs
define i32 @outer2() {
; CHECK: Function Attrs: norecurse
; CHECK-LABEL: define {{[^@]+}}@outer2
; CHECK-SAME: () #[[ATTR2:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[R:%.*]] = call i32 @inner2() #[[ATTR3:[0-9]+]]
; CHECK-NEXT: ret i32 [[R]]
; IS__TUNIT____: Function Attrs: norecurse
; IS__TUNIT____-LABEL: define {{[^@]+}}@outer2
; IS__TUNIT____-SAME: () #[[ATTR2:[0-9]+]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: [[R:%.*]] = call i32 @inner2() #[[ATTR3:[0-9]+]]
; IS__TUNIT____-NEXT: ret i32 [[R]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@outer2() {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[R:%.*]] = call i32 @inner2() #[[ATTR2:[0-9]+]]
; IS__CGSCC____-NEXT: ret i32 [[R]]
;
entry:
%r = call i32 @inner2() alwaysinline
Expand All @@ -61,15 +72,25 @@ entry:
; it is `unexactly defined` and alwaysinline but cannot be inlined.
; so it will not be analyzed
define linkonce i32 @inner3(i8* %addr) alwaysinline {
; CHECK: Function Attrs: alwaysinline
; CHECK-LABEL: define {{[^@]+}}@inner3
; CHECK-SAME: (i8* [[ADDR:%.*]]) #[[ATTR3]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: indirectbr i8* [[ADDR]], [label [[ONE:%.*]], label %two]
; CHECK: one:
; CHECK-NEXT: ret i32 42
; CHECK: two:
; CHECK-NEXT: ret i32 44
; IS__TUNIT____: Function Attrs: alwaysinline
; IS__TUNIT____-LABEL: define {{[^@]+}}@inner3
; IS__TUNIT____-SAME: (i8* [[ADDR:%.*]]) #[[ATTR3]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: indirectbr i8* [[ADDR]], [label [[ONE:%.*]], label %two]
; IS__TUNIT____: one:
; IS__TUNIT____-NEXT: ret i32 42
; IS__TUNIT____: two:
; IS__TUNIT____-NEXT: ret i32 44
;
; IS__CGSCC____: Function Attrs: alwaysinline
; IS__CGSCC____-LABEL: define {{[^@]+}}@inner3
; IS__CGSCC____-SAME: (i8* [[ADDR:%.*]]) #[[ATTR2]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: indirectbr i8* [[ADDR]], [label [[ONE:%.*]], label %two]
; IS__CGSCC____: one:
; IS__CGSCC____-NEXT: ret i32 42
; IS__CGSCC____: two:
; IS__CGSCC____-NEXT: ret i32 44
;
entry:
indirectbr i8* %addr, [ label %one, label %two ]
Expand All @@ -82,22 +103,33 @@ two:
}

define i32 @outer3(i32 %x) {
; CHECK: Function Attrs: norecurse
; CHECK-LABEL: define {{[^@]+}}@outer3
; CHECK-SAME: (i32 [[X:%.*]]) #[[ATTR2]] {
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 42
; CHECK-NEXT: [[ADDR:%.*]] = select i1 [[CMP]], i8* blockaddress(@inner3, [[ONE:%.*]]), i8* blockaddress(@inner3, [[TWO:%.*]])
; CHECK-NEXT: [[CALL:%.*]] = call i32 @inner3(i8* [[ADDR]])
; CHECK-NEXT: ret i32 [[CALL]]
; IS__TUNIT____: Function Attrs: norecurse
; IS__TUNIT____-LABEL: define {{[^@]+}}@outer3
; IS__TUNIT____-SAME: (i32 [[X:%.*]]) #[[ATTR2]] {
; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 42
; IS__TUNIT____-NEXT: [[ADDR:%.*]] = select i1 [[CMP]], i8* blockaddress(@inner3, [[ONE:%.*]]), i8* blockaddress(@inner3, [[TWO:%.*]])
; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @inner3(i8* [[ADDR]])
; IS__TUNIT____-NEXT: ret i32 [[CALL]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@outer3
; IS__CGSCC____-SAME: (i32 [[X:%.*]]) {
; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 42
; IS__CGSCC____-NEXT: [[ADDR:%.*]] = select i1 [[CMP]], i8* blockaddress(@inner3, [[ONE:%.*]]), i8* blockaddress(@inner3, [[TWO:%.*]])
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @inner3(i8* [[ADDR]])
; IS__CGSCC____-NEXT: ret i32 [[CALL]]
;
%cmp = icmp slt i32 %x, 42
%addr = select i1 %cmp, i8* blockaddress(@inner3, %one), i8* blockaddress(@inner3, %two)
%call = call i32 @inner3(i8* %addr)
ret i32 %call
}
;.
; CHECK: attributes #[[ATTR0]] = { alwaysinline nofree norecurse nosync nounwind readnone willreturn }
; CHECK: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
; CHECK: attributes #[[ATTR2]] = { norecurse }
; CHECK: attributes #[[ATTR3]] = { alwaysinline }
; IS__TUNIT____: attributes #[[ATTR0]] = { alwaysinline nofree norecurse nosync nounwind readnone willreturn }
; IS__TUNIT____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__TUNIT____: attributes #[[ATTR2]] = { norecurse }
; IS__TUNIT____: attributes #[[ATTR3]] = { alwaysinline }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { alwaysinline nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2]] = { alwaysinline }
;.
99 changes: 68 additions & 31 deletions llvm/test/Transforms/Attributor/assumes_info.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,21 @@
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM

define dso_local void @entry(i1 %cond) #0 {
; CHECK-LABEL: define {{[^@]+}}@entry
; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @foo(i1 [[COND]])
; CHECK-NEXT: call void @bar()
; CHECK-NEXT: call void @qux() #[[ATTR1:[0-9]+]]
; CHECK-NEXT: ret void
; IS__TUNIT____-LABEL: define {{[^@]+}}@entry
; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) #[[ATTR0:[0-9]+]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: call void @foo(i1 [[COND]])
; IS__TUNIT____-NEXT: call void @bar()
; IS__TUNIT____-NEXT: call void @qux() #[[ATTR1:[0-9]+]]
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@entry
; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) #[[ATTR0:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: call void @foo(i1 [[COND]]) #[[ATTR4:[0-9]+]]
; IS__CGSCC____-NEXT: call void @bar() #[[ATTR3:[0-9]+]]
; IS__CGSCC____-NEXT: call void @qux() #[[ATTR4]]
; IS__CGSCC____-NEXT: ret void
;
entry:
call void @foo(i1 %cond)
Expand All @@ -21,11 +29,17 @@ entry:
}

define internal void @foo(i1 %cond) #1 {
; CHECK-LABEL: define {{[^@]+}}@foo
; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @baz(i1 [[COND]])
; CHECK-NEXT: ret void
; IS__TUNIT____-LABEL: define {{[^@]+}}@foo
; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) #[[ATTR1]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: call void @baz(i1 [[COND]])
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@foo
; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: call void @baz(i1 [[COND]]) #[[ATTR1]]
; IS__CGSCC____-NEXT: ret void
;
entry:
call void @baz(i1 %cond)
Expand All @@ -45,17 +59,29 @@ entry:
}

define internal void @baz(i1 %Cond) {
; CHECK-LABEL: define {{[^@]+}}@baz
; CHECK-SAME: (i1 [[COND:%.*]]) #[[ATTR1]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i1 [[COND]], false
; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK: if.then:
; CHECK-NEXT: call void @baz(i1 noundef false)
; CHECK-NEXT: br label [[IF_END]]
; CHECK: if.end:
; CHECK-NEXT: call void @qux()
; CHECK-NEXT: ret void
; IS__TUNIT____-LABEL: define {{[^@]+}}@baz
; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) #[[ATTR1]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i1 [[COND]], false
; IS__TUNIT____-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; IS__TUNIT____: if.then:
; IS__TUNIT____-NEXT: call void @baz(i1 noundef false)
; IS__TUNIT____-NEXT: br label [[IF_END]]
; IS__TUNIT____: if.end:
; IS__TUNIT____-NEXT: call void @qux()
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@baz
; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i1 [[COND]], false
; IS__CGSCC____-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; IS__CGSCC____: if.then:
; IS__CGSCC____-NEXT: call void @baz(i1 noundef false)
; IS__CGSCC____-NEXT: br label [[IF_END]]
; IS__CGSCC____: if.end:
; IS__CGSCC____-NEXT: call void @qux()
; IS__CGSCC____-NEXT: ret void
;
entry:
%tobool = icmp ne i1 %Cond, 0
Expand All @@ -71,11 +97,16 @@ if.end:
}

define internal void @qux() {
; CHECK-LABEL: define {{[^@]+}}@qux
; CHECK-SAME: () #[[ATTR1]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @call()
; CHECK-NEXT: ret void
; IS__TUNIT____-LABEL: define {{[^@]+}}@qux
; IS__TUNIT____-SAME: () #[[ATTR1]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: call void @call()
; IS__TUNIT____-NEXT: ret void
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@qux() {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: call void @call()
; IS__CGSCC____-NEXT: ret void
;
entry:
call void @call()
Expand All @@ -89,7 +120,13 @@ attributes #1 = { "llvm.assume"="B" }
attributes #2 = { "llvm.assume"="B,C" }
attributes #3 = { "llvm.assume"="B,C,A" }
;.
; CHECK: attributes #[[ATTR0]] = { "llvm.assume"="A" }
; CHECK: attributes #[[ATTR1]] = { "llvm.assume"="B,A" }
; CHECK: attributes #[[ATTR2]] = { "llvm.assume"="B,C,A" }
; IS__TUNIT____: attributes #[[ATTR0]] = { "llvm.assume"="A" }
; IS__TUNIT____: attributes #[[ATTR1]] = { "llvm.assume"="B,A" }
; IS__TUNIT____: attributes #[[ATTR2]] = { "llvm.assume"="B,C,A" }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { "llvm.assume"="A" }
; IS__CGSCC____: attributes #[[ATTR1]] = { "llvm.assume"="B" }
; IS__CGSCC____: attributes #[[ATTR2]] = { "llvm.assume"="B,C" }
; IS__CGSCC____: attributes #[[ATTR3]] = { "llvm.assume"="B,C,A" }
; IS__CGSCC____: attributes #[[ATTR4]] = { "llvm.assume"="B,A" }
;.
239 changes: 132 additions & 107 deletions llvm/test/Transforms/Attributor/callbacks.ll

Large diffs are not rendered by default.

125 changes: 84 additions & 41 deletions llvm/test/Transforms/Attributor/cb_liveness_disabled.ll
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,33 @@ define i32 @test_range2(i32 %0) #0 {
ret i32 %.0
}
define i32 @test(i32 %0, i32 %1) #0 {
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
; CHECK: 4:
; CHECK-NEXT: [[TMP5:%.*]] = call noundef i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
; CHECK-NEXT: br label [[TMP8:%.*]]
; CHECK: 6:
; CHECK-NEXT: [[TMP7:%.*]] = call noundef i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]]
; CHECK-NEXT: br label [[TMP8]]
; CHECK: 8:
; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ]
; CHECK-NEXT: ret i32 [[DOT0]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0
; IS__TUNIT____-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
; IS__TUNIT____: 4:
; IS__TUNIT____-NEXT: [[TMP5:%.*]] = call noundef i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
; IS__TUNIT____-NEXT: br label [[TMP8:%.*]]
; IS__TUNIT____: 6:
; IS__TUNIT____-NEXT: [[TMP7:%.*]] = call noundef i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]]
; IS__TUNIT____-NEXT: br label [[TMP8]]
; IS__TUNIT____: 8:
; IS__TUNIT____-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ]
; IS__TUNIT____-NEXT: ret i32 [[DOT0]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0
; IS__CGSCC____-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
; IS__CGSCC____: 4:
; IS__CGSCC____-NEXT: [[TMP5:%.*]] = call noundef i32 @test_range1(i32 [[TMP0]])
; IS__CGSCC____-NEXT: br label [[TMP8:%.*]]
; IS__CGSCC____: 6:
; IS__CGSCC____-NEXT: [[TMP7:%.*]] = call noundef i32 @test_range2(i32 [[TMP0]])
; IS__CGSCC____-NEXT: br label [[TMP8]]
; IS__CGSCC____: 8:
; IS__CGSCC____-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ]
; IS__CGSCC____-NEXT: ret i32 [[DOT0]]
;
%3 = icmp ne i32 %1, 0
br i1 %3, label %4, label %6
Expand All @@ -94,12 +108,19 @@ define i32 @test(i32 %0, i32 %1) #0 {
}

define i32 @test_pcheck1(i32 %0) #0 {
; CHECK-LABEL: define {{[^@]+}}@test_pcheck1
; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2:![0-9]+]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; CHECK-NEXT: ret i32 [[TMP4]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test_pcheck1
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2:![0-9]+]]
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101
; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test_pcheck1
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1)
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101
; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
;
%2 = call i32 @test(i32 %0, i32 1)
%3 = icmp slt i32 %2, 101
Expand All @@ -108,12 +129,19 @@ define i32 @test_pcheck1(i32 %0) #0 {
}

define i32 @test_pcheck2(i32 %0) #0 {
; CHECK-LABEL: define {{[^@]+}}@test_pcheck2
; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; CHECK-NEXT: ret i32 [[TMP4]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test_pcheck2
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99
; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test_pcheck2
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0)
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99
; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
;
%2 = call i32 @test(i32 %0, i32 0)
%3 = icmp sgt i32 %2, 99
Expand All @@ -122,12 +150,19 @@ define i32 @test_pcheck2(i32 %0) #0 {
}

define i32 @test_ncheck1(i32 %0) #0 {
; CHECK-LABEL: define {{[^@]+}}@test_ncheck1
; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; CHECK-NEXT: ret i32 [[TMP4]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test_ncheck1
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2]]
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50
; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test_ncheck1
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1)
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50
; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
;
%2 = call i32 @test(i32 %0, i32 1)
%3 = icmp sgt i32 %2, 50
Expand All @@ -136,12 +171,19 @@ define i32 @test_ncheck1(i32 %0) #0 {
}

define i32 @test_ncheck2(i32 %0) #0 {
; CHECK-LABEL: define {{[^@]+}}@test_ncheck2
; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; CHECK-NEXT: ret i32 [[TMP4]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test_ncheck2
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150
; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test_ncheck2
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0)
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150
; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
;
%2 = call i32 @test(i32 %0, i32 0)
%3 = icmp sgt i32 %2, 150
Expand All @@ -158,9 +200,10 @@ attributes #0 = { noinline nounwind sspstrong uwtable}
; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone sspstrong willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone sspstrong willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { readnone willreturn }
;.
; CHECK: [[RNG0]] = !{i32 0, i32 101}
; CHECK: [[RNG1]] = !{i32 100, i32 201}
; CHECK: [[RNG2]] = !{i32 0, i32 201}
; IS__TUNIT____: [[RNG0]] = !{i32 0, i32 101}
; IS__TUNIT____: [[RNG1]] = !{i32 100, i32 201}
; IS__TUNIT____: [[RNG2]] = !{i32 0, i32 201}
;.
125 changes: 84 additions & 41 deletions llvm/test/Transforms/Attributor/cb_liveness_enabled.ll
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,33 @@ define i32 @test_range2(i32 %0) #0 {
ret i32 %.0
}
define i32 @test(i32 %0, i32 %1) #0 {
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0
; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
; CHECK: 4:
; CHECK-NEXT: [[TMP5:%.*]] = call noundef i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
; CHECK-NEXT: br label [[TMP8:%.*]]
; CHECK: 6:
; CHECK-NEXT: [[TMP7:%.*]] = call noundef i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]]
; CHECK-NEXT: br label [[TMP8]]
; CHECK: 8:
; CHECK-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ]
; CHECK-NEXT: ret i32 [[DOT0]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0
; IS__TUNIT____-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
; IS__TUNIT____: 4:
; IS__TUNIT____-NEXT: [[TMP5:%.*]] = call noundef i32 @test_range1(i32 [[TMP0]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
; IS__TUNIT____-NEXT: br label [[TMP8:%.*]]
; IS__TUNIT____: 6:
; IS__TUNIT____-NEXT: [[TMP7:%.*]] = call noundef i32 @test_range2(i32 [[TMP0]]) #[[ATTR1]], !range [[RNG1:![0-9]+]]
; IS__TUNIT____-NEXT: br label [[TMP8]]
; IS__TUNIT____: 8:
; IS__TUNIT____-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ]
; IS__TUNIT____-NEXT: ret i32 [[DOT0]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP1]], 0
; IS__CGSCC____-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP6:%.*]]
; IS__CGSCC____: 4:
; IS__CGSCC____-NEXT: [[TMP5:%.*]] = call noundef i32 @test_range1(i32 [[TMP0]])
; IS__CGSCC____-NEXT: br label [[TMP8:%.*]]
; IS__CGSCC____: 6:
; IS__CGSCC____-NEXT: [[TMP7:%.*]] = call noundef i32 @test_range2(i32 [[TMP0]])
; IS__CGSCC____-NEXT: br label [[TMP8]]
; IS__CGSCC____: 8:
; IS__CGSCC____-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP5]], [[TMP4]] ], [ [[TMP7]], [[TMP6]] ]
; IS__CGSCC____-NEXT: ret i32 [[DOT0]]
;
%3 = icmp ne i32 %1, 0
br i1 %3, label %4, label %6
Expand All @@ -94,12 +108,19 @@ define i32 @test(i32 %0, i32 %1) #0 {
}

define i32 @test_pcheck1(i32 %0) #0 {
; CHECK-LABEL: define {{[^@]+}}@test_pcheck1
; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2:![0-9]+]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; CHECK-NEXT: ret i32 [[TMP4]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test_pcheck1
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2:![0-9]+]]
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101
; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test_pcheck1
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1)
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 101
; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
;
; IS__TUNIT_____ENABLED-LABEL: define {{[^@]+}}@test_pcheck1
; IS__TUNIT_____ENABLED-SAME: (i32 [[TMP0:%.*]])
Expand All @@ -111,12 +132,19 @@ define i32 @test_pcheck1(i32 %0) #0 {
}

define i32 @test_pcheck2(i32 %0) #0 {
; CHECK-LABEL: define {{[^@]+}}@test_pcheck2
; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; CHECK-NEXT: ret i32 [[TMP4]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test_pcheck2
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99
; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test_pcheck2
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0)
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 99
; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
;
%2 = call i32 @test(i32 %0, i32 0)
%3 = icmp sgt i32 %2, 99
Expand All @@ -125,12 +153,19 @@ define i32 @test_pcheck2(i32 %0) #0 {
}

define i32 @test_ncheck1(i32 %0) #0 {
; CHECK-LABEL: define {{[^@]+}}@test_ncheck1
; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; CHECK-NEXT: ret i32 [[TMP4]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test_ncheck1
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1) #[[ATTR1]], !range [[RNG2]]
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50
; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test_ncheck1
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 1)
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 50
; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
;
%2 = call i32 @test(i32 %0, i32 1)
%3 = icmp sgt i32 %2, 50
Expand All @@ -139,12 +174,19 @@ define i32 @test_ncheck1(i32 %0) #0 {
}

define i32 @test_ncheck2(i32 %0) #0 {
; CHECK-LABEL: define {{[^@]+}}@test_ncheck2
; CHECK-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; CHECK-NEXT: ret i32 [[TMP4]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test_ncheck2
; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0) #[[ATTR1]], !range [[RNG2]]
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150
; IS__TUNIT____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP4]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test_ncheck2
; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = call i32 @test(i32 [[TMP0]], i32 noundef 0)
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 150
; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP4]]
;
%2 = call i32 @test(i32 %0, i32 0)
%3 = icmp sgt i32 %2, 150
Expand All @@ -161,9 +203,10 @@ attributes #0 = { noinline nounwind sspstrong uwtable}
; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree noinline norecurse nosync nounwind readnone sspstrong willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree noinline nosync nounwind readnone sspstrong willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { readnone willreturn }
;.
; CHECK: [[RNG0]] = !{i32 0, i32 101}
; CHECK: [[RNG1]] = !{i32 100, i32 201}
; CHECK: [[RNG2]] = !{i32 0, i32 201}
; IS__TUNIT____: [[RNG0]] = !{i32 0, i32 101}
; IS__TUNIT____: [[RNG1]] = !{i32 100, i32 201}
; IS__TUNIT____: [[RNG2]] = !{i32 0, i32 201}
;.
126 changes: 75 additions & 51 deletions llvm/test/Transforms/Attributor/cb_range_disabled.ll
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,35 @@ define i32 @test_range(i32 %unknown) {
}

define i32 @test1(i32 %unknown, i32 %b) {
; CHECK-LABEL: define {{[^@]+}}@test1
; CHECK-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 [[TMP1]], [[B]]
; CHECK-NEXT: ret i32 [[TMP2]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test1
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = sub nsw i32 [[TMP1]], [[B]]
; IS__TUNIT____-NEXT: ret i32 [[TMP2]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test1
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]])
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = sub nsw i32 [[TMP1]], [[B]]
; IS__CGSCC____-NEXT: ret i32 [[TMP2]]
;
%1 = call i32 @test_range(i32 %unknown)
%2 = sub nsw i32 %1, %b
ret i32 %2
}

define i32 @test2(i32 %unknown, i32 %b) {
; CHECK-LABEL: define {{[^@]+}}@test2
; CHECK-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]]) #[[ATTR1]], !range [[RNG0]]
; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[B]]
; CHECK-NEXT: ret i32 [[TMP2]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test2
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]]) #[[ATTR1]], !range [[RNG0]]
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[B]]
; IS__TUNIT____-NEXT: ret i32 [[TMP2]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test2
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]])
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[B]]
; IS__CGSCC____-NEXT: ret i32 [[TMP2]]
;
%1 = call i32 @test_range(i32 %unknown)
%2 = add nsw i32 %1, %b
Expand All @@ -48,19 +60,19 @@ define i32 @test2(i32 %unknown, i32 %b) {
; Positive checks

define i32 @test1_pcheck(i32 %unknown) {
; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test1_pcheck
; NOT_CGSCC_NPM-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; NOT_CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20)
; NOT_CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 90
; NOT_CGSCC_NPM-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; NOT_CGSCC_NPM-NEXT: ret i32 [[TMP3]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test1_pcheck
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20)
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 90
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP3]]
;
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test1_pcheck
; IS__CGSCC_NPM-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG1:![0-9]+]]
; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 90
; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC_NPM-NEXT: ret i32 [[TMP3]]
; IS__CGSCC____-LABEL: define {{[^@]+}}@test1_pcheck
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20)
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 90
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP3]]
;
%1 = call i32 @test1(i32 %unknown, i32 20)
%2 = icmp sle i32 %1, 90
Expand All @@ -69,12 +81,19 @@ define i32 @test1_pcheck(i32 %unknown) {
}

define i32 @test2_pcheck(i32 %unknown) {
; CHECK-LABEL: define {{[^@]+}}@test2_pcheck
; CHECK-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20)
; CHECK-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 20
; CHECK-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; CHECK-NEXT: ret i32 [[TMP3]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test2_pcheck
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20)
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 20
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP3]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test2_pcheck
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20)
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 20
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP3]]
;
%1 = call i32 @test2(i32 %unknown, i32 20)
%2 = icmp sge i32 %1, 20
Expand All @@ -85,19 +104,19 @@ define i32 @test2_pcheck(i32 %unknown) {
; Negative checks

define i32 @test1_ncheck(i32 %unknown) {
; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test1_ncheck
; NOT_CGSCC_NPM-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; NOT_CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20)
; NOT_CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 10
; NOT_CGSCC_NPM-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; NOT_CGSCC_NPM-NEXT: ret i32 [[TMP3]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test1_ncheck
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20)
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 10
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP3]]
;
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test1_ncheck
; IS__CGSCC_NPM-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG1]]
; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 10
; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC_NPM-NEXT: ret i32 [[TMP3]]
; IS__CGSCC____-LABEL: define {{[^@]+}}@test1_ncheck
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20)
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 10
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP3]]
;
%1 = call i32 @test1(i32 %unknown, i32 20)
%2 = icmp sle i32 %1, 10
Expand All @@ -106,12 +125,19 @@ define i32 @test1_ncheck(i32 %unknown) {
}

define i32 @test2_ncheck(i32 %unknown) {
; CHECK-LABEL: define {{[^@]+}}@test2_ncheck
; CHECK-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20)
; CHECK-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 30
; CHECK-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; CHECK-NEXT: ret i32 [[TMP3]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test2_ncheck
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20)
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 30
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP3]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test2_ncheck
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20)
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 30
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP3]]
;
%1 = call i32 @test2(i32 %unknown, i32 20)
%2 = icmp sge i32 %1, 30
Expand All @@ -123,10 +149,8 @@ define i32 @test2_ncheck(i32 %unknown) {
; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
;.
; NOT_CGSCC_NPM: [[RNG0]] = !{i32 0, i32 101}
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { readnone willreturn }
;.
; IS__CGSCC_NPM: [[RNG0]] = !{i32 0, i32 101}
; IS__CGSCC_NPM: [[RNG1]] = !{i32 -2147483647, i32 -2147483648}
; IS__TUNIT____: [[RNG0]] = !{i32 0, i32 101}
;.
105 changes: 73 additions & 32 deletions llvm/test/Transforms/Attributor/cb_range_enabled.ll
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,35 @@ define i32 @test_range(i32 %unknown) {
}

define i32 @test1(i32 %unknown, i32 %b) {
; CHECK-LABEL: define {{[^@]+}}@test1
; CHECK-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i32 [[TMP1]], [[B]]
; CHECK-NEXT: ret i32 [[TMP2]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test1
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]]) #[[ATTR1:[0-9]+]], !range [[RNG0:![0-9]+]]
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = sub nsw i32 [[TMP1]], [[B]]
; IS__TUNIT____-NEXT: ret i32 [[TMP2]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test1
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]])
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = sub nsw i32 [[TMP1]], [[B]]
; IS__CGSCC____-NEXT: ret i32 [[TMP2]]
;
%1 = call i32 @test_range(i32 %unknown)
%2 = sub nsw i32 %1, %b
ret i32 %2
}

define i32 @test2(i32 %unknown, i32 %b) {
; CHECK-LABEL: define {{[^@]+}}@test2
; CHECK-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]]) #[[ATTR1]], !range [[RNG0]]
; CHECK-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[B]]
; CHECK-NEXT: ret i32 [[TMP2]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test2
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]]) #[[ATTR1]], !range [[RNG0]]
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[B]]
; IS__TUNIT____-NEXT: ret i32 [[TMP2]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test2
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]], i32 [[B:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test_range(i32 [[UNKNOWN]])
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = add nsw i32 [[TMP1]], [[B]]
; IS__CGSCC____-NEXT: ret i32 [[TMP2]]
;
%1 = call i32 @test_range(i32 %unknown)
%2 = add nsw i32 %1, %b
Expand All @@ -52,9 +64,16 @@ define i32 @test2(i32 %unknown, i32 %b) {
; we need to look into this again. For the purpose of making some progress we take this regression
; for now, call site contexts are not on by default anyway (yet).
define i32 @test1_pcheck(i32 %unknown) {
; CHECK-LABEL: define {{[^@]+}}@test1_pcheck
; CHECK-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: ret i32 1
; IS__TUNIT____-LABEL: define {{[^@]+}}@test1_pcheck
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: ret i32 1
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test1_pcheck
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20)
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 90
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP3]]
;
%1 = call i32 @test1(i32 %unknown, i32 20)
%2 = icmp sle i32 %1, 90
Expand All @@ -63,9 +82,16 @@ define i32 @test1_pcheck(i32 %unknown) {
}

define i32 @test2_pcheck(i32 %unknown) {
; CHECK-LABEL: define {{[^@]+}}@test2_pcheck
; CHECK-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: ret i32 1
; IS__TUNIT____-LABEL: define {{[^@]+}}@test2_pcheck
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: ret i32 1
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test2_pcheck
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20)
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 20
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP3]]
;
%1 = call i32 @test2(i32 %unknown, i32 20)
%2 = icmp sge i32 %1, 20
Expand All @@ -76,12 +102,19 @@ define i32 @test2_pcheck(i32 %unknown) {
; Negative checks

define i32 @test1_ncheck(i32 %unknown) {
; CHECK-LABEL: define {{[^@]+}}@test1_ncheck
; CHECK-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG1:![0-9]+]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 10
; CHECK-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; CHECK-NEXT: ret i32 [[TMP3]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test1_ncheck
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG1:![0-9]+]]
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 10
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP3]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test1_ncheck
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test1(i32 [[UNKNOWN]], i32 noundef 20)
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sle i32 [[TMP1]], 10
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP3]]
;
%1 = call i32 @test1(i32 %unknown, i32 20)
%2 = icmp sle i32 %1, 10
Expand All @@ -90,12 +123,19 @@ define i32 @test1_ncheck(i32 %unknown) {
}

define i32 @test2_ncheck(i32 %unknown) {
; CHECK-LABEL: define {{[^@]+}}@test2_ncheck
; CHECK-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG2:![0-9]+]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 30
; CHECK-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; CHECK-NEXT: ret i32 [[TMP3]]
; IS__TUNIT____-LABEL: define {{[^@]+}}@test2_ncheck
; IS__TUNIT____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20) #[[ATTR1]], !range [[RNG2:![0-9]+]]
; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 30
; IS__TUNIT____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__TUNIT____-NEXT: ret i32 [[TMP3]]
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@test2_ncheck
; IS__CGSCC____-SAME: (i32 [[UNKNOWN:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @test2(i32 [[UNKNOWN]], i32 noundef 20)
; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp sge i32 [[TMP1]], 30
; IS__CGSCC____-NEXT: [[TMP3:%.*]] = zext i1 [[TMP2]] to i32
; IS__CGSCC____-NEXT: ret i32 [[TMP3]]
;
%1 = call i32 @test2(i32 %unknown, i32 20)
%2 = icmp sge i32 %1, 30
Expand All @@ -107,9 +147,10 @@ define i32 @test2_ncheck(i32 %unknown) {
; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR2:[0-9]+]] = { readnone willreturn }
;.
; CHECK: [[RNG0]] = !{i32 0, i32 101}
; CHECK: [[RNG1]] = !{i32 -20, i32 81}
; CHECK: [[RNG2]] = !{i32 20, i32 121}
; IS__TUNIT____: [[RNG0]] = !{i32 0, i32 101}
; IS__TUNIT____: [[RNG1]] = !{i32 -20, i32 81}
; IS__TUNIT____: [[RNG2]] = !{i32 20, i32 121}
;.
54 changes: 36 additions & 18 deletions llvm/test/Transforms/Attributor/dereferenceable-1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -498,23 +498,41 @@ for.body: ; preds = %entry, %for.body
}

define void @call_fill_range(i32* nocapture %p, i64* nocapture readonly %range) {
; IS________OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind
; IS________OPM-LABEL: define {{[^@]+}}@call_fill_range
; IS________OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) #[[ATTR4:[0-9]+]] {
; IS________OPM-NEXT: entry:
; IS________OPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range [[RNG0:![0-9]+]]
; IS________OPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR7:[0-9]+]]
; IS________OPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR7]]
; IS________OPM-NEXT: ret void
; IS__TUNIT_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind
; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@call_fill_range
; IS__TUNIT_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) #[[ATTR4:[0-9]+]] {
; IS__TUNIT_OPM-NEXT: entry:
; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range [[RNG0:![0-9]+]]
; IS__TUNIT_OPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR7:[0-9]+]]
; IS__TUNIT_OPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR7]]
; IS__TUNIT_OPM-NEXT: ret void
;
; IS________NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn
; IS________NPM-LABEL: define {{[^@]+}}@call_fill_range
; IS________NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) #[[ATTR3:[0-9]+]] {
; IS________NPM-NEXT: entry:
; IS________NPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range [[RNG0:![0-9]+]]
; IS________NPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6:[0-9]+]]
; IS________NPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6]]
; IS________NPM-NEXT: ret void
; IS__TUNIT_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn
; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@call_fill_range
; IS__TUNIT_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) #[[ATTR3:[0-9]+]] {
; IS__TUNIT_NPM-NEXT: entry:
; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range [[RNG0:![0-9]+]]
; IS__TUNIT_NPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6:[0-9]+]]
; IS__TUNIT_NPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6]]
; IS__TUNIT_NPM-NEXT: ret void
;
; IS__CGSCC_OPM: Function Attrs: argmemonly nofree nosync nounwind
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@call_fill_range
; IS__CGSCC_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) #[[ATTR4:[0-9]+]] {
; IS__CGSCC_OPM-NEXT: entry:
; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range [[RNG0:![0-9]+]]
; IS__CGSCC_OPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR7:[0-9]+]]
; IS__CGSCC_OPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR7]]
; IS__CGSCC_OPM-NEXT: ret void
;
; IS__CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn
; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@call_fill_range
; IS__CGSCC_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree noundef nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) #[[ATTR3:[0-9]+]] {
; IS__CGSCC_NPM-NEXT: entry:
; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range [[RNG0:![0-9]+]]
; IS__CGSCC_NPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6:[0-9]+]]
; IS__CGSCC_NPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) #[[ATTR6]]
; IS__CGSCC_NPM-NEXT: ret void
;
entry:
%0 = load i64, i64* %range, align 8, !range !0
Expand Down Expand Up @@ -974,7 +992,7 @@ f:
; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nounwind willreturn }
; IS__CGSCC_OPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
; IS__CGSCC_OPM: attributes #[[ATTR3]] = { argmemonly nofree norecurse nosync nounwind writeonly }
; IS__CGSCC_OPM: attributes #[[ATTR4]] = { argmemonly nofree norecurse nosync nounwind }
; IS__CGSCC_OPM: attributes #[[ATTR4]] = { argmemonly nofree nosync nounwind }
; IS__CGSCC_OPM: attributes #[[ATTR5]] = { argmemonly nofree nosync nounwind writeonly }
; IS__CGSCC_OPM: attributes #[[ATTR6:[0-9]+]] = { inaccessiblememonly nocallback nofree nosync nounwind willreturn }
; IS__CGSCC_OPM: attributes #[[ATTR7]] = { nounwind writeonly }
Expand All @@ -985,7 +1003,7 @@ f:
; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nounwind willreturn }
; IS__CGSCC_NPM: attributes #[[ATTR2]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
; IS__CGSCC_NPM: attributes #[[ATTR3]] = { argmemonly nofree norecurse nosync nounwind willreturn }
; IS__CGSCC_NPM: attributes #[[ATTR3]] = { argmemonly nofree nosync nounwind willreturn }
; IS__CGSCC_NPM: attributes #[[ATTR4]] = { argmemonly nofree nosync nounwind writeonly }
; IS__CGSCC_NPM: attributes #[[ATTR5:[0-9]+]] = { inaccessiblememonly nocallback nofree nosync nounwind willreturn }
; IS__CGSCC_NPM: attributes #[[ATTR6]] = { nounwind willreturn writeonly }
Expand Down
93 changes: 59 additions & 34 deletions llvm/test/Transforms/Attributor/internal-noalias.ll
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ define dso_local i32 @visible(i32* noalias %A, i32* noalias %B) #0 {
; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]]
; IS__TUNIT____-NEXT: ret i32 [[ADD]]
;
; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable
; IS__CGSCC____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly willreturn uwtable
; IS__CGSCC____-LABEL: define {{[^@]+}}@visible
; IS__CGSCC____-SAME: (i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR0:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @noalias_args(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR4:[0-9]+]]
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i32 @noalias_args_argmem(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR4]]
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @noalias_args(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR5:[0-9]+]]
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i32 @noalias_args_argmem(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR5]]
; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]]
; IS__CGSCC____-NEXT: ret i32 [[ADD]]
;
Expand All @@ -42,14 +42,14 @@ define private i32 @noalias_args(i32* %A, i32* %B) #0 {
; IS__TUNIT____-NEXT: [[ADD2:%.*]] = add nsw i32 [[ADD]], [[CALL]]
; IS__TUNIT____-NEXT: ret i32 [[ADD2]]
;
; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable
; IS__CGSCC____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly willreturn uwtable
; IS__CGSCC____-LABEL: define {{[^@]+}}@noalias_args
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR0]] {
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR0]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 4
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4
; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR4]]
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR5]]
; IS__CGSCC____-NEXT: [[ADD2:%.*]] = add nsw i32 [[ADD]], [[CALL]]
; IS__CGSCC____-NEXT: ret i32 [[ADD2]]
;
Expand All @@ -64,14 +64,23 @@ entry:


define internal i32 @noalias_args_argmem(i32* %A, i32* %B) #1 {
; CHECK: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable
; CHECK-LABEL: define {{[^@]+}}@noalias_args_argmem
; CHECK-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
; CHECK-NEXT: ret i32 [[ADD]]
; IS__TUNIT____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable
; IS__TUNIT____-LABEL: define {{[^@]+}}@noalias_args_argmem
; IS__TUNIT____-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR0]] {
; IS__TUNIT____-NEXT: entry:
; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 4
; IS__TUNIT____-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4
; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
; IS__TUNIT____-NEXT: ret i32 [[ADD]]
;
; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable
; IS__CGSCC____-LABEL: define {{[^@]+}}@noalias_args_argmem
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 4
; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4
; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]]
; IS__CGSCC____-NEXT: ret i32 [[ADD]]
;
entry:
%0 = load i32, i32* %A, align 4
Expand All @@ -92,13 +101,13 @@ define dso_local i32 @visible_local(i32* %A) #0 {
; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]]
; IS__TUNIT____-NEXT: ret i32 [[ADD]]
;
; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind willreturn uwtable
; IS__CGSCC____: Function Attrs: argmemonly nofree noinline nosync nounwind willreturn uwtable
; IS__CGSCC____-LABEL: define {{[^@]+}}@visible_local
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR1:[0-9]+]] {
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) #[[ATTR2:[0-9]+]] {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4
; IS__CGSCC____-NEXT: store i32 5, i32* [[B]], align 4
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @noalias_args(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR4]]
; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @noalias_args(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR5]]
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i32 @noalias_args_argmem(i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]])
; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]]
; IS__CGSCC____-NEXT: ret i32 [[ADD]]
Expand All @@ -113,10 +122,13 @@ entry:
}

define internal i32 @noalias_args_argmem_ro(i32* %A, i32* %B) #1 {
; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone willreturn uwtable
; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable
; IS__CGSCC____-LABEL: define {{[^@]+}}@noalias_args_argmem_ro
; IS__CGSCC____-SAME: () #[[ATTR2:[0-9]+]] {
; IS__CGSCC____-NEXT: ret i32 10
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] {
; IS__CGSCC____-NEXT: [[T0:%.*]] = load i32, i32* [[A]], align 4
; IS__CGSCC____-NEXT: [[T1:%.*]] = load i32, i32* [[B]], align 4
; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[T0]], [[T1]]
; IS__CGSCC____-NEXT: ret i32 [[ADD]]
;
%t0 = load i32, i32* %A, align 4
%t1 = load i32, i32* %B, align 4
Expand All @@ -131,11 +143,13 @@ define i32 @visible_local_2() {
; IS__TUNIT____-NEXT: [[B:%.*]] = alloca i32, align 4
; IS__TUNIT____-NEXT: ret i32 10
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@visible_local_2
; IS__CGSCC____-SAME: () #[[ATTR3:[0-9]+]] {
; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4
; IS__CGSCC____-NEXT: ret i32 10
; IS__CGSCC____-NEXT: store i32 5, i32* [[B]], align 4
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]], i32* noalias nocapture nofree noundef nonnull readonly align 4 dereferenceable(4) [[B]]) #[[ATTR6:[0-9]+]]
; IS__CGSCC____-NEXT: ret i32 [[CALL]]
;
%B = alloca i32, align 4
store i32 5, i32* %B, align 4
Expand All @@ -144,11 +158,18 @@ define i32 @visible_local_2() {
}

define internal i32 @noalias_args_argmem_rn(i32* %A, i32* %B) #1 {
; CHECK: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind willreturn uwtable
; CHECK-LABEL: define {{[^@]+}}@noalias_args_argmem_rn
; CHECK-SAME: (i32* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1:[0-9]+]] {
; CHECK-NEXT: [[T0:%.*]] = load i32, i32* [[B]], align 4
; CHECK-NEXT: ret i32 [[T0]]
; IS__TUNIT____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind willreturn uwtable
; IS__TUNIT____-LABEL: define {{[^@]+}}@noalias_args_argmem_rn
; IS__TUNIT____-SAME: (i32* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR1]] {
; IS__TUNIT____-NEXT: [[T0:%.*]] = load i32, i32* [[B]], align 4
; IS__TUNIT____-NEXT: ret i32 [[T0]]
;
; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind willreturn uwtable
; IS__CGSCC____-LABEL: define {{[^@]+}}@noalias_args_argmem_rn
; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[B:%.*]]) #[[ATTR4:[0-9]+]] {
; IS__CGSCC____-NEXT: [[T0:%.*]] = load i32, i32* [[B]], align 4
; IS__CGSCC____-NEXT: store i32 0, i32* [[B]], align 4
; IS__CGSCC____-NEXT: ret i32 [[T0]]
;
%t0 = load i32, i32* %B, align 4
store i32 0, i32* %B
Expand All @@ -164,12 +185,13 @@ define i32 @visible_local_3() {
; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[B]]) #[[ATTR4:[0-9]+]]
; IS__TUNIT____-NEXT: ret i32 [[CALL]]
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@visible_local_3
; IS__CGSCC____-SAME: () #[[ATTR3]] {
; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4
; IS__CGSCC____-NEXT: store i32 5, i32* [[B]], align 4
; IS__CGSCC____-NEXT: ret i32 5
; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree noundef nonnull align 4 dereferenceable(4) [[B]]) #[[ATTR7:[0-9]+]]
; IS__CGSCC____-NEXT: ret i32 [[CALL]]
;
%B = alloca i32, align 4
store i32 5, i32* %B, align 4
Expand All @@ -186,9 +208,12 @@ attributes #1 = { argmemonly noinline nounwind uwtable willreturn}
; IS__TUNIT____: attributes #[[ATTR3]] = { nofree nosync nounwind readonly }
; IS__TUNIT____: attributes #[[ATTR4]] = { nofree nosync nounwind willreturn }
;.
; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR1]] = { argmemonly nofree noinline norecurse nosync nounwind willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR2]] = { nofree noinline norecurse nosync nounwind readnone willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR4]] = { readonly }
; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree noinline nosync nounwind readonly willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR1]] = { argmemonly nofree noinline norecurse nosync nounwind readonly willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR2]] = { argmemonly nofree noinline nosync nounwind willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR3]] = { nofree nosync nounwind readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR4]] = { argmemonly nofree noinline norecurse nosync nounwind willreturn uwtable }
; IS__CGSCC____: attributes #[[ATTR5]] = { readonly }
; IS__CGSCC____: attributes #[[ATTR6]] = { readonly willreturn }
; IS__CGSCC____: attributes #[[ATTR7]] = { nounwind willreturn }
;.
50 changes: 31 additions & 19 deletions llvm/test/Transforms/Attributor/liveness.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2223,8 +2223,8 @@ define i32 @switch_default_caller() {
; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@switch_default_caller
; IS__CGSCC____-SAME: () #[[ATTR12]] {
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = tail call i32 @switch_default() #[[ATTR15]]
; IS__CGSCC____-NEXT: ret i32 123
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = tail call noundef i32 @switch_default() #[[ATTR15]]
; IS__CGSCC____-NEXT: ret i32 [[CALL2]]
;
%call2 = tail call i32 @switch_default(i64 0)
ret i32 %call2
Expand Down Expand Up @@ -2263,10 +2263,11 @@ define i32 @switch_default_dead_caller() {
; NOT_CGSCC_NPM-SAME: () #[[ATTR11:[0-9]+]] {
; NOT_CGSCC_NPM-NEXT: ret i32 123
;
; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn
; IS__CGSCC____-LABEL: define {{[^@]+}}@switch_default_dead_caller
; IS__CGSCC____-SAME: () #[[ATTR6]] {
; IS__CGSCC____-NEXT: ret i32 123
; IS__CGSCC____-SAME: () #[[ATTR11]] {
; IS__CGSCC____-NEXT: [[CALL2:%.*]] = tail call noundef i32 @switch_default_dead() #[[ATTR16:[0-9]+]]
; IS__CGSCC____-NEXT: ret i32 [[CALL2]]
;
%call2 = tail call i32 @switch_default_dead(i64 0)
ret i32 %call2
Expand All @@ -2283,19 +2284,29 @@ define void @call_via_pointer_with_dead_args(i32* %a, i32* %b, void (i32*, i32*,
}

define internal void @call_via_pointer_with_dead_args_internal_a(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
; CHECK-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
; CHECK-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
; CHECK-NEXT: call void poison(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; CHECK-NEXT: ret void
; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
; NOT_CGSCC_NPM-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
; NOT_CGSCC_NPM-NEXT: call void poison(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; NOT_CGSCC_NPM-NEXT: ret void
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_a
; IS__CGSCC____-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull [[FP:%.*]]) {
; IS__CGSCC____-NEXT: call void [[FP]](i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; IS__CGSCC____-NEXT: ret void
;
call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
ret void
}
define internal void @call_via_pointer_with_dead_args_internal_b(i32* %a, i32* %b, void (i32*, i32*, i32*, i64, i32**)* %fp) {
; CHECK-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
; CHECK-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
; CHECK-NEXT: call void poison(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; CHECK-NEXT: ret void
; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
; NOT_CGSCC_NPM-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]]) {
; NOT_CGSCC_NPM-NEXT: call void poison(i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; NOT_CGSCC_NPM-NEXT: ret void
;
; IS__CGSCC____-LABEL: define {{[^@]+}}@call_via_pointer_with_dead_args_internal_b
; IS__CGSCC____-SAME: (i32* [[A:%.*]], i32* noundef nonnull align 128 dereferenceable(4) [[B:%.*]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull [[FP:%.*]]) {
; IS__CGSCC____-NEXT: call void [[FP]](i32* [[A]], i32* nonnull align 128 dereferenceable(4) [[B]], i32* [[A]], i64 -1, i32** null)
; IS__CGSCC____-NEXT: ret void
;
call void %fp(i32* %a, i32* %b, i32* %a, i64 -1, i32** null)
ret void
Expand All @@ -2321,8 +2332,8 @@ define void @call_via_pointer_with_dead_args_caller(i32* %a, i32* %b) {
; IS__CGSCC____-NEXT: [[PTR4:%.*]] = alloca i32, align 128
; IS__CGSCC____-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR1]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull @called_via_pointer)
; IS__CGSCC____-NEXT: call void @call_via_pointer_with_dead_args(i32* [[A]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR2]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull @called_via_pointer_internal_1)
; IS__CGSCC____-NEXT: call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR3]])
; IS__CGSCC____-NEXT: call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR4]])
; IS__CGSCC____-NEXT: call void @call_via_pointer_with_dead_args_internal_a(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR3]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull @called_via_pointer)
; IS__CGSCC____-NEXT: call void @call_via_pointer_with_dead_args_internal_b(i32* [[B]], i32* noundef nonnull align 128 dereferenceable(4) [[PTR4]], void (i32*, i32*, i32*, i64, i32**)* nocapture nofree noundef nonnull @called_via_pointer_internal_2)
; IS__CGSCC____-NEXT: ret void
;
%ptr1 = alloca i32, align 128
Expand Down Expand Up @@ -2364,7 +2375,7 @@ entry:
; FIXME: Figure out why the MODULE has the unused arguments still
define internal void @called_via_pointer_internal_2(i32* %a, i32* %b, i32* %c, i64 %d, i32** %e) {
; IS__CGSCC____-LABEL: define {{[^@]+}}@called_via_pointer_internal_2
; IS__CGSCC____-SAME: (i32* [[A:%.*]], i32* [[B:%.*]], i32* [[C:%.*]], i64 [[D:%.*]], i32** [[E:%.*]]) {
; IS__CGSCC____-SAME: (i32* [[A:%.*]], i32* nocapture nofree readnone [[B:%.*]], i32* nocapture nofree readnone [[C:%.*]], i64 [[D:%.*]], i32** nocapture nofree readnone [[E:%.*]]) {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: tail call void @use_i32p(i32* [[A]])
; IS__CGSCC____-NEXT: tail call void @use_i32p(i32* [[A]])
Expand Down Expand Up @@ -2575,7 +2586,7 @@ define void @bad_gep() {
; IS__CGSCC____-NEXT: entry:
; IS__CGSCC____-NEXT: [[N:%.*]] = alloca i8, align 1
; IS__CGSCC____-NEXT: [[M:%.*]] = alloca i8, align 1
; IS__CGSCC____-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR16:[0-9]+]]
; IS__CGSCC____-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR17:[0-9]+]]
; IS__CGSCC____-NEXT: br label [[EXIT:%.*]]
; IS__CGSCC____: while.body:
; IS__CGSCC____-NEXT: unreachable
Expand All @@ -2584,7 +2595,7 @@ define void @bad_gep() {
; IS__CGSCC____: if.end:
; IS__CGSCC____-NEXT: unreachable
; IS__CGSCC____: exit:
; IS__CGSCC____-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR16]]
; IS__CGSCC____-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 1, i8* noalias nocapture nofree noundef nonnull dereferenceable(1) [[N]]) #[[ATTR17]]
; IS__CGSCC____-NEXT: ret void
;
entry:
Expand Down Expand Up @@ -2682,5 +2693,6 @@ declare void @llvm.lifetime.end.p0i8(i64 %0, i8* %1)
; IS__CGSCC____: attributes #[[ATTR13]] = { nounwind readonly }
; IS__CGSCC____: attributes #[[ATTR14:[0-9]+]] = { argmemonly nocallback nofree nosync nounwind willreturn }
; IS__CGSCC____: attributes #[[ATTR15]] = { nounwind willreturn }
; IS__CGSCC____: attributes #[[ATTR16]] = { willreturn }
; IS__CGSCC____: attributes #[[ATTR16]] = { readnone willreturn }
; IS__CGSCC____: attributes #[[ATTR17]] = { willreturn }
;.
Loading