xref: /llvm-project/llvm/test/Transforms/Attributor/alwaysinline.ll (revision 7d16a35c83d239a8fba44bdff9ffadcc32bb524b)
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; When a function is marked `alwaysinline` and is able to be inlined,
6; we can IPO its boundaries
7
8; the function is not exactly defined, and marked alwaysinline and can be inlined,
9; so the function can be analyzed
10define linkonce void @inner1() alwaysinline {
11; CHECK: Function Attrs: alwaysinline mustprogress nofree norecurse nosync nounwind willreturn memory(none)
12; CHECK-LABEL: define {{[^@]+}}@inner1
13; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
14; CHECK-NEXT:  entry:
15; CHECK-NEXT:    ret void
16;
17entry:
18  ret void
19}
20
21define void @outer1() {
22; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
23; TUNIT-LABEL: define {{[^@]+}}@outer1
24; TUNIT-SAME: () #[[ATTR1:[0-9]+]] {
25; TUNIT-NEXT:  entry:
26; TUNIT-NEXT:    ret void
27;
28; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
29; CGSCC-LABEL: define {{[^@]+}}@outer1
30; CGSCC-SAME: () #[[ATTR1:[0-9]+]] {
31; CGSCC-NEXT:  entry:
32; CGSCC-NEXT:    ret void
33;
34entry:
35  call void @inner1()
36  ret void
37}
38
39; The function is not alwaysinline and is not exactly defined
40; so it will not be analyzed
41define linkonce i32 @inner2() {
42; CHECK-LABEL: define {{[^@]+}}@inner2() {
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    ret i32 1
45;
46entry:
47  ret i32 1
48}
49
50; CHECK-NOT: Function Attrs
51define i32 @outer2() {
52; CHECK-LABEL: define {{[^@]+}}@outer2() {
53; CHECK-NEXT:  entry:
54; CHECK-NEXT:    [[R:%.*]] = call i32 @inner2() #[[ATTR2:[0-9]+]]
55; CHECK-NEXT:    ret i32 [[R]]
56;
57entry:
58  %r = call i32 @inner2() alwaysinline
59  ret i32 %r
60}
61
62; This function cannot be inlined although it is marked alwaysinline
63; it is `unexactly defined` and alwaysinline but cannot be inlined.
64; so it will not be analyzed
65define linkonce i32 @inner3(ptr %addr) alwaysinline {
66; CHECK: Function Attrs: alwaysinline
67; CHECK-LABEL: define {{[^@]+}}@inner3
68; CHECK-SAME: (ptr [[ADDR:%.*]]) #[[ATTR2]] {
69; CHECK-NEXT:  entry:
70; CHECK-NEXT:    indirectbr ptr [[ADDR]], [label [[ONE:%.*]], label %two]
71; CHECK:       one:
72; CHECK-NEXT:    ret i32 42
73; CHECK:       two:
74; CHECK-NEXT:    ret i32 44
75;
76entry:
77  indirectbr ptr %addr, [ label %one, label %two ]
78
79one:
80  ret i32 42
81
82two:
83  ret i32 44
84}
85
86define i32 @outer3(i32 %x) {
87; CHECK-LABEL: define {{[^@]+}}@outer3
88; CHECK-SAME: (i32 [[X:%.*]]) {
89; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X]], 42
90; CHECK-NEXT:    [[ADDR:%.*]] = select i1 [[CMP]], ptr blockaddress(@inner3, [[ONE:%.*]]), ptr blockaddress(@inner3, [[TWO:%.*]])
91; CHECK-NEXT:    [[CALL:%.*]] = call i32 @inner3(ptr [[ADDR]])
92; CHECK-NEXT:    ret i32 [[CALL]]
93;
94  %cmp = icmp slt i32 %x, 42
95  %addr = select i1 %cmp, ptr blockaddress(@inner3, %one), ptr blockaddress(@inner3, %two)
96  %call = call i32 @inner3(ptr %addr)
97  ret i32 %call
98}
99;.
100; TUNIT: attributes #[[ATTR0]] = { alwaysinline mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
101; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
102; TUNIT: attributes #[[ATTR2]] = { alwaysinline }
103;.
104; CGSCC: attributes #[[ATTR0]] = { alwaysinline mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
105; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
106; CGSCC: attributes #[[ATTR2]] = { alwaysinline }
107;.
108