xref: /llvm-project/llvm/test/Analysis/MemorySSA/phi-translation.ll (revision 1469d82e1cb3edc939d6b93089046edfef0cf36c)
1; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,NOLIMIT
2; RUN: opt -memssa-check-limit=0 -aa-pipeline=basic-aa -passes='print<memoryssa>,verify<memoryssa>' -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK,LIMIT
3
4; %ptr can't alias %local, so we should be able to optimize the use of %local to
5; point to the store to %local.
6; CHECK-LABEL: define void @check
7define void @check(ptr %ptr, i1 %bool) {
8entry:
9  %local = alloca i8, align 1
10; CHECK: 1 = MemoryDef(liveOnEntry)
11; CHECK-NEXT: store i8 0, ptr %local, align 1
12  store i8 0, ptr %local, align 1
13  br i1 %bool, label %if.then, label %if.end
14
15if.then:
16  %p2 = getelementptr inbounds i8, ptr %ptr, i32 1
17; CHECK: 2 = MemoryDef(1)
18; CHECK-NEXT: store i8 0, ptr %p2, align 1
19  store i8 0, ptr %p2, align 1
20  br label %if.end
21
22if.end:
23; CHECK: 3 = MemoryPhi({entry,1},{if.then,2})
24; NOLIMIT: MemoryUse(1)
25; NOLIMIT-NEXT: load i8, ptr %local, align 1
26; LIMIT: MemoryUse(3)
27; LIMIT-NEXT: load i8, ptr %local, align 1
28  load i8, ptr %local, align 1
29  ret void
30}
31
32; CHECK-LABEL: define void @check2
33define void @check2(i1 %val1, i1 %val2, i1 %val3) {
34entry:
35  %local = alloca i8, align 1
36  %local2 = alloca i8, align 1
37
38; CHECK: 1 = MemoryDef(liveOnEntry)
39; CHECK-NEXT: store i8 0, ptr %local
40  store i8 0, ptr %local
41  br i1 %val1, label %if.then, label %phi.3
42
43if.then:
44; CHECK: 2 = MemoryDef(1)
45; CHECK-NEXT: store i8 2, ptr %local2
46  store i8 2, ptr %local2
47  br i1 %val2, label %phi.2, label %phi.3
48
49phi.3:
50; CHECK: 7 = MemoryPhi({entry,1},{if.then,2})
51; CHECK: 3 = MemoryDef(7)
52; CHECK-NEXT: store i8 3, ptr %local2
53  store i8 3, ptr %local2
54  br i1 %val3, label %phi.2, label %phi.1
55
56phi.2:
57; CHECK: 5 = MemoryPhi({if.then,2},{phi.3,3})
58; CHECK: 4 = MemoryDef(5)
59; CHECK-NEXT: store i8 4, ptr %local2
60  store i8 4, ptr %local2
61  br label %phi.1
62
63phi.1:
64; Order matters here; phi.2 needs to come before phi.3, because that's the order
65; they're visited in.
66; CHECK: 6 = MemoryPhi({phi.2,4},{phi.3,3})
67; NOLIMIT: MemoryUse(1)
68; NOLIMIT-NEXT: load i8, ptr %local
69; LIMIT: MemoryUse(6)
70; LIMIT-NEXT: load i8, ptr %local
71  load i8, ptr %local
72  ret void
73}
74
75; CHECK-LABEL: define void @cross_phi
76define void @cross_phi(ptr noalias %p1, ptr noalias %p2, i1 %arg) {
77; CHECK: 1 = MemoryDef(liveOnEntry)
78; CHECK-NEXT: store i8 0, ptr %p1
79  store i8 0, ptr %p1
80; NOLIMIT: MemoryUse(1)
81; NOLIMIT-NEXT: load i8, ptr %p1
82; LIMIT: MemoryUse(1)
83; LIMIT-NEXT: load i8, ptr %p1
84  load i8, ptr %p1
85  br i1 %arg, label %a, label %b
86
87a:
88; CHECK: 2 = MemoryDef(1)
89; CHECK-NEXT: store i8 0, ptr %p2
90  store i8 0, ptr %p2
91  br i1 %arg, label %c, label %d
92
93b:
94; CHECK: 3 = MemoryDef(1)
95; CHECK-NEXT: store i8 1, ptr %p2
96  store i8 1, ptr %p2
97  br i1 %arg, label %c, label %d
98
99c:
100; CHECK: 6 = MemoryPhi({a,2},{b,3})
101; CHECK: 4 = MemoryDef(6)
102; CHECK-NEXT: store i8 2, ptr %p2
103  store i8 2, ptr %p2
104  br label %e
105
106d:
107; CHECK: 7 = MemoryPhi({a,2},{b,3})
108; CHECK: 5 = MemoryDef(7)
109; CHECK-NEXT: store i8 3, ptr %p2
110  store i8 3, ptr %p2
111  br label %e
112
113e:
114; 8 = MemoryPhi({c,4},{d,5})
115; NOLIMIT: MemoryUse(1)
116; NOLIMIT-NEXT: load i8, ptr %p1
117; LIMIT: MemoryUse(8)
118; LIMIT-NEXT: load i8, ptr %p1
119  load i8, ptr %p1
120  ret void
121}
122
123; CHECK-LABEL: define void @looped
124define void @looped(ptr noalias %p1, ptr noalias %p2, i1 %arg) {
125; CHECK: 1 = MemoryDef(liveOnEntry)
126; CHECK-NEXT: store i8 0, ptr %p1
127  store i8 0, ptr %p1
128  br label %loop.1
129
130loop.1:
131; CHECK: 6 = MemoryPhi({%0,1},{loop.3,4})
132; CHECK: 2 = MemoryDef(6)
133; CHECK-NEXT: store i8 0, ptr %p2
134  store i8 0, ptr %p2
135  br i1 %arg, label %loop.2, label %loop.3
136
137loop.2:
138; CHECK: 5 = MemoryPhi({loop.1,2},{loop.3,4})
139; CHECK: 3 = MemoryDef(5)
140; CHECK-NEXT: store i8 1, ptr %p2
141  store i8 1, ptr %p2
142  br label %loop.3
143
144loop.3:
145; CHECK: 7 = MemoryPhi({loop.1,2},{loop.2,3})
146; CHECK: 4 = MemoryDef(7)
147; CHECK-NEXT: store i8 2, ptr %p2
148  store i8 2, ptr %p2
149; NOLIMIT: MemoryUse(1)
150; NOLIMIT-NEXT: load i8, ptr %p1
151; LIMIT: MemoryUse(4)
152; LIMIT-NEXT: load i8, ptr %p1
153  load i8, ptr %p1
154  br i1 %arg, label %loop.2, label %loop.1
155}
156
157; CHECK-LABEL: define void @looped_visitedonlyonce
158define void @looped_visitedonlyonce(ptr noalias %p1, ptr noalias %p2, i1 %arg) {
159  br label %while.cond
160
161while.cond:
162; CHECK: 5 = MemoryPhi({%0,liveOnEntry},{if.end,3})
163; CHECK-NEXT: br i1 %arg, label %if.then, label %if.end
164  br i1 %arg, label %if.then, label %if.end
165
166if.then:
167; CHECK: 1 = MemoryDef(5)
168; CHECK-NEXT: store i8 0, ptr %p1
169  store i8 0, ptr %p1
170  br i1 %arg, label %if.end, label %if.then2
171
172if.then2:
173; CHECK: 2 = MemoryDef(1)
174; CHECK-NEXT: store i8 1, ptr %p2
175  store i8 1, ptr %p2
176  br label %if.end
177
178if.end:
179; CHECK: 4 = MemoryPhi({while.cond,5},{if.then,1},{if.then2,2})
180; CHECK: MemoryUse(4)
181; CHECK-NEXT: load i8, ptr %p1
182  load i8, ptr %p1
183; CHECK: 3 = MemoryDef(4)
184; CHECK-NEXT: store i8 2, ptr %p2
185  store i8 2, ptr %p2
186; NOLIMIT: MemoryUse(4)
187; NOLIMIT-NEXT: load i8, ptr %p1
188; LIMIT: MemoryUse(3)
189; LIMIT-NEXT: load i8, ptr %p1
190  load i8, ptr %p1
191  br label %while.cond
192}
193
194; CHECK-LABEL: define i32 @use_not_optimized_due_to_backedge
195define i32 @use_not_optimized_due_to_backedge(ptr nocapture %m_i_strides, ptr nocapture readonly %eval_left_dims) {
196entry:
197; CHECK: 1 = MemoryDef(liveOnEntry)
198; CHECK-NEXT: store i32 1, ptr %m_i_strides, align 4
199  store i32 1, ptr %m_i_strides, align 4
200  br label %for.body
201
202for.cond.cleanup:                                 ; preds = %for.inc
203  ret i32 %m_i_size.1
204
205for.body:                                         ; preds = %entry, %for.inc
206; CHECK: 4 = MemoryPhi({entry,1},{for.inc,3})
207; CHECK-NEXT: %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
208  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ]
209  %m_i_size.022 = phi i32 [ 1, %entry ], [ %m_i_size.1, %for.inc ]
210  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
211  %cmp1 = icmp eq i64 %indvars.iv, 0
212  %arrayidx2 = getelementptr inbounds i32, ptr %m_i_strides, i64 %indvars.iv
213; CHECK: MemoryUse(4)
214; CHECK-NEXT: %0 = load i32, ptr %arrayidx2, align 4
215  %0 = load i32, ptr %arrayidx2, align 4
216  %arrayidx4 = getelementptr inbounds i32, ptr %eval_left_dims, i64 %indvars.iv
217; CHECK: MemoryUse(4)
218; CHECK-NEXT: %1 = load i32, ptr %arrayidx4, align 4
219  %1 = load i32, ptr %arrayidx4, align 4
220  %mul = mul nsw i32 %1, %0
221  br i1 %cmp1, label %if.then, label %for.inc
222
223if.then:                                          ; preds = %for.body
224  %arrayidx7 = getelementptr inbounds i32, ptr %m_i_strides, i64 %indvars.iv.next
225; CHECK: 2 = MemoryDef(4)
226; CHECK-NEXT: store i32 %mul, ptr %arrayidx7, align 4
227  store i32 %mul, ptr %arrayidx7, align 4
228  br label %for.inc
229
230for.inc:                                          ; preds = %for.body, %if.then
231; CHECK: 3 = MemoryPhi({for.body,4},{if.then,2})
232; CHECK-NEXT: %m_i_size.1 = phi i32 [ %m_i_size.022, %if.then ], [ %mul, %for.body ]
233  %m_i_size.1 = phi i32 [ %m_i_size.022, %if.then ], [ %mul, %for.body ]
234  br i1 %cmp1, label %for.body, label %for.cond.cleanup
235}
236
237
238%ArrayType = type { [2 x i64] }
239%StructOverArrayType = type { %ArrayType }
240%BigStruct = type { i8, i8, i8, i8, i8, i8, i8, %ArrayType, %ArrayType}
241
242; CHECK-LABEL: define void @use_not_optimized_due_to_backedge_unknown
243define void @use_not_optimized_due_to_backedge_unknown(ptr %this) {
244entry:
245  %eval_left_dims = alloca %StructOverArrayType, align 8
246  %eval_right_dims = alloca %StructOverArrayType, align 8
247  %lhs_strides = alloca %ArrayType, align 8
248  %rhs_strides = alloca %ArrayType, align 8
249  br label %for.body.preheader
250
251for.body.preheader:                               ; preds = %entry
252  %arrayidx.i527 = getelementptr inbounds %BigStruct, ptr %this, i64 0, i32 7, i32 0, i64 0
253; CHECK: 1 = MemoryDef(liveOnEntry)
254; CHECK-NEXT: store i64 1, ptr %arrayidx.i527, align 8
255  store i64 1, ptr %arrayidx.i527, align 8
256  %arrayidx.i528 = getelementptr inbounds %BigStruct, ptr %this, i64 0, i32 8, i32 0, i64 0
257; CHECK: 2 = MemoryDef(1)
258; CHECK-NEXT: store i64 1, ptr %arrayidx.i528, align 8
259  store i64 1, ptr %arrayidx.i528, align 8
260  br label %for.main.body
261
262for.main.body:               ; preds = %if.end220.if.then185_crit_edge, %for.body.preheader
263; CHECK: 4 = MemoryPhi({for.body.preheader,2},{if.end220.if.then185_crit_edge,3})
264; CHECK-NEXT: %nocontract_idx.0656 = phi i64 [ 0, %for.body.preheader ], [ 1, %if.end220.if.then185_crit_edge ]
265  %nocontract_idx.0656 = phi i64 [ 0, %for.body.preheader ], [ 1, %if.end220.if.then185_crit_edge ]
266  %add199 = add nuw nsw i64 %nocontract_idx.0656, 1
267  %cmp200 = icmp eq i64 %nocontract_idx.0656, 0
268  %arrayidx.i559 = getelementptr inbounds %BigStruct, ptr %this, i64 0, i32 7, i32 0, i64 %nocontract_idx.0656
269; CHECK: MemoryUse(4)
270; CHECK-NEXT: %tmp21 = load i64, ptr %arrayidx.i559, align 8
271  %tmp21 = load i64, ptr %arrayidx.i559, align 8
272  %mul206 = mul nsw i64 %tmp21, %tmp21
273  br i1 %cmp200, label %if.end220.if.then185_crit_edge, label %the.end
274
275if.end220.if.then185_crit_edge:                   ; preds = %for.main.body
276  %arrayidx.i571 = getelementptr inbounds %BigStruct, ptr %this, i64 0, i32 7, i32 0, i64 %add199
277; CHECK: 3 = MemoryDef(4)
278; CHECK-NEXT: store i64 %mul206, ptr %arrayidx.i571, align 8
279  store i64 %mul206, ptr %arrayidx.i571, align 8
280  br label %for.main.body
281
282the.end:                            ; preds = %for.main.body
283  ret void
284
285}
286
287
288@c = local_unnamed_addr global [2 x i16] zeroinitializer, align 2
289
290define i32 @dont_merge_noalias_simple(ptr noalias %ptr) {
291; CHECK-LABEL: define i32 @dont_merge_noalias_simple
292; CHECK-LABEL: entry:
293; CHECK:       ; 1 = MemoryDef(liveOnEntry)
294; CHECK-NEXT:  store i16 1, ptr @c, align 2
295
296; CHECK-LABEL: %for.body
297; NOLIMIT:     ; MemoryUse(1)
298; LIMIT:       ; MemoryUse(4)
299; CHECK-NEXT:    %lv = load i16, ptr %arrayidx, align 2
300
301entry:
302  store i16 1, ptr @c, align 2
303  br label %for.body
304
305for.body:                                         ; preds = %for.body, %entry
306  %storemerge2 = phi i32 [ 1, %entry ], [ %dec, %for.body ]
307  %idxprom1 = zext i32 %storemerge2 to i64
308  %arrayidx = getelementptr inbounds [2 x i16], ptr @c, i64 0, i64 %idxprom1
309  %lv = load i16, ptr %arrayidx, align 2
310  %conv = sext i16 %lv to i32
311  store i32 %conv, ptr %ptr, align 4
312  %dec = add nsw i32 %storemerge2, -1
313  %cmp = icmp sgt i32 %storemerge2, 0
314  br i1 %cmp, label %for.body, label %for.end
315
316for.end:                                          ; preds = %for.body
317  store i16 0, ptr @c, align 2
318  ret i32 0
319}
320
321
322define i32 @dont_merge_noalias_complex(ptr noalias %ptr, ptr noalias %another) {
323; CHECK-LABEL: define i32 @dont_merge_noalias_complex
324; CHECK-LABEL: entry:
325; CHECK:       ; 1 = MemoryDef(liveOnEntry)
326; CHECK-NEXT:  store i16 1, ptr @c, align 2
327
328; CHECK-LABEL: %for.body
329; NOLIMIT:     ; MemoryUse(1)
330; LIMIT:       ; MemoryUse(7)
331; CHECK-NEXT:    %lv = load i16, ptr %arrayidx, align 2
332
333entry:
334  store i16 1, ptr @c, align 2
335  br label %for.body
336
337for.body:                                         ; preds = %for.body, %entry
338  %storemerge2 = phi i32 [ 1, %entry ], [ %dec, %merge.body ]
339  %idxprom1 = zext i32 %storemerge2 to i64
340  %arrayidx = getelementptr inbounds [2 x i16], ptr @c, i64 0, i64 %idxprom1
341  %lv = load i16, ptr %arrayidx, align 2
342  %conv = sext i16 %lv to i32
343  store i32 %conv, ptr %ptr, align 4
344  %dec = add nsw i32 %storemerge2, -1
345
346  %cmpif = icmp sgt i32 %storemerge2, 1
347  br i1 %cmpif, label %if.body, label %else.body
348
349if.body:
350  store i32 %conv, ptr %another, align 4
351  br label %merge.body
352
353else.body:
354  store i32 %conv, ptr %another, align 4
355  br label %merge.body
356
357merge.body:
358  %cmp = icmp sgt i32 %storemerge2, 0
359  br i1 %cmp, label %for.body, label %for.end
360
361for.end:                                          ; preds = %for.body
362  store i16 0, ptr @c, align 2
363  ret i32 0
364}
365
366declare i1 @should_exit(i32) readnone
367declare void @init(ptr)
368
369; Test case for PR47498.
370; %l.1 may read the result of `store i32 10, ptr %p.1` in %storebb, because
371; after %storebb has been executed, %loop.1.header might be executed again.
372; Make sure %l.1's defining access is the MemoryPhi in the block.
373define void @dont_merge_noalias_complex_2(i32 %arg, i32 %arg1)  {
374; CHECK-LABEL: define void @dont_merge_noalias_complex_2(
375
376; CHECK-LABEL: entry:
377; CHECK:       ; 1 = MemoryDef(liveOnEntry)
378; CHECK-NEXT:  call void @init(ptr %tmp)
379
380; CHECK-LABEL: loop.1.header:
381; CHECK-NEXT:  ; 4 = MemoryPhi({entry,1},{loop.1.latch,3})
382; CHECK:       ; MemoryUse(4)
383; CHECK-NEXT:  %l.1 = load i32, ptr %p.1, align 4
384
385; CHECK-LABEL: loop.1.latch:
386; CHECK-NEXT:  ; 3 = MemoryPhi({loop.1.header,4},{storebb,2})
387
388; CHECK-LABEL: storebb:
389; CHECK-NEXT:  %iv.add2 = add nuw nsw i64 %iv, 2
390; CHECK-NEXT:  %p.2 = getelementptr inbounds [32 x i32], ptr %tmp, i64 0, i64 %iv.add2
391; CHECK-NEXT:  ; MemoryUse(4)
392; CHECK-NEXT:  %l.2 = load i32, ptr %p.2, align 4
393; CHECK-NEXT:  ; 2 = MemoryDef(4)
394; CHECK-NEXT:  store i32 10, ptr %p.1, align 4
395entry:
396  %tmp = alloca [32 x i32], align 16
397  call void @init(ptr %tmp)
398  br label %loop.1.header
399
400loop.1.header:
401  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.1.latch ]
402  %iv.next = add nuw nsw i64 %iv, 1
403  %p.1 = getelementptr inbounds [32 x i32], ptr %tmp, i64 0, i64 %iv.next
404  %l.1 = load i32, ptr %p.1, align 4
405  %tmp244 = icmp ult i64 %iv, 10
406  br i1 %tmp244, label %loop.1.latch, label %storebb
407
408loop.1.latch:
409  %ec = call i1 @should_exit(i32 %l.1)
410  br i1 %ec, label %exit, label %loop.1.header
411
412storebb:
413  %iv.add2 = add nuw nsw i64 %iv, 2
414  %p.2 = getelementptr inbounds [32 x i32], ptr %tmp, i64 0, i64 %iv.add2
415  %l.2 = load i32, ptr %p.2, align 4
416  store i32 10, ptr %p.1, align 4
417  br label %loop.1.latch
418
419exit:
420  ret void
421}
422
423define i32 @phi_with_constant_values(i1 %cmp) {
424; CHECK-LABEL: define i32 @phi_with_constant_values
425; CHECK-LABEL: lhs:
426; CHECK:       ; 1 = MemoryDef(liveOnEntry)
427; CHECK-NEXT:  store i16 1, ptr @c, align 2
428
429; CHECK-LABEL: rhs:
430; CHECK:       ; 2 = MemoryDef(liveOnEntry)
431; CHECK-NEXT:  store i16 1, ptr %s2.ptr, align 2
432
433; CHECK-LABEL: merge:
434; CHECK:       ; 3 = MemoryPhi({lhs,1},{rhs,2})
435; CHECK-NEXT:   %storemerge2 = phi i32 [ 2, %lhs ], [ 3, %rhs ]
436; LIMIT:       ; MemoryUse(3)
437; LIMIT-NEXT:  %lv = load i16, ptr %arrayidx, align 2
438; NOLIMIT:     ; MemoryUse(liveOnEntry)
439; NOLIMIT-NEXT: %lv = load i16, ptr %arrayidx, align 2
440
441entry:
442  br i1 %cmp, label %lhs, label %rhs
443
444lhs:
445  store i16 1, ptr @c, align 2
446  br label %merge
447
448rhs:
449  %s2.ptr = getelementptr inbounds [2 x i16], ptr @c, i64 0, i64 1
450  store i16 1, ptr %s2.ptr, align 2
451  br label %merge
452
453merge:                                         ; preds = %for.body, %entry
454  %storemerge2 = phi i32 [ 2, %lhs ], [ 3, %rhs ]
455  %idxprom1 = zext i32 %storemerge2 to i64
456  %arrayidx = getelementptr inbounds [2 x i16], ptr @c, i64 0, i64 %idxprom1
457  %lv = load i16, ptr %arrayidx, align 2
458  br label %end
459
460end:                                          ; preds = %for.body
461  ret i32 0
462}
463
464; CHECK-LABEL: define void @use_clobbered_by_def_in_loop()
465define void @use_clobbered_by_def_in_loop() {
466entry:
467  %nodeStack = alloca [12 x i32], align 4
468  call void @llvm.lifetime.start.p0(i64 48, ptr nonnull %nodeStack)
469  br i1 false, label %cleanup, label %while.cond
470
471; CHECK-LABEL: while.cond:
472; CHECK-NEXT: ; [[NO6:.*]] = MemoryPhi({entry,1},{while.cond.backedge,5})
473
474while.cond:                                       ; preds = %entry, %while.cond.backedge
475  %depth.1 = phi i32 [ %depth.1.be, %while.cond.backedge ], [ 0, %entry ]
476  %cmp = icmp sgt i32 %depth.1, 0
477  br i1 %cmp, label %land.rhs, label %while.end
478
479; CHECK-LABEL: land.rhs:
480; CHECK-NEXT: %sub = add nsw i32 %depth.1, -1
481; CHECK-NEXT: %arrayidx = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i32 %sub
482; CHECK-NEXT: ; MemoryUse([[NO6]])
483; CHECK-NEXT: %0 = load i32, ptr %arrayidx, align 4
484
485land.rhs:                                         ; preds = %while.cond
486  %sub = add nsw i32 %depth.1, -1
487  %arrayidx = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i32 %sub
488  %0 = load i32, ptr %arrayidx, align 4
489  br i1 true, label %while.body, label %while.end
490
491while.body:                                       ; preds = %land.rhs
492  br i1 true, label %cleanup, label %while.cond.backedge
493
494while.cond.backedge:                              ; preds = %while.body, %while.end
495  %depth.1.be = phi i32 [ %sub, %while.body ], [ %inc, %while.end ]
496  br label %while.cond
497
498while.end:                                        ; preds = %while.cond, %land.rhs
499  %arrayidx10 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i32 %depth.1
500  store i32 %depth.1, ptr %arrayidx10, align 4
501  %inc = add nsw i32 %depth.1, 1
502  br i1 true, label %cleanup, label %while.cond.backedge
503
504cleanup:                                          ; preds = %while.body, %while.end, %entry
505  call void @llvm.lifetime.end.p0(i64 48, ptr nonnull %nodeStack)
506  ret void
507}
508
509declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
510declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
511
512define void @another_loop_clobber_inc() {
513; CHECK-LABEL: void @another_loop_clobber_inc
514; CHECK-LABEL: loop.header:
515; CHECK-NEXT:  ; 4 = MemoryPhi({entry,1},{cond.read,3})
516
517; CHECK-LABEL: cond.read:
518; CHECK:       ; MemoryUse(4)
519; CHECK-NEXT:  %use = load i32, ptr %ptr.1, align 4
520; CHECK-NEXT:  ; 2 = MemoryDef(4)
521; CHECK-NEXT:  %c.2 = call i1 @cond(i32 %use)
522; CHECK-NEXT:  %ptr.10 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i32 %inc
523; CHECK-NEXT:  ; 3 = MemoryDef(2)
524; CHECK-NEXT:  store i32 10, ptr %ptr.2, align 4
525
526entry:
527  %nodeStack = alloca [12 x i32], align 4
528  %c.1 = call i1 @cond(i32 1)
529  br i1 %c.1, label %cleanup, label %loop.header
530
531loop.header:                                       ; preds = %entry, %while.cond.backedge
532  %depth.1 = phi i32 [ %inc, %cond.read], [ 1, %entry ]
533  %cmp = icmp sgt i32 %depth.1, 0
534  %inc = add nsw i32 %depth.1, 3
535  %inc2 = add nsw i32 %depth.1, 6
536  br i1 %cmp, label %cond.read, label %cleanup
537
538cond.read:                                        ; preds = %while.cond
539  %ptr.1 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i32 %depth.1
540  %ptr.2 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i32 %inc2
541  %use = load i32, ptr %ptr.1, align 4
542  %c.2 = call i1 @cond(i32 %use)
543  %ptr.10 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i32 %inc
544  store i32 10, ptr %ptr.2, align 4
545  br i1 %c.2, label %loop.header, label %cleanup
546
547cleanup:
548  ret void
549}
550
551define void @another_loop_clobber_dec() {
552; CHECK-LABEL: void @another_loop_clobber_dec
553; CHECK-LABEL: loop.header:
554; CHECK-NEXT:  ; 4 = MemoryPhi({entry,1},{cond.read,3})
555
556; CHECK-LABEL: cond.read:
557; CHECK:       ; MemoryUse(4)
558; CHECK-NEXT:  %use = load i32, ptr %ptr.1, align 4
559; CHECK-NEXT:  ; 2 = MemoryDef(4)
560; CHECK-NEXT:  %c.2 = call i1 @cond(i32 %use)
561; CHECK-NEXT:  %ptr.10 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i64 %sub
562; CHECK-NEXT:  ; 3 = MemoryDef(2)
563; CHECK-NEXT:  store i32 10, ptr %ptr.2, align 4
564
565entry:
566  %nodeStack = alloca [12 x i32], align 4
567  %c.1 = call i1 @cond(i32 1)
568  br i1 %c.1, label %cleanup, label %loop.header
569
570loop.header:                                       ; preds = %entry, %while.cond.backedge
571  %depth.1 = phi i64 [ %sub, %cond.read], [ 20, %entry ]
572  %cmp = icmp sgt i64 %depth.1, 6
573  %sub = sub nsw nuw i64 %depth.1, 3
574  %sub2 = sub nsw nuw i64 %depth.1, 6
575  br i1 %cmp, label %cond.read, label %cleanup
576
577cond.read:                                        ; preds = %while.cond
578  %ptr.1 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i64 %depth.1
579  %ptr.2 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i64 %sub2
580  %use = load i32, ptr %ptr.1, align 4
581  %c.2 = call i1 @cond(i32 %use)
582  %ptr.10 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i64 %sub
583  store i32 10, ptr %ptr.2, align 4
584  br i1 %c.2, label %loop.header, label %cleanup
585
586cleanup:
587  ret void
588}
589
590declare i1 @cond(i32)
591