xref: /llvm-project/llvm/test/Transforms/Inline/nonnull.ll (revision 4d51c6258e8391738e5c002b36de3b5538d31b8c)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -S -passes=inline %s | FileCheck %s
3; RUN: opt -S -passes='cgscc(inline)' %s | FileCheck %s
4; RUN: opt -S -passes='module-inline' %s | FileCheck %s
5
6declare void @foo()
7declare void @bar()
8
9define void @callee(ptr %arg) {
10; CHECK-LABEL: define void @callee
11; CHECK-SAME: (ptr [[ARG:%.*]]) {
12; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[ARG]], null
13; CHECK-NEXT:    br i1 [[CMP]], label [[EXPENSIVE:%.*]], label [[DONE:%.*]]
14; CHECK:       expensive:
15; CHECK-NEXT:    call void @foo()
16; CHECK-NEXT:    call void @foo()
17; CHECK-NEXT:    call void @foo()
18; CHECK-NEXT:    call void @foo()
19; CHECK-NEXT:    call void @foo()
20; CHECK-NEXT:    call void @foo()
21; CHECK-NEXT:    call void @foo()
22; CHECK-NEXT:    call void @foo()
23; CHECK-NEXT:    call void @foo()
24; CHECK-NEXT:    call void @foo()
25; CHECK-NEXT:    ret void
26; CHECK:       done:
27; CHECK-NEXT:    call void @bar()
28; CHECK-NEXT:    ret void
29;
30  %cmp = icmp eq ptr %arg, null
31  br i1 %cmp, label %expensive, label %done
32
33; This block is designed to be too expensive to inline.  We can only inline
34; callee if this block is known to be dead.
35expensive:
36  call void @foo()
37  call void @foo()
38  call void @foo()
39  call void @foo()
40  call void @foo()
41  call void @foo()
42  call void @foo()
43  call void @foo()
44  call void @foo()
45  call void @foo()
46  ret void
47
48done:
49  call void @bar()
50  ret void
51}
52
53; Positive test - arg is known non null
54define void @caller(ptr nonnull %arg) {
55; CHECK-LABEL: define void @caller
56; CHECK-SAME: (ptr nonnull [[ARG:%.*]]) {
57; CHECK-NEXT:    call void @bar()
58; CHECK-NEXT:    ret void
59;
60  call void @callee(ptr nonnull %arg)
61  ret void
62}
63
64; Negative test - arg is not known to be non null
65define void @caller2(ptr %arg) {
66; CHECK-LABEL: define void @caller2
67; CHECK-SAME: (ptr [[ARG:%.*]]) {
68; CHECK-NEXT:    call void @callee(ptr [[ARG]])
69; CHECK-NEXT:    ret void
70;
71  call void @callee(ptr %arg)
72  ret void
73}
74
75define void @caller3(ptr %arg) {
76; CHECK-LABEL: define void @caller3
77; CHECK-SAME: (ptr [[ARG:%.*]]) {
78; CHECK-NEXT:    [[CMP_I:%.*]] = icmp eq ptr [[ARG]], null
79; CHECK-NEXT:    br i1 [[CMP_I]], label [[EXPENSIVE_I:%.*]], label [[DONE_I:%.*]]
80; CHECK:       expensive.i:
81; CHECK-NEXT:    call void @foo()
82; CHECK-NEXT:    call void @foo()
83; CHECK-NEXT:    call void @foo()
84; CHECK-NEXT:    call void @foo()
85; CHECK-NEXT:    call void @foo()
86; CHECK-NEXT:    call void @foo()
87; CHECK-NEXT:    call void @foo()
88; CHECK-NEXT:    call void @foo()
89; CHECK-NEXT:    call void @foo()
90; CHECK-NEXT:    call void @foo()
91; CHECK-NEXT:    br label [[CALLEE_EXIT:%.*]]
92; CHECK:       done.i:
93; CHECK-NEXT:    call void @bar()
94; CHECK-NEXT:    br label [[CALLEE_EXIT]]
95; CHECK:       callee.exit:
96; CHECK-NEXT:    ret void
97;
98  call void @callee(ptr nonnull %arg)
99  ret void
100}
101
102define void @caller4(ptr dereferenceable(8) %arg) {
103; CHECK-LABEL: define void @caller4
104; CHECK-SAME: (ptr dereferenceable(8) [[ARG:%.*]]) {
105; CHECK-NEXT:    call void @callee(ptr dereferenceable(8) [[ARG]])
106; CHECK-NEXT:    ret void
107;
108  call void @callee(ptr dereferenceable(8) %arg)
109  ret void
110}
111
112define void @caller5(ptr dereferenceable(8) %arg) {
113; CHECK-LABEL: define void @caller5
114; CHECK-SAME: (ptr dereferenceable(8) [[ARG:%.*]]) {
115; CHECK-NEXT:    call void @callee(ptr [[ARG]])
116; CHECK-NEXT:    ret void
117;
118  call void @callee(ptr %arg)
119  ret void
120}
121
122define void @caller6(ptr %arg) {
123; CHECK-LABEL: define void @caller6
124; CHECK-SAME: (ptr [[ARG:%.*]]) {
125; CHECK-NEXT:    call void @callee(ptr dereferenceable(8) [[ARG]])
126; CHECK-NEXT:    ret void
127;
128  call void @callee(ptr dereferenceable(8) %arg)
129  ret void
130}
131
132declare ptr @buz()
133define nonnull ptr @callee7() {
134; CHECK-LABEL: define nonnull ptr @callee7() {
135; CHECK-NEXT:    [[R:%.*]] = call ptr @buz() #[[ATTR0:[0-9]+]]
136; CHECK-NEXT:    ret ptr [[R]]
137;
138  %r = call ptr @buz() willreturn nounwind
139  ret ptr %r
140}
141
142define ptr @caller7() {
143; CHECK-LABEL: define ptr @caller7() {
144; CHECK-NEXT:    [[R_I:%.*]] = call nonnull ptr @buz() #[[ATTR0]]
145; CHECK-NEXT:    ret ptr [[R_I]]
146;
147  %r = call ptr @callee7()
148  ret ptr %r
149}
150
151define nonnull ptr @callee8() {
152; CHECK-LABEL: define nonnull ptr @callee8() {
153; CHECK-NEXT:    [[R:%.*]] = call ptr @buz()
154; CHECK-NEXT:    ret ptr [[R]]
155;
156  %r = call ptr @buz()
157  ret ptr %r
158}
159
160define ptr @caller8() {
161; CHECK-LABEL: define ptr @caller8() {
162; CHECK-NEXT:    [[R_I:%.*]] = call nonnull ptr @buz()
163; CHECK-NEXT:    ret ptr [[R_I]]
164;
165  %r = call nonnull ptr @callee8()
166  ret ptr %r
167}
168
169define ptr @callee9() {
170; CHECK-LABEL: define ptr @callee9() {
171; CHECK-NEXT:    [[R:%.*]] = call ptr @buz()
172; CHECK-NEXT:    call void @foo() #[[ATTR1:[0-9]+]]
173; CHECK-NEXT:    ret ptr [[R]]
174;
175  %r = call ptr @buz()
176  call void @foo() nounwind
177  ret ptr %r
178}
179
180define ptr @caller9() {
181; CHECK-LABEL: define ptr @caller9() {
182; CHECK-NEXT:    [[R_I:%.*]] = call ptr @buz()
183; CHECK-NEXT:    call void @foo() #[[ATTR1]]
184; CHECK-NEXT:    ret ptr [[R_I]]
185;
186  %r = call nonnull ptr @callee9()
187  ret ptr %r
188}
189