[Frontend] Remove unused includes (NFC) (#116927)
[llvm-project.git] / llvm / test / Analysis / GlobalsModRef / noescape-nocapture-nocallback.ll
blob042bfe34c1261702fb0243283c5dc1a791d07892
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -aa-pipeline=basic-aa,globals-aa -S -passes='require<globals-aa>,function(loop-mssa(licm))' | FileCheck %s
4 ;Reference C code:
5 ;struct str {
6 ;  void **p;
7 ;};
8 ;static struct str obj;
9 ;extern void nocapture_nocallback_func(struct str *);
10 ;void test(void *p) {
11 ;  nocapture_nocallback_func(&obj);
12 ;  for (int i = 0; i < 1000; ++i) {
13 ;    unknown_call(); // optional
14 ;    obj.p[i] = p;
15 ;  }
18 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
20 %struct.str = type { ptr }
22 @obj0 = internal global %struct.str zeroinitializer, align 8
23 @obj1 = internal global %struct.str zeroinitializer, align 8
24 @obj2 = internal global %struct.str zeroinitializer, align 8
25 @obj3 = internal global %struct.str zeroinitializer, align 8
26 @obj4 = internal global %struct.str zeroinitializer, align 8
27 @obj5 = internal global %struct.str zeroinitializer, align 8
29 define dso_local void @test0(ptr %p) {
30 ; Check that load from @obj0 is hoisted from the loop, meaning
31 ; that it does not conflict with the store inside the loop:
32 ; CHECK-LABEL: @test0(
33 ; CHECK-NEXT:  entry:
34 ; CHECK-NEXT:    call void @nocapture_nocallback_func(ptr @obj0)
35 ; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr @obj0, align 8
36 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
37 ; CHECK:       for.cond:
38 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
39 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000
40 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
41 ; CHECK:       for.body:
42 ; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
43 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]
44 ; CHECK-NEXT:    store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8
45 ; CHECK-NEXT:    br label [[FOR_INC]]
46 ; CHECK:       for.inc:
47 ; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_0]], 1
48 ; CHECK-NEXT:    br label [[FOR_COND]]
49 ; CHECK:       for.end:
50 ; CHECK-NEXT:    ret void
53 entry:
54   call void @nocapture_nocallback_func(ptr @obj0)
55   br label %for.cond
57 for.cond:                                         ; preds = %for.inc, %entry
58   %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
59   %cmp = icmp slt i32 %i.0, 1000
60   br i1 %cmp, label %for.body, label %for.end
62 for.body:                                         ; preds = %for.cond
63   %0 = load ptr, ptr @obj0, align 8
64   %idxprom = sext i32 %i.0 to i64
65   %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom
66   store ptr %p, ptr %arrayidx, align 8
67   br label %for.inc
69 for.inc:                                          ; preds = %for.body
70   %inc = add nsw i32 %i.0, 1
71   br label %for.cond
73 for.end:                                          ; preds = %for.cond
74   ret void
77 define dso_local void @test1(ptr %p) {
78 ; Check that load from @obj1 is not hoisted from the loop,
79 ; because 'nocallback' is missing:
80 ; CHECK-LABEL: @test1(
81 ; CHECK-NEXT:  entry:
82 ; CHECK-NEXT:    call void @nocapture_func(ptr @obj1)
83 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
84 ; CHECK:       for.cond:
85 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
86 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000
87 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
88 ; CHECK:       for.body:
89 ; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr @obj1, align 8
90 ; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
91 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]
92 ; CHECK-NEXT:    store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8
93 ; CHECK-NEXT:    br label [[FOR_INC]]
94 ; CHECK:       for.inc:
95 ; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_0]], 1
96 ; CHECK-NEXT:    br label [[FOR_COND]]
97 ; CHECK:       for.end:
98 ; CHECK-NEXT:    ret void
101 entry:
102   call void @nocapture_func(ptr @obj1)
103   br label %for.cond
105 for.cond:                                         ; preds = %for.inc, %entry
106   %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
107   %cmp = icmp slt i32 %i.0, 1000
108   br i1 %cmp, label %for.body, label %for.end
110 for.body:                                         ; preds = %for.cond
111   %0 = load ptr, ptr @obj1, align 8
112   %idxprom = sext i32 %i.0 to i64
113   %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom
114   store ptr %p, ptr %arrayidx, align 8
115   br label %for.inc
117 for.inc:                                          ; preds = %for.body
118   %inc = add nsw i32 %i.0, 1
119   br label %for.cond
121 for.end:                                          ; preds = %for.cond
122   ret void
125 define dso_local void @test2(ptr %p) {
126 ; Check that load from @obj2 is not hoisted from the loop,
127 ; because 'nocapture' is missing:
128 ; CHECK-LABEL: @test2(
129 ; CHECK-NEXT:  entry:
130 ; CHECK-NEXT:    call void @nocallback_func(ptr @obj2)
131 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
132 ; CHECK:       for.cond:
133 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
134 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000
135 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
136 ; CHECK:       for.body:
137 ; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr @obj2, align 8
138 ; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
139 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]
140 ; CHECK-NEXT:    store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8
141 ; CHECK-NEXT:    br label [[FOR_INC]]
142 ; CHECK:       for.inc:
143 ; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_0]], 1
144 ; CHECK-NEXT:    br label [[FOR_COND]]
145 ; CHECK:       for.end:
146 ; CHECK-NEXT:    ret void
149 entry:
150   call void @nocallback_func(ptr @obj2)
151   br label %for.cond
153 for.cond:                                         ; preds = %for.inc, %entry
154   %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
155   %cmp = icmp slt i32 %i.0, 1000
156   br i1 %cmp, label %for.body, label %for.end
158 for.body:                                         ; preds = %for.cond
159   %0 = load ptr, ptr @obj2, align 8
160   %idxprom = sext i32 %i.0 to i64
161   %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom
162   store ptr %p, ptr %arrayidx, align 8
163   br label %for.inc
165 for.inc:                                          ; preds = %for.body
166   %inc = add nsw i32 %i.0, 1
167   br label %for.cond
169 for.end:                                          ; preds = %for.cond
170   ret void
173 define dso_local void @test3(ptr %p) {
174 ; Check that load from @obj3 is hoisted from the loop, even though
175 ; there is unknown call in the loop.
176 ; CHECK-LABEL: @test3(
177 ; CHECK-NEXT:  entry:
178 ; CHECK-NEXT:    call void @nocapture_nocallback_func(ptr @obj3)
179 ; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr @obj3, align 8
180 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
181 ; CHECK:       for.cond:
182 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
183 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000
184 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
185 ; CHECK:       for.body:
186 ; CHECK-NEXT:    call void @unknown_call()
187 ; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
188 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]
189 ; CHECK-NEXT:    store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8
190 ; CHECK-NEXT:    br label [[FOR_INC]]
191 ; CHECK:       for.inc:
192 ; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_0]], 1
193 ; CHECK-NEXT:    br label [[FOR_COND]]
194 ; CHECK:       for.end:
195 ; CHECK-NEXT:    ret void
198 entry:
199   call void @nocapture_nocallback_func(ptr @obj3)
200   br label %for.cond
202 for.cond:                                         ; preds = %for.inc, %entry
203   %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
204   %cmp = icmp slt i32 %i.0, 1000
205   br i1 %cmp, label %for.body, label %for.end
207 for.body:                                         ; preds = %for.cond
208   %0 = load ptr, ptr @obj3, align 8
209   call void @unknown_call()
210   %idxprom = sext i32 %i.0 to i64
211   %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom
212   store ptr %p, ptr %arrayidx, align 8
213   br label %for.inc
215 for.inc:                                          ; preds = %for.body
216   %inc = add nsw i32 %i.0, 1
217   br label %for.cond
219 for.end:                                          ; preds = %for.cond
220   ret void
223 define dso_local void @test4(ptr %p) {
224 ; Check that load from @obj4 is not hoisted from the loop,
225 ; because 'nocallback' is missing:
226 ; CHECK-LABEL: @test4(
227 ; CHECK-NEXT:  entry:
228 ; CHECK-NEXT:    call void @nocapture_func(ptr @obj4)
229 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
230 ; CHECK:       for.cond:
231 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
232 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000
233 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
234 ; CHECK:       for.body:
235 ; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr @obj4, align 8
236 ; CHECK-NEXT:    call void @unknown_call()
237 ; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
238 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]
239 ; CHECK-NEXT:    store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8
240 ; CHECK-NEXT:    br label [[FOR_INC]]
241 ; CHECK:       for.inc:
242 ; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_0]], 1
243 ; CHECK-NEXT:    br label [[FOR_COND]]
244 ; CHECK:       for.end:
245 ; CHECK-NEXT:    ret void
248 entry:
249   call void @nocapture_func(ptr @obj4)
250   br label %for.cond
252 for.cond:                                         ; preds = %for.inc, %entry
253   %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
254   %cmp = icmp slt i32 %i.0, 1000
255   br i1 %cmp, label %for.body, label %for.end
257 for.body:                                         ; preds = %for.cond
258   %0 = load ptr, ptr @obj4, align 8
259   call void @unknown_call()
260   %idxprom = sext i32 %i.0 to i64
261   %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom
262   store ptr %p, ptr %arrayidx, align 8
263   br label %for.inc
265 for.inc:                                          ; preds = %for.body
266   %inc = add nsw i32 %i.0, 1
267   br label %for.cond
269 for.end:                                          ; preds = %for.cond
270   ret void
273 define dso_local void @test5(ptr %p) {
274 ; Check that load from @obj5 is not hoisted from the loop,
275 ; because 'nocapture' is missing:
276 ; CHECK-LABEL: @test5(
277 ; CHECK-NEXT:  entry:
278 ; CHECK-NEXT:    call void @nocallback_func(ptr @obj5)
279 ; CHECK-NEXT:    br label [[FOR_COND:%.*]]
280 ; CHECK:       for.cond:
281 ; CHECK-NEXT:    [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]
282 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000
283 ; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
284 ; CHECK:       for.body:
285 ; CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr @obj5, align 8
286 ; CHECK-NEXT:    call void @unknown_call()
287 ; CHECK-NEXT:    [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64
288 ; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]
289 ; CHECK-NEXT:    store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8
290 ; CHECK-NEXT:    br label [[FOR_INC]]
291 ; CHECK:       for.inc:
292 ; CHECK-NEXT:    [[INC]] = add nsw i32 [[I_0]], 1
293 ; CHECK-NEXT:    br label [[FOR_COND]]
294 ; CHECK:       for.end:
295 ; CHECK-NEXT:    ret void
298 entry:
299   call void @nocallback_func(ptr @obj5)
300   br label %for.cond
302 for.cond:                                         ; preds = %for.inc, %entry
303   %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
304   %cmp = icmp slt i32 %i.0, 1000
305   br i1 %cmp, label %for.body, label %for.end
307 for.body:                                         ; preds = %for.cond
308   %0 = load ptr, ptr @obj5, align 8
309   call void @unknown_call()
310   %idxprom = sext i32 %i.0 to i64
311   %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom
312   store ptr %p, ptr %arrayidx, align 8
313   br label %for.inc
315 for.inc:                                          ; preds = %for.body
316   %inc = add nsw i32 %i.0, 1
317   br label %for.cond
319 for.end:                                          ; preds = %for.cond
320   ret void
323 declare void @nocapture_nocallback_func(ptr nocapture) nocallback
324 declare void @nocapture_func(ptr nocapture)
325 declare void @nocallback_func(ptr) nocallback
326 ; nosync and nocallback are required, otherwise the call
327 ; will by ModRef for any global:
328 declare void @unknown_call() nosync nocallback