1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals 2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM 3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM 4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM 5; 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 6; 7; When a function is marked `alwaysinline` and is able to be inlined, 8; we can IPO its boundaries 9 10; the function is not exactly defined, and marked alwaysinline and can be inlined, 11; so the function can be analyzed 12define linkonce void @inner1() alwaysinline { 13; CHECK: Function Attrs: alwaysinline nofree norecurse nosync nounwind readnone willreturn 14; CHECK-LABEL: define {{[^@]+}}@inner1 15; CHECK-SAME: () #[[ATTR0:[0-9]+]] { 16; CHECK-NEXT: entry: 17; CHECK-NEXT: ret void 18; 19entry: 20 ret void 21} 22 23define void @outer1() { 24; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn 25; IS__TUNIT____-LABEL: define {{[^@]+}}@outer1 26; IS__TUNIT____-SAME: () #[[ATTR1:[0-9]+]] { 27; IS__TUNIT____-NEXT: entry: 28; IS__TUNIT____-NEXT: ret void 29; 30; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone willreturn 31; IS__CGSCC____-LABEL: define {{[^@]+}}@outer1 32; IS__CGSCC____-SAME: () #[[ATTR1:[0-9]+]] { 33; IS__CGSCC____-NEXT: entry: 34; IS__CGSCC____-NEXT: ret void 35; 36entry: 37 call void @inner1() 38 ret void 39} 40 41; The function is not alwaysinline and is not exactly defined 42; so it will not be analyzed 43define linkonce i32 @inner2() { 44; CHECK-LABEL: define {{[^@]+}}@inner2() { 45; CHECK-NEXT: entry: 46; CHECK-NEXT: ret i32 1 47; 48entry: 49 ret i32 1 50} 51 52; CHECK-NOT: Function Attrs 53define i32 @outer2() { 54; IS__TUNIT____: Function Attrs: norecurse 55; IS__TUNIT____-LABEL: define {{[^@]+}}@outer2 56; IS__TUNIT____-SAME: () #[[ATTR2:[0-9]+]] { 57; IS__TUNIT____-NEXT: entry: 58; IS__TUNIT____-NEXT: [[R:%.*]] = call i32 @inner2() #[[ATTR3:[0-9]+]] 59; IS__TUNIT____-NEXT: ret i32 [[R]] 60; 61; IS__CGSCC____-LABEL: define {{[^@]+}}@outer2() { 62; IS__CGSCC____-NEXT: entry: 63; IS__CGSCC____-NEXT: [[R:%.*]] = call i32 @inner2() #[[ATTR2:[0-9]+]] 64; IS__CGSCC____-NEXT: ret i32 [[R]] 65; 66entry: 67 %r = call i32 @inner2() alwaysinline 68 ret i32 %r 69} 70 71; This function cannot be inlined although it is marked alwaysinline 72; it is `unexactly defined` and alwaysinline but cannot be inlined. 73; so it will not be analyzed 74define linkonce i32 @inner3(i8* %addr) alwaysinline { 75; IS__TUNIT____: Function Attrs: alwaysinline 76; IS__TUNIT____-LABEL: define {{[^@]+}}@inner3 77; IS__TUNIT____-SAME: (i8* [[ADDR:%.*]]) #[[ATTR3]] { 78; IS__TUNIT____-NEXT: entry: 79; IS__TUNIT____-NEXT: indirectbr i8* [[ADDR]], [label [[ONE:%.*]], label %two] 80; IS__TUNIT____: one: 81; IS__TUNIT____-NEXT: ret i32 42 82; IS__TUNIT____: two: 83; IS__TUNIT____-NEXT: ret i32 44 84; 85; IS__CGSCC____: Function Attrs: alwaysinline 86; IS__CGSCC____-LABEL: define {{[^@]+}}@inner3 87; IS__CGSCC____-SAME: (i8* [[ADDR:%.*]]) #[[ATTR2]] { 88; IS__CGSCC____-NEXT: entry: 89; IS__CGSCC____-NEXT: indirectbr i8* [[ADDR]], [label [[ONE:%.*]], label %two] 90; IS__CGSCC____: one: 91; IS__CGSCC____-NEXT: ret i32 42 92; IS__CGSCC____: two: 93; IS__CGSCC____-NEXT: ret i32 44 94; 95entry: 96 indirectbr i8* %addr, [ label %one, label %two ] 97 98one: 99 ret i32 42 100 101two: 102 ret i32 44 103} 104 105define i32 @outer3(i32 %x) { 106; IS__TUNIT____: Function Attrs: norecurse 107; IS__TUNIT____-LABEL: define {{[^@]+}}@outer3 108; IS__TUNIT____-SAME: (i32 [[X:%.*]]) #[[ATTR2]] { 109; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 42 110; IS__TUNIT____-NEXT: [[ADDR:%.*]] = select i1 [[CMP]], i8* blockaddress(@inner3, [[ONE:%.*]]), i8* blockaddress(@inner3, [[TWO:%.*]]) 111; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @inner3(i8* [[ADDR]]) 112; IS__TUNIT____-NEXT: ret i32 [[CALL]] 113; 114; IS__CGSCC____-LABEL: define {{[^@]+}}@outer3 115; IS__CGSCC____-SAME: (i32 [[X:%.*]]) { 116; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 42 117; IS__CGSCC____-NEXT: [[ADDR:%.*]] = select i1 [[CMP]], i8* blockaddress(@inner3, [[ONE:%.*]]), i8* blockaddress(@inner3, [[TWO:%.*]]) 118; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @inner3(i8* [[ADDR]]) 119; IS__CGSCC____-NEXT: ret i32 [[CALL]] 120; 121 %cmp = icmp slt i32 %x, 42 122 %addr = select i1 %cmp, i8* blockaddress(@inner3, %one), i8* blockaddress(@inner3, %two) 123 %call = call i32 @inner3(i8* %addr) 124 ret i32 %call 125} 126;. 127; IS__TUNIT____: attributes #[[ATTR0]] = { alwaysinline nofree norecurse nosync nounwind readnone willreturn } 128; IS__TUNIT____: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone willreturn } 129; IS__TUNIT____: attributes #[[ATTR2]] = { norecurse } 130; IS__TUNIT____: attributes #[[ATTR3]] = { alwaysinline } 131;. 132; IS__CGSCC____: attributes #[[ATTR0]] = { alwaysinline nofree norecurse nosync nounwind readnone willreturn } 133; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone willreturn } 134; IS__CGSCC____: attributes #[[ATTR2]] = { alwaysinline } 135;. 136