xref: /llvm-project/llvm/test/Analysis/LoopAccessAnalysis/non-constant-strides-forward.ll (revision 933f49248bfede6b22d516baa5cf80bdf85c3c61)
1; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s
3
4target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
5
6declare void @llvm.assume(i1)
7
8define void @different_non_constant_strides_known_forward(ptr %A) {
9; CHECK-LABEL: 'different_non_constant_strides_known_forward'
10; CHECK-NEXT:    loop:
11; CHECK-NEXT:      Memory dependences are safe
12; CHECK-NEXT:      Dependences:
13; CHECK-NEXT:        Forward:
14; CHECK-NEXT:            %l = load i32, ptr %gep.mul.2, align 4 ->
15; CHECK-NEXT:            store i32 %add, ptr %gep, align 4
16; CHECK-EMPTY:
17; CHECK-NEXT:      Run-time memory checks:
18; CHECK-NEXT:      Grouped accesses:
19; CHECK-EMPTY:
20; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
21; CHECK-NEXT:      SCEV assumptions:
22; CHECK-EMPTY:
23; CHECK-NEXT:      Expressions re-written:
24;
25entry:
26  br label %loop
27
28loop:
29  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
30  %iv.mul.2 = shl nuw nsw i64 %iv, 1
31  %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
32  %l = load i32, ptr %gep.mul.2, align 4
33  %add = add nsw i32 %l, 5
34  %gep = getelementptr inbounds i32, ptr %A, i64 %iv
35  store i32 %add, ptr %gep, align 4
36  %iv.next = add nuw nsw i64 %iv, 1
37  %exitcond.not = icmp eq i64 %iv.next, 256
38  br i1 %exitcond.not, label %exit, label %loop
39
40exit:
41  ret void
42}
43
44define void @different_non_constant_strides_known_forward_min_distance_3(ptr %A) {
45; CHECK-LABEL: 'different_non_constant_strides_known_forward_min_distance_3'
46; CHECK-NEXT:    loop:
47; CHECK-NEXT:      Memory dependences are safe
48; CHECK-NEXT:      Dependences:
49; CHECK-NEXT:        Forward:
50; CHECK-NEXT:            %l = load i32, ptr %gep.mul.2, align 4 ->
51; CHECK-NEXT:            store i32 %add, ptr %gep, align 4
52; CHECK-EMPTY:
53; CHECK-NEXT:      Run-time memory checks:
54; CHECK-NEXT:      Grouped accesses:
55; CHECK-EMPTY:
56; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
57; CHECK-NEXT:      SCEV assumptions:
58; CHECK-EMPTY:
59; CHECK-NEXT:      Expressions re-written:
60;
61entry:
62  %A.3 = getelementptr inbounds i8, ptr %A, i64 3
63  br label %loop
64
65loop:
66  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
67  %iv.mul.2 = shl nuw nsw i64 %iv, 1
68  %gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2
69  %l = load i32, ptr %gep.mul.2, align 4
70  %add = add nsw i32 %l, 5
71  %gep = getelementptr inbounds i32, ptr %A, i64 %iv
72  store i32 %add, ptr %gep, align 4
73  %iv.next = add nuw nsw i64 %iv, 1
74  %exitcond.not = icmp eq i64 %iv.next, 256
75  br i1 %exitcond.not, label %exit, label %loop
76
77exit:
78  ret void
79}
80
81define void @different_non_constant_strides_known_forward_via_assume(ptr %A, i64 %scale) {
82; CHECK-LABEL: 'different_non_constant_strides_known_forward_via_assume'
83; CHECK-NEXT:    loop:
84; CHECK-NEXT:      Report: cannot identify array bounds
85; CHECK-NEXT:      Dependences:
86; CHECK-NEXT:      Run-time memory checks:
87; CHECK-NEXT:      Grouped accesses:
88; CHECK-EMPTY:
89; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
90; CHECK-NEXT:      SCEV assumptions:
91; CHECK-EMPTY:
92; CHECK-NEXT:      Expressions re-written:
93;
94entry:
95  %c = icmp sgt i64 %scale, 0
96  call void @llvm.assume(i1 %c)
97  br label %loop
98
99loop:
100  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
101  %iv.mul.2 = shl nuw nsw i64 %iv, %scale
102  %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
103  %l = load i32, ptr %gep.mul.2, align 4
104  %add = add nsw i32 %l, 5
105  %gep = getelementptr inbounds i32, ptr %A, i64 %iv
106  store i32 %add, ptr %gep, align 4
107  %iv.next = add nuw nsw i64 %iv, 1
108  %exitcond.not = icmp eq i64 %iv.next, 256
109  br i1 %exitcond.not, label %exit, label %loop
110
111exit:
112  ret void
113}
114
115define void @different_non_constant_strides_known_forward_via_assume_min_distance_3(ptr %A, i64 %scale) {
116; CHECK-LABEL: 'different_non_constant_strides_known_forward_via_assume_min_distance_3'
117; CHECK-NEXT:    loop:
118; CHECK-NEXT:      Report: cannot identify array bounds
119; CHECK-NEXT:      Dependences:
120; CHECK-NEXT:      Run-time memory checks:
121; CHECK-NEXT:      Grouped accesses:
122; CHECK-EMPTY:
123; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
124; CHECK-NEXT:      SCEV assumptions:
125; CHECK-EMPTY:
126; CHECK-NEXT:      Expressions re-written:
127;
128entry:
129  %A.3 = getelementptr inbounds i8, ptr %A, i64 3
130  %c = icmp sgt i64 %scale, 0
131  call void @llvm.assume(i1 %c)
132  br label %loop
133
134loop:
135  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
136  %iv.mul.2 = shl nuw nsw i64 %iv, %scale
137  %gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2
138  %l = load i32, ptr %gep.mul.2, align 4
139  %add = add nsw i32 %l, 5
140  %gep = getelementptr inbounds i32, ptr %A, i64 %iv
141  store i32 %add, ptr %gep, align 4
142  %iv.next = add nuw nsw i64 %iv, 1
143  %exitcond.not = icmp eq i64 %iv.next, 256
144  br i1 %exitcond.not, label %exit, label %loop
145
146exit:
147  ret void
148}
149
150define void @different_non_constant_strides_not_known_forward(ptr %A, i64 %scale) {
151; CHECK-LABEL: 'different_non_constant_strides_not_known_forward'
152; CHECK-NEXT:    loop:
153; CHECK-NEXT:      Report: cannot identify array bounds
154; CHECK-NEXT:      Dependences:
155; CHECK-NEXT:      Run-time memory checks:
156; CHECK-NEXT:      Grouped accesses:
157; CHECK-EMPTY:
158; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
159; CHECK-NEXT:      SCEV assumptions:
160; CHECK-EMPTY:
161; CHECK-NEXT:      Expressions re-written:
162;
163entry:
164  br label %loop
165
166loop:
167  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
168  %iv.mul.2 = shl nuw nsw i64 %iv, %scale
169  %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
170  %l = load i32, ptr %gep.mul.2, align 4
171  %add = add nsw i32 %l, 5
172  %gep = getelementptr inbounds i32, ptr %A, i64 %iv
173  store i32 %add, ptr %gep, align 4
174  %iv.next = add nuw nsw i64 %iv, 1
175  %exitcond.not = icmp eq i64 %iv.next, 256
176  br i1 %exitcond.not, label %exit, label %loop
177
178exit:
179  ret void
180}
181
182; Tests with accesses with strides with different signs.
183define void @strides_with_different_directions_1(ptr %A) {
184; CHECK-LABEL: 'strides_with_different_directions_1'
185; CHECK-NEXT:    loop:
186; CHECK-NEXT:      Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
187; CHECK-NEXT:  Unknown data dependence.
188; CHECK-NEXT:      Dependences:
189; CHECK-NEXT:        Unknown:
190; CHECK-NEXT:            %l = load i32, ptr %gep.mul.2, align 4 ->
191; CHECK-NEXT:            store i32 %add, ptr %gep, align 4
192; CHECK-EMPTY:
193; CHECK-NEXT:      Run-time memory checks:
194; CHECK-NEXT:      Grouped accesses:
195; CHECK-EMPTY:
196; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
197; CHECK-NEXT:      SCEV assumptions:
198; CHECK-EMPTY:
199; CHECK-NEXT:      Expressions re-written:
200;
201entry:
202  br label %loop
203
204loop:
205  %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ]
206  %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ]
207  %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.1
208  %l = load i32, ptr %gep.mul.2, align 4
209  %add = add nsw i32 %l, 5
210  %gep = getelementptr inbounds i32, ptr %A, i64 %iv.2
211  store i32 %add, ptr %gep, align 4
212  %iv.1.next = add nuw nsw i64 %iv.1, 1
213  %iv.2.next = add nsw i64 %iv.2, -1
214  %exitcond.not = icmp eq i64 %iv.1.next, 256
215  br i1 %exitcond.not, label %exit, label %loop
216
217exit:
218  ret void
219}
220
221define void @strides_with_different_directions_2(ptr %A) {
222; CHECK-LABEL: 'strides_with_different_directions_2'
223; CHECK-NEXT:    loop:
224; CHECK-NEXT:      Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
225; CHECK-NEXT:  Unknown data dependence.
226; CHECK-NEXT:      Dependences:
227; CHECK-NEXT:        Unknown:
228; CHECK-NEXT:            %l = load i32, ptr %gep.mul.2, align 4 ->
229; CHECK-NEXT:            store i32 %add, ptr %gep, align 4
230; CHECK-EMPTY:
231; CHECK-NEXT:      Run-time memory checks:
232; CHECK-NEXT:      Grouped accesses:
233; CHECK-EMPTY:
234; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
235; CHECK-NEXT:      SCEV assumptions:
236; CHECK-EMPTY:
237; CHECK-NEXT:      Expressions re-written:
238;
239entry:
240  br label %loop
241
242loop:
243  %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ]
244  %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ]
245  %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.2
246  %l = load i32, ptr %gep.mul.2, align 4
247  %add = add nsw i32 %l, 5
248  %gep = getelementptr inbounds i32, ptr %A, i64 %iv.1
249  store i32 %add, ptr %gep, align 4
250  %iv.1.next = add nuw nsw i64 %iv.1, 1
251  %iv.2.next = add nsw i64 %iv.2, -1
252  %exitcond.not = icmp eq i64 %iv.1.next, 256
253  br i1 %exitcond.not, label %exit, label %loop
254
255exit:
256  ret void
257}
258
259define void @strides_with_different_directions_3(ptr %A) {
260; CHECK-LABEL: 'strides_with_different_directions_3'
261; CHECK-NEXT:    loop:
262; CHECK-NEXT:      Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
263; CHECK-NEXT:  Unknown data dependence.
264; CHECK-NEXT:      Dependences:
265; CHECK-NEXT:        Unknown:
266; CHECK-NEXT:            %l = load i32, ptr %gep.mul.2, align 4 ->
267; CHECK-NEXT:            store i32 %add, ptr %gep, align 4
268; CHECK-EMPTY:
269; CHECK-NEXT:      Run-time memory checks:
270; CHECK-NEXT:      Grouped accesses:
271; CHECK-EMPTY:
272; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
273; CHECK-NEXT:      SCEV assumptions:
274; CHECK-EMPTY:
275; CHECK-NEXT:      Expressions re-written:
276;
277entry:
278  br label %loop
279
280loop:
281  %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ]
282  %iv.2 = phi i64 [ 600, %entry ], [ %iv.2.next, %loop ]
283  %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.1
284  %l = load i32, ptr %gep.mul.2, align 4
285  %add = add nsw i32 %l, 5
286  %gep = getelementptr inbounds i32, ptr %A, i64 %iv.2
287  store i32 %add, ptr %gep, align 4
288  %iv.1.next = add nuw nsw i64 %iv.1, 1
289  %iv.2.next = add nsw i64 %iv.2, -2
290  %exitcond.not = icmp eq i64 %iv.1.next, 256
291  br i1 %exitcond.not, label %exit, label %loop
292
293exit:
294  ret void
295}
296
297define void @strides_with_different_directions_4(ptr %A) {
298; CHECK-LABEL: 'strides_with_different_directions_4'
299; CHECK-NEXT:    loop:
300; CHECK-NEXT:      Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
301; CHECK-NEXT:  Unknown data dependence.
302; CHECK-NEXT:      Dependences:
303; CHECK-NEXT:        Unknown:
304; CHECK-NEXT:            %l = load i32, ptr %gep.mul.2, align 4 ->
305; CHECK-NEXT:            store i32 %add, ptr %gep, align 4
306; CHECK-EMPTY:
307; CHECK-NEXT:      Run-time memory checks:
308; CHECK-NEXT:      Grouped accesses:
309; CHECK-EMPTY:
310; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
311; CHECK-NEXT:      SCEV assumptions:
312; CHECK-EMPTY:
313; CHECK-NEXT:      Expressions re-written:
314;
315entry:
316  br label %loop
317
318loop:
319  %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ]
320  %iv.2 = phi i64 [ 600, %entry ], [ %iv.2.next, %loop ]
321  %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.2
322  %l = load i32, ptr %gep.mul.2, align 4
323  %add = add nsw i32 %l, 5
324  %gep = getelementptr inbounds i32, ptr %A, i64 %iv.1
325  store i32 %add, ptr %gep, align 4
326  %iv.1.next = add nuw nsw i64 %iv.1, 1
327  %iv.2.next = add nsw i64 %iv.2, -2
328  %exitcond.not = icmp eq i64 %iv.1.next, 256
329  br i1 %exitcond.not, label %exit, label %loop
330
331exit:
332  ret void
333}
334
335define void @non_constant_strides_with_different_directions_1(ptr %A) {
336; CHECK-LABEL: 'non_constant_strides_with_different_directions_1'
337; CHECK-NEXT:    loop:
338; CHECK-NEXT:      Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
339; CHECK-NEXT:  Unknown data dependence.
340; CHECK-NEXT:      Dependences:
341; CHECK-NEXT:        Unknown:
342; CHECK-NEXT:            %l = load i32, ptr %gep.mul.2, align 4 ->
343; CHECK-NEXT:            store i32 %add, ptr %gep, align 4
344; CHECK-EMPTY:
345; CHECK-NEXT:      Run-time memory checks:
346; CHECK-NEXT:      Grouped accesses:
347; CHECK-EMPTY:
348; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
349; CHECK-NEXT:      SCEV assumptions:
350; CHECK-EMPTY:
351; CHECK-NEXT:      Expressions re-written:
352;
353entry:
354  br label %loop
355
356loop:
357  %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ]
358  %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ]
359  %iv.mul.2 = shl nuw nsw i64 %iv.1, 1
360  %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
361  %l = load i32, ptr %gep.mul.2, align 4
362  %add = add nsw i32 %l, 5
363  %gep = getelementptr inbounds i32, ptr %A, i64 %iv.2
364  store i32 %add, ptr %gep, align 4
365  %iv.1.next = add nuw nsw i64 %iv.1, 1
366  %iv.2.next = add nsw i64 %iv.2, -1
367  %exitcond.not = icmp eq i64 %iv.1.next, 256
368  br i1 %exitcond.not, label %exit, label %loop
369
370exit:
371  ret void
372}
373
374define void @non_constant_strides_with_different_directions_2(ptr %A) {
375; CHECK-LABEL: 'non_constant_strides_with_different_directions_2'
376; CHECK-NEXT:    loop:
377; CHECK-NEXT:      Report: unsafe dependent memory operations in loop. Use #pragma clang loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
378; CHECK-NEXT:  Unknown data dependence.
379; CHECK-NEXT:      Dependences:
380; CHECK-NEXT:        Unknown:
381; CHECK-NEXT:            %l = load i32, ptr %gep.mul.2, align 4 ->
382; CHECK-NEXT:            store i32 %add, ptr %gep, align 4
383; CHECK-EMPTY:
384; CHECK-NEXT:      Run-time memory checks:
385; CHECK-NEXT:      Grouped accesses:
386; CHECK-EMPTY:
387; CHECK-NEXT:      Non vectorizable stores to invariant address were not found in loop.
388; CHECK-NEXT:      SCEV assumptions:
389; CHECK-EMPTY:
390; CHECK-NEXT:      Expressions re-written:
391;
392entry:
393  br label %loop
394
395loop:
396  %iv.1 = phi i64 [ 0, %entry ], [ %iv.1.next, %loop ]
397  %iv.2 = phi i64 [ 300, %entry ], [ %iv.2.next, %loop ]
398  %iv.mul.2 = shl nuw nsw i64 %iv.2, 1
399  %gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
400  %l = load i32, ptr %gep.mul.2, align 4
401  %add = add nsw i32 %l, 5
402  %gep = getelementptr inbounds i32, ptr %A, i64 %iv.1
403  store i32 %add, ptr %gep, align 4
404  %iv.1.next = add nuw nsw i64 %iv.1, 1
405  %iv.2.next = add nsw i64 %iv.2, -1
406  %exitcond.not = icmp eq i64 %iv.1.next, 256
407  br i1 %exitcond.not, label %exit, label %loop
408
409exit:
410  ret void
411}
412