1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC 4; 5; 6; /---------------------------------------| 7; | /----------------------|----| 8; | | /-----| | 9; V V V | | 10; void broker(int (*cb0)(int), int (*cb1)(int), int (*cb2)(int), int, int); 11; 12; static int cb0(int zero) { 13; return zero; 14; } 15; static int cb1(int unknown) { 16; return unknown; 17; } 18; static int cb2(int unknown) { 19; cb0(0); 20; return unknown; 21; } 22; static int cb3(int unknown) { 23; return unknown; 24; } 25; static int cb4(int unknown) { 26; return unknown; 27; } 28; 29; void foo() { 30; cb0(0); 31; cb3(1); 32; broker(cb0, cb1, cb0, 0, 1); 33; broker(cb1, cb2, cb2, 0, 1); 34; broker(cb3, cb2, cb3, 0, 1); 35; broker(cb4, cb4, cb4, 0, 1); 36; } 37; 38target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 39 40define internal i32 @cb0(i32 %zero) { 41; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 42; CHECK-LABEL: define {{[^@]+}}@cb0 43; CHECK-SAME: (i32 [[ZERO:%.*]]) #[[ATTR0:[0-9]+]] { 44; CHECK-NEXT: entry: 45; CHECK-NEXT: ret i32 0 46; 47entry: 48 ret i32 %zero 49} 50 51define internal i32 @cb1(i32 %unknown) { 52; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 53; CHECK-LABEL: define {{[^@]+}}@cb1 54; CHECK-SAME: (i32 noundef [[UNKNOWN:%.*]]) #[[ATTR0]] { 55; CHECK-NEXT: entry: 56; CHECK-NEXT: ret i32 [[UNKNOWN]] 57; 58entry: 59 ret i32 %unknown 60} 61 62define internal i32 @cb2(i32 %unknown) { 63; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 64; TUNIT-LABEL: define {{[^@]+}}@cb2 65; TUNIT-SAME: (i32 noundef [[UNKNOWN:%.*]]) #[[ATTR0]] { 66; TUNIT-NEXT: entry: 67; TUNIT-NEXT: ret i32 [[UNKNOWN]] 68; 69; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) 70; CGSCC-LABEL: define {{[^@]+}}@cb2 71; CGSCC-SAME: (i32 noundef [[UNKNOWN:%.*]]) #[[ATTR1:[0-9]+]] { 72; CGSCC-NEXT: entry: 73; CGSCC-NEXT: ret i32 [[UNKNOWN]] 74; 75entry: 76 %call = call i32 @cb0(i32 0) 77 ret i32 %unknown 78} 79 80define internal i32 @cb3(i32 %unknown) { 81; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 82; CHECK-LABEL: define {{[^@]+}}@cb3 83; CHECK-SAME: (i32 noundef [[UNKNOWN:%.*]]) #[[ATTR0]] { 84; CHECK-NEXT: entry: 85; CHECK-NEXT: ret i32 [[UNKNOWN]] 86; 87entry: 88 ret i32 %unknown 89} 90 91define internal i32 @cb4(i32 %unknown) { 92; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) 93; CHECK-LABEL: define {{[^@]+}}@cb4 94; CHECK-SAME: (i32 noundef [[UNKNOWN:%.*]]) #[[ATTR0]] { 95; CHECK-NEXT: entry: 96; CHECK-NEXT: ret i32 [[UNKNOWN]] 97; 98entry: 99 ret i32 %unknown 100} 101 102define void @foo() { 103; CHECK-LABEL: define {{[^@]+}}@foo() { 104; CHECK-NEXT: entry: 105; CHECK-NEXT: call void @broker(ptr noundef nonnull @cb0, ptr noundef nonnull @cb1, ptr noundef nonnull @cb0, i32 noundef 0, i32 noundef 1) 106; CHECK-NEXT: call void @broker(ptr noundef nonnull @cb1, ptr noundef nonnull @cb2, ptr noundef nonnull @cb2, i32 noundef 0, i32 noundef 1) 107; CHECK-NEXT: call void @broker(ptr noundef nonnull @cb3, ptr noundef nonnull @cb2, ptr noundef nonnull @cb3, i32 noundef 0, i32 noundef 1) 108; CHECK-NEXT: call void @broker(ptr noundef nonnull @cb4, ptr noundef nonnull @cb4, ptr noundef nonnull @cb4, i32 noundef 0, i32 noundef 1) 109; CHECK-NEXT: ret void 110; 111entry: 112 %call = call i32 @cb0(i32 0) 113 %call1 = call i32 @cb3(i32 1) 114 call void @broker(ptr nonnull @cb0, ptr nonnull @cb1, ptr nonnull @cb0, i32 0, i32 1) 115 call void @broker(ptr nonnull @cb1, ptr nonnull @cb2, ptr nonnull @cb2, i32 0, i32 1) 116 call void @broker(ptr nonnull @cb3, ptr nonnull @cb2, ptr nonnull @cb3, i32 0, i32 1) 117 call void @broker(ptr nonnull @cb4, ptr nonnull @cb4, ptr nonnull @cb4, i32 0, i32 1) 118 ret void 119} 120 121declare !callback !3 void @broker(ptr, ptr, ptr, i32, i32) 122 123!0 = !{i64 0, i64 3, i1 false} 124!1 = !{i64 1, i64 4, i1 false} 125!2 = !{i64 2, i64 3, i1 false} 126!3 = !{!0, !2, !1} 127;. 128; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 129;. 130; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } 131; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(none) } 132;. 133; TUNIT: [[META0:![0-9]+]] = !{[[META1:![0-9]+]], [[META2:![0-9]+]], [[META3:![0-9]+]]} 134; TUNIT: [[META1]] = !{i64 0, i64 3, i1 false} 135; TUNIT: [[META2]] = !{i64 2, i64 3, i1 false} 136; TUNIT: [[META3]] = !{i64 1, i64 4, i1 false} 137;. 138; CGSCC: [[META0:![0-9]+]] = !{[[META1:![0-9]+]], [[META2:![0-9]+]], [[META3:![0-9]+]]} 139; CGSCC: [[META1]] = !{i64 0, i64 3, i1 false} 140; CGSCC: [[META2]] = !{i64 2, i64 3, i1 false} 141; CGSCC: [[META3]] = !{i64 1, i64 4, i1 false} 142;. 143