Skip to content

Commit 977c0a6

Browse files
committed
[LAA] Add tests with non-constant strides & distances.
Add a number of LAA test cases with both forward and backward dependences with non-constant strides and dependence distances. This includes test coverage for #87336 Also includes a LoopLoadElimination test to make sure the pass does not crash on non-constant dependence distances.
1 parent ea2392e commit 977c0a6

File tree

4 files changed

+736
-0
lines changed

4 files changed

+736
-0
lines changed
Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
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+
4+
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
5+
6+
declare void @llvm.assume(i1)
7+
8+
define void @different_non_constant_strides_known_backward(ptr %A) {
9+
; CHECK-LABEL: 'different_non_constant_strides_known_backward'
10+
; CHECK-NEXT: loop:
11+
; 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
12+
; CHECK-NEXT: Unknown data dependence.
13+
; CHECK-NEXT: Dependences:
14+
; CHECK-NEXT: Unknown:
15+
; CHECK-NEXT: %l = load i32, ptr %gep, align 4 ->
16+
; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, align 4
17+
; CHECK-EMPTY:
18+
; CHECK-NEXT: Run-time memory checks:
19+
; CHECK-NEXT: Grouped accesses:
20+
; CHECK-EMPTY:
21+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
22+
; CHECK-NEXT: SCEV assumptions:
23+
; CHECK-EMPTY:
24+
; CHECK-NEXT: Expressions re-written:
25+
;
26+
entry:
27+
br label %loop
28+
29+
loop:
30+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
31+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
32+
%l = load i32, ptr %gep, align 4
33+
%add = add nsw i32 %l, 5
34+
%iv.mul.2 = shl nuw nsw i64 %iv, 1
35+
%gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
36+
store i32 %add, ptr %gep.mul.2, align 4
37+
%iv.next = add nuw nsw i64 %iv, 1
38+
%exitcond.not = icmp eq i64 %iv.next, 256
39+
br i1 %exitcond.not, label %exit, label %loop
40+
41+
exit:
42+
ret void
43+
}
44+
45+
define void @different_non_constant_strides_known_backward_distance_larger_than_trip_count(ptr %A) {
46+
; CHECK-LABEL: 'different_non_constant_strides_known_backward_distance_larger_than_trip_count'
47+
; CHECK-NEXT: loop:
48+
; 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
49+
; CHECK-NEXT: Unknown data dependence.
50+
; CHECK-NEXT: Dependences:
51+
; CHECK-NEXT: Unknown:
52+
; CHECK-NEXT: %l = load i32, ptr %gep, align 4 ->
53+
; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, align 4
54+
; CHECK-EMPTY:
55+
; CHECK-NEXT: Run-time memory checks:
56+
; CHECK-NEXT: Grouped accesses:
57+
; CHECK-EMPTY:
58+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
59+
; CHECK-NEXT: SCEV assumptions:
60+
; CHECK-EMPTY:
61+
; CHECK-NEXT: Expressions re-written:
62+
;
63+
entry:
64+
%A.1024 = getelementptr inbounds i8, ptr %A, i64 1024
65+
br label %loop
66+
67+
loop:
68+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
69+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
70+
%l = load i32, ptr %gep, align 4
71+
%add = add nsw i32 %l, 5
72+
%iv.mul.2 = shl nuw nsw i64 %iv, 1
73+
%gep.mul.2 = getelementptr inbounds i32, ptr %A.1024, i64 %iv.mul.2
74+
store i32 %add, ptr %gep.mul.2, align 4
75+
%iv.next = add nuw nsw i64 %iv, 1
76+
%exitcond.not = icmp eq i64 %iv.next, 256
77+
br i1 %exitcond.not, label %exit, label %loop
78+
79+
exit:
80+
ret void
81+
}
82+
83+
define void @different_non_constant_strides_known_backward_min_distance_16(ptr %A) {
84+
; CHECK-LABEL: 'different_non_constant_strides_known_backward_min_distance_16'
85+
; CHECK-NEXT: loop:
86+
; 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
87+
; CHECK-NEXT: Unknown data dependence.
88+
; CHECK-NEXT: Dependences:
89+
; CHECK-NEXT: Unknown:
90+
; CHECK-NEXT: %l = load i32, ptr %gep, align 4 ->
91+
; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, align 4
92+
; CHECK-EMPTY:
93+
; CHECK-NEXT: Run-time memory checks:
94+
; CHECK-NEXT: Grouped accesses:
95+
; CHECK-EMPTY:
96+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
97+
; CHECK-NEXT: SCEV assumptions:
98+
; CHECK-EMPTY:
99+
; CHECK-NEXT: Expressions re-written:
100+
;
101+
entry:
102+
%A.16 = getelementptr inbounds i8, ptr %A, i64 16
103+
br label %loop
104+
105+
loop:
106+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
107+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
108+
%l = load i32, ptr %gep, align 4
109+
%add = add nsw i32 %l, 5
110+
%iv.mul.2 = shl nuw nsw i64 %iv, 1
111+
%gep.mul.2 = getelementptr inbounds i32, ptr %A.16, i64 %iv.mul.2
112+
store i32 %add, ptr %gep.mul.2, align 4
113+
%iv.next = add nuw nsw i64 %iv, 1
114+
%exitcond.not = icmp eq i64 %iv.next, 256
115+
br i1 %exitcond.not, label %exit, label %loop
116+
117+
exit:
118+
ret void
119+
}
120+
121+
define void @different_non_constant_strides_known_backward_min_distance_15(ptr %A) {
122+
; CHECK-LABEL: 'different_non_constant_strides_known_backward_min_distance_15'
123+
; CHECK-NEXT: loop:
124+
; 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
125+
; CHECK-NEXT: Unknown data dependence.
126+
; CHECK-NEXT: Dependences:
127+
; CHECK-NEXT: Unknown:
128+
; CHECK-NEXT: %l = load i32, ptr %gep, align 4 ->
129+
; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, align 4
130+
; CHECK-EMPTY:
131+
; CHECK-NEXT: Run-time memory checks:
132+
; CHECK-NEXT: Grouped accesses:
133+
; CHECK-EMPTY:
134+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
135+
; CHECK-NEXT: SCEV assumptions:
136+
; CHECK-EMPTY:
137+
; CHECK-NEXT: Expressions re-written:
138+
;
139+
entry:
140+
%A.15 = getelementptr inbounds i8, ptr %A, i64 15
141+
br label %loop
142+
143+
loop:
144+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
145+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
146+
%l = load i32, ptr %gep, align 4
147+
%add = add nsw i32 %l, 5
148+
%iv.mul.2 = shl nuw nsw i64 %iv, 1
149+
%gep.mul.2 = getelementptr inbounds i32, ptr %A.15, i64 %iv.mul.2
150+
store i32 %add, ptr %gep.mul.2, align 4
151+
%iv.next = add nuw nsw i64 %iv, 1
152+
%exitcond.not = icmp eq i64 %iv.next, 256
153+
br i1 %exitcond.not, label %exit, label %loop
154+
155+
exit:
156+
ret void
157+
}
158+
159+
define void @different_non_constant_strides_known_backward_min_distance_8(ptr %A) {
160+
; CHECK-LABEL: 'different_non_constant_strides_known_backward_min_distance_8'
161+
; CHECK-NEXT: loop:
162+
; 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
163+
; CHECK-NEXT: Unknown data dependence.
164+
; CHECK-NEXT: Dependences:
165+
; CHECK-NEXT: Unknown:
166+
; CHECK-NEXT: %l = load i32, ptr %gep, align 4 ->
167+
; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, align 4
168+
; CHECK-EMPTY:
169+
; CHECK-NEXT: Run-time memory checks:
170+
; CHECK-NEXT: Grouped accesses:
171+
; CHECK-EMPTY:
172+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
173+
; CHECK-NEXT: SCEV assumptions:
174+
; CHECK-EMPTY:
175+
; CHECK-NEXT: Expressions re-written:
176+
;
177+
entry:
178+
%A.8 = getelementptr inbounds i8, ptr %A, i64 8
179+
br label %loop
180+
181+
loop:
182+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
183+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
184+
%l = load i32, ptr %gep, align 4
185+
%add = add nsw i32 %l, 5
186+
%iv.mul.2 = shl nuw nsw i64 %iv, 1
187+
%gep.mul.2 = getelementptr inbounds i32, ptr %A.8, i64 %iv.mul.2
188+
store i32 %add, ptr %gep.mul.2, align 4
189+
%iv.next = add nuw nsw i64 %iv, 1
190+
%exitcond.not = icmp eq i64 %iv.next, 256
191+
br i1 %exitcond.not, label %exit, label %loop
192+
193+
exit:
194+
ret void
195+
}
196+
197+
define void @different_non_constant_strides_known_backward_min_distance_3(ptr %A) {
198+
; CHECK-LABEL: 'different_non_constant_strides_known_backward_min_distance_3'
199+
; CHECK-NEXT: loop:
200+
; 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
201+
; CHECK-NEXT: Unknown data dependence.
202+
; CHECK-NEXT: Dependences:
203+
; CHECK-NEXT: Unknown:
204+
; CHECK-NEXT: %l = load i32, ptr %gep, align 4 ->
205+
; CHECK-NEXT: store i32 %add, ptr %gep.mul.2, align 4
206+
; CHECK-EMPTY:
207+
; CHECK-NEXT: Run-time memory checks:
208+
; CHECK-NEXT: Grouped accesses:
209+
; CHECK-EMPTY:
210+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
211+
; CHECK-NEXT: SCEV assumptions:
212+
; CHECK-EMPTY:
213+
; CHECK-NEXT: Expressions re-written:
214+
;
215+
entry:
216+
%A.3 = getelementptr inbounds i8, ptr %A, i64 3
217+
br label %loop
218+
219+
loop:
220+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
221+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
222+
%l = load i32, ptr %gep, align 4
223+
%add = add nsw i32 %l, 5
224+
%iv.mul.2 = shl nuw nsw i64 %iv, 1
225+
%gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2
226+
store i32 %add, ptr %gep.mul.2, align 4
227+
%iv.next = add nuw nsw i64 %iv, 1
228+
%exitcond.not = icmp eq i64 %iv.next, 256
229+
br i1 %exitcond.not, label %exit, label %loop
230+
231+
exit:
232+
ret void
233+
}
234+
235+
define void @different_non_constant_strides_known_backward_via_assume(ptr %A, i64 %scale) {
236+
; CHECK-LABEL: 'different_non_constant_strides_known_backward_via_assume'
237+
; CHECK-NEXT: loop:
238+
; CHECK-NEXT: Report: cannot identify array bounds
239+
; CHECK-NEXT: Dependences:
240+
; CHECK-NEXT: Run-time memory checks:
241+
; CHECK-NEXT: Grouped accesses:
242+
; CHECK-EMPTY:
243+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
244+
; CHECK-NEXT: SCEV assumptions:
245+
; CHECK-EMPTY:
246+
; CHECK-NEXT: Expressions re-written:
247+
;
248+
entry:
249+
%c = icmp sgt i64 %scale, 0
250+
call void @llvm.assume(i1 %c)
251+
br label %loop
252+
253+
loop:
254+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
255+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
256+
%l = load i32, ptr %gep, align 4
257+
%add = add nsw i32 %l, 5
258+
%iv.mul.2 = shl nuw nsw i64 %iv, %scale
259+
%gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
260+
store i32 %add, ptr %gep.mul.2, align 4
261+
%iv.next = add nuw nsw i64 %iv, 1
262+
%exitcond.not = icmp eq i64 %iv.next, 256
263+
br i1 %exitcond.not, label %exit, label %loop
264+
265+
exit:
266+
ret void
267+
}
268+
269+
define void @different_non_constant_strides_known_backward_via_assume_distance_larger_than_trip_count(ptr %A, i64 %scale) {
270+
; CHECK-LABEL: 'different_non_constant_strides_known_backward_via_assume_distance_larger_than_trip_count'
271+
; CHECK-NEXT: loop:
272+
; CHECK-NEXT: Report: cannot identify array bounds
273+
; CHECK-NEXT: Dependences:
274+
; CHECK-NEXT: Run-time memory checks:
275+
; CHECK-NEXT: Grouped accesses:
276+
; CHECK-EMPTY:
277+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
278+
; CHECK-NEXT: SCEV assumptions:
279+
; CHECK-EMPTY:
280+
; CHECK-NEXT: Expressions re-written:
281+
;
282+
entry:
283+
%A.1024 = getelementptr inbounds i8, ptr %A, i64 1024
284+
%c = icmp sgt i64 %scale, 0
285+
call void @llvm.assume(i1 %c)
286+
br label %loop
287+
288+
loop:
289+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
290+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
291+
%l = load i32, ptr %gep, align 4
292+
%add = add nsw i32 %l, 5
293+
%iv.mul.2 = shl nuw nsw i64 %iv, %scale
294+
%gep.mul.2 = getelementptr inbounds i32, ptr %A.1024, i64 %iv.mul.2
295+
store i32 %add, ptr %gep.mul.2, align 4
296+
%iv.next = add nuw nsw i64 %iv, 1
297+
%exitcond.not = icmp eq i64 %iv.next, 256
298+
br i1 %exitcond.not, label %exit, label %loop
299+
300+
exit:
301+
ret void
302+
}
303+
304+
define void @different_non_constant_strides_known_backward_via_assume_min_distance_3(ptr %A, i64 %scale) {
305+
; CHECK-LABEL: 'different_non_constant_strides_known_backward_via_assume_min_distance_3'
306+
; CHECK-NEXT: loop:
307+
; CHECK-NEXT: Report: cannot identify array bounds
308+
; CHECK-NEXT: Dependences:
309+
; CHECK-NEXT: Run-time memory checks:
310+
; CHECK-NEXT: Grouped accesses:
311+
; CHECK-EMPTY:
312+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
313+
; CHECK-NEXT: SCEV assumptions:
314+
; CHECK-EMPTY:
315+
; CHECK-NEXT: Expressions re-written:
316+
;
317+
entry:
318+
%A.3 = getelementptr inbounds i8, ptr %A, i64 3
319+
%c = icmp sgt i64 %scale, 0
320+
call void @llvm.assume(i1 %c)
321+
br label %loop
322+
323+
loop:
324+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
325+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
326+
%l = load i32, ptr %gep, align 4
327+
%add = add nsw i32 %l, 5
328+
%iv.mul.2 = shl nuw nsw i64 %iv, %scale
329+
%gep.mul.2 = getelementptr inbounds i32, ptr %A.3, i64 %iv.mul.2
330+
store i32 %add, ptr %gep.mul.2, align 4
331+
%iv.next = add nuw nsw i64 %iv, 1
332+
%exitcond.not = icmp eq i64 %iv.next, 256
333+
br i1 %exitcond.not, label %exit, label %loop
334+
335+
exit:
336+
ret void
337+
}
338+
339+
define void @different_non_constant_strides_not_known_backward(ptr %A, i64 %scale) {
340+
; CHECK-LABEL: 'different_non_constant_strides_not_known_backward'
341+
; CHECK-NEXT: loop:
342+
; CHECK-NEXT: Report: cannot identify array bounds
343+
; CHECK-NEXT: Dependences:
344+
; CHECK-NEXT: Run-time memory checks:
345+
; CHECK-NEXT: Grouped accesses:
346+
; CHECK-EMPTY:
347+
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
348+
; CHECK-NEXT: SCEV assumptions:
349+
; CHECK-EMPTY:
350+
; CHECK-NEXT: Expressions re-written:
351+
;
352+
entry:
353+
br label %loop
354+
355+
loop:
356+
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
357+
%gep = getelementptr inbounds i32, ptr %A, i64 %iv
358+
%l = load i32, ptr %gep, align 4
359+
%add = add nsw i32 %l, 5
360+
%iv.mul.2 = shl nuw nsw i64 %iv, %scale
361+
%gep.mul.2 = getelementptr inbounds i32, ptr %A, i64 %iv.mul.2
362+
store i32 %add, ptr %gep.mul.2, align 4
363+
%iv.next = add nuw nsw i64 %iv, 1
364+
%exitcond.not = icmp eq i64 %iv.next, 256
365+
br i1 %exitcond.not, label %exit, label %loop
366+
367+
exit:
368+
ret void
369+
}

0 commit comments

Comments
 (0)