1 ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 3
2 ; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s
4 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
6 ; Test cases for https://github.com/llvm/llvm-project/issues/69744.
7 ; Note that both loops in the tests are needed to incorrectly determine that
8 ; the loops are safe with runtime checks via FoundNonConstantDistanceDependence
9 ; handling code in LAA.
11 define void @test_indirect_read_write_loop_also_modifies_pointer_array(ptr noundef %arr) {
12 ; CHECK-LABEL: 'test_indirect_read_write_loop_also_modifies_pointer_array'
14 ; CHECK-NEXT: Report: could not determine number of loop iterations
15 ; CHECK-NEXT: Dependences:
16 ; CHECK-NEXT: Run-time memory checks:
17 ; CHECK-NEXT: Grouped accesses:
19 ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
20 ; CHECK-NEXT: SCEV assumptions:
22 ; CHECK-NEXT: Expressions re-written:
24 ; 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
25 ; CHECK-NEXT: Unsafe indirect dependence.
26 ; CHECK-NEXT: Dependences:
27 ; CHECK-NEXT: IndirectUnsafe:
28 ; CHECK-NEXT: %l.2 = load i64, ptr %l.1, align 8, !tbaa !4 ->
29 ; CHECK-NEXT: store i64 %inc, ptr %l.1, align 8, !tbaa !4
31 ; CHECK-NEXT: Unknown:
32 ; CHECK-NEXT: %l.1 = load ptr, ptr %gep.iv.1, align 8, !tbaa !0 ->
33 ; CHECK-NEXT: store ptr %l.1, ptr %gep.iv.2, align 8, !tbaa !0
35 ; CHECK-NEXT: Run-time memory checks:
36 ; CHECK-NEXT: Grouped accesses:
38 ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
39 ; CHECK-NEXT: SCEV assumptions:
41 ; CHECK-NEXT: Expressions re-written:
47 %iv = phi i64 [ %iv.next, %loop.1 ], [ 8, %entry ]
48 %arr.addr.0.i = phi ptr [ %incdec.ptr.i, %loop.1 ], [ %arr, %entry ]
49 %incdec.ptr.i = getelementptr inbounds ptr, ptr %arr.addr.0.i, i64 1
50 %0 = load ptr, ptr %arr.addr.0.i, align 8, !tbaa !6
51 %tobool.not.i = icmp eq ptr %0, null
52 %iv.next = add i64 %iv, 8
53 br i1 %tobool.not.i, label %loop.1.exit, label %loop.1
56 %iv.lcssa = phi i64 [ %iv, %loop.1 ]
60 %iv.1 = phi i64 [ 0, %loop.1.exit ], [ %iv.1.next, %loop.2 ]
61 %iv.2 = phi i64 [ %iv.lcssa, %loop.1.exit ], [ %iv.2.next, %loop.2 ]
62 %gep.iv.1 = getelementptr inbounds ptr, ptr %arr, i64 %iv.1
63 %l.1 = load ptr, ptr %gep.iv.1, align 8, !tbaa !6
64 %l.2 = load i64, ptr %l.1, align 8, !tbaa !13
65 %inc = add i64 %l.2, 1
66 store i64 %inc, ptr %l.1, align 8, !tbaa !13
67 %iv.2.next = add nsw i64 %iv.2, 1
68 %gep.iv.2 = getelementptr inbounds ptr, ptr %arr, i64 %iv.2
69 store ptr %l.1, ptr %gep.iv.2, align 8, !tbaa !6
70 %iv.1.next = add nuw nsw i64 %iv.1, 1
71 %cmp = icmp ult i64 %iv.1.next, 1000
72 br i1 %cmp, label %loop.2, label %exit
78 define void @test_indirect_read_loop_also_modifies_pointer_array(ptr noundef %arr) {
79 ; CHECK-LABEL: 'test_indirect_read_loop_also_modifies_pointer_array'
81 ; CHECK-NEXT: Report: could not determine number of loop iterations
82 ; CHECK-NEXT: Dependences:
83 ; CHECK-NEXT: Run-time memory checks:
84 ; CHECK-NEXT: Grouped accesses:
86 ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
87 ; CHECK-NEXT: SCEV assumptions:
89 ; CHECK-NEXT: Expressions re-written:
91 ; CHECK-NEXT: Memory dependences are safe with run-time checks
92 ; CHECK-NEXT: Dependences:
93 ; CHECK-NEXT: Run-time memory checks:
94 ; CHECK-NEXT: Check 0:
95 ; CHECK-NEXT: Comparing group ([[GRP1:0x[0-9a-f]+]]):
96 ; CHECK-NEXT: %gep.iv.2 = getelementptr inbounds i64, ptr %arr, i64 %iv.2
97 ; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]):
98 ; CHECK-NEXT: %gep.iv.1 = getelementptr inbounds ptr, ptr %arr, i64 %iv.1
99 ; CHECK-NEXT: Grouped accesses:
100 ; CHECK-NEXT: Group [[GRP1]]:
101 ; CHECK-NEXT: (Low: {(64 + %arr),+,64}<%loop.1> High: {(8064 + %arr),+,64}<%loop.1>)
102 ; CHECK-NEXT: Member: {{\{\{}}(64 + %arr),+,64}<%loop.1>,+,8}<%loop.2>
103 ; CHECK-NEXT: Group [[GRP2]]:
104 ; CHECK-NEXT: (Low: %arr High: (8000 + %arr))
105 ; CHECK-NEXT: Member: {%arr,+,8}<nuw><%loop.2>
107 ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
108 ; CHECK-NEXT: SCEV assumptions:
110 ; CHECK-NEXT: Expressions re-written:
116 %iv = phi i64 [ %iv.next, %loop.1 ], [ 8, %entry ]
117 %arr.addr.0.i = phi ptr [ %incdec.ptr.i, %loop.1 ], [ %arr, %entry ]
118 %incdec.ptr.i = getelementptr inbounds ptr, ptr %arr.addr.0.i, i64 1
119 %0 = load ptr, ptr %arr.addr.0.i, align 8, !tbaa !6
120 %tobool.not.i = icmp eq ptr %0, null
121 %iv.next = add i64 %iv, 8
122 br i1 %tobool.not.i, label %loop.1.exit, label %loop.1
125 %iv.lcssa = phi i64 [ %iv, %loop.1 ]
129 %iv.1 = phi i64 [ 0, %loop.1.exit ], [ %iv.1.next, %loop.2 ]
130 %iv.2 = phi i64 [ %iv.lcssa, %loop.1.exit ], [ %iv.2.next, %loop.2 ]
131 %gep.iv.1 = getelementptr inbounds ptr, ptr %arr, i64 %iv.1
132 %l.1 = load ptr, ptr %gep.iv.1, align 8, !tbaa !6
133 %l.2 = load i64, ptr %l.1, align 8, !tbaa !13
134 %inc = add i64 %l.2, 1
135 %iv.2.next = add nsw i64 %iv.2, 1
136 %gep.iv.2 = getelementptr inbounds i64, ptr %arr, i64 %iv.2
137 store i64 %l.2, ptr %gep.iv.2, align 8, !tbaa !6
138 %iv.1.next = add nuw nsw i64 %iv.1, 1
139 %cmp = icmp ult i64 %iv.1.next, 1000
140 br i1 %cmp, label %loop.2, label %exit
146 define void @test_indirect_write_loop_also_modifies_pointer_array(ptr noundef %arr) {
147 ; CHECK-LABEL: 'test_indirect_write_loop_also_modifies_pointer_array'
148 ; CHECK-NEXT: loop.1:
149 ; CHECK-NEXT: Report: could not determine number of loop iterations
150 ; CHECK-NEXT: Dependences:
151 ; CHECK-NEXT: Run-time memory checks:
152 ; CHECK-NEXT: Grouped accesses:
154 ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
155 ; CHECK-NEXT: SCEV assumptions:
157 ; CHECK-NEXT: Expressions re-written:
158 ; CHECK-NEXT: loop.2:
159 ; CHECK-NEXT: Memory dependences are safe with run-time checks
160 ; CHECK-NEXT: Dependences:
161 ; CHECK-NEXT: Run-time memory checks:
162 ; CHECK-NEXT: Check 0:
163 ; CHECK-NEXT: Comparing group ([[GRP3:0x[0-9a-f]+]]):
164 ; CHECK-NEXT: %gep.iv.2 = getelementptr inbounds ptr, ptr %arr, i64 %iv.2
165 ; CHECK-NEXT: Against group ([[GRP4:0x[0-9a-f]+]]):
166 ; CHECK-NEXT: %gep.iv.1 = getelementptr inbounds ptr, ptr %arr, i64 %iv.1
167 ; CHECK-NEXT: Grouped accesses:
168 ; CHECK-NEXT: Group [[GRP3]]:
169 ; CHECK-NEXT: (Low: {(64 + %arr),+,64}<%loop.1> High: {(8064 + %arr),+,64}<%loop.1>)
170 ; CHECK-NEXT: Member: {{\{\{}}(64 + %arr),+,64}<%loop.1>,+,8}<%loop.2>
171 ; CHECK-NEXT: Group [[GRP4]]:
172 ; CHECK-NEXT: (Low: %arr High: (8000 + %arr))
173 ; CHECK-NEXT: Member: {%arr,+,8}<nuw><%loop.2>
175 ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
176 ; CHECK-NEXT: SCEV assumptions:
178 ; CHECK-NEXT: Expressions re-written:
184 %iv = phi i64 [ %iv.next, %loop.1 ], [ 8, %entry ]
185 %arr.addr.0.i = phi ptr [ %incdec.ptr.i, %loop.1 ], [ %arr, %entry ]
186 %incdec.ptr.i = getelementptr inbounds ptr, ptr %arr.addr.0.i, i64 1
187 %0 = load ptr, ptr %arr.addr.0.i, align 8, !tbaa !6
188 %tobool.not.i = icmp eq ptr %0, null
189 %iv.next = add i64 %iv, 8
190 br i1 %tobool.not.i, label %loop.1.exit, label %loop.1
193 %iv.lcssa = phi i64 [ %iv, %loop.1 ]
197 %iv.1 = phi i64 [ 0, %loop.1.exit ], [ %iv.1.next, %loop.2 ]
198 %iv.2 = phi i64 [ %iv.lcssa, %loop.1.exit ], [ %iv.2.next, %loop.2 ]
199 %gep.iv.1 = getelementptr inbounds ptr, ptr %arr, i64 %iv.1
200 %l.1 = load ptr, ptr %gep.iv.1, align 8, !tbaa !6
201 %inc = add i64 %iv.1, 1
202 store i64 %inc, ptr %l.1, align 8, !tbaa !13
203 %iv.2.next = add nsw i64 %iv.2, 1
204 %gep.iv.2 = getelementptr inbounds ptr, ptr %arr, i64 %iv.2
205 store ptr %l.1, ptr %gep.iv.2, align 8, !tbaa !6
206 %iv.1.next = add nuw nsw i64 %iv.1, 1
207 %cmp = icmp ult i64 %iv.1.next, 1000
208 br i1 %cmp, label %loop.2, label %exit
214 ; FIXME: Not safe with runtime checks due to the indirect pointers are modified
216 define void @test_indirect_read_write_loop_does_not_modify_pointer_array(ptr noundef %arr, ptr noundef noalias %arr2) {
217 ; CHECK-LABEL: 'test_indirect_read_write_loop_does_not_modify_pointer_array'
218 ; CHECK-NEXT: loop.1:
219 ; CHECK-NEXT: Report: could not determine number of loop iterations
220 ; CHECK-NEXT: Dependences:
221 ; CHECK-NEXT: Run-time memory checks:
222 ; CHECK-NEXT: Grouped accesses:
224 ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
225 ; CHECK-NEXT: SCEV assumptions:
227 ; CHECK-NEXT: Expressions re-written:
228 ; CHECK-NEXT: loop.2:
229 ; 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
230 ; CHECK-NEXT: Unsafe indirect dependence.
231 ; CHECK-NEXT: Dependences:
232 ; CHECK-NEXT: IndirectUnsafe:
233 ; CHECK-NEXT: %l.2 = load i64, ptr %l.1, align 8, !tbaa !4 ->
234 ; CHECK-NEXT: store i64 %inc, ptr %l.1, align 8, !tbaa !4
236 ; CHECK-NEXT: Unknown:
237 ; CHECK-NEXT: %l.3 = load i64, ptr %gep.arr2.iv.1, align 8 ->
238 ; CHECK-NEXT: store i64 %inc.2, ptr %gep.arr2.iv.2, align 8, !tbaa !0
240 ; CHECK-NEXT: Run-time memory checks:
241 ; CHECK-NEXT: Grouped accesses:
243 ; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
244 ; CHECK-NEXT: SCEV assumptions:
246 ; CHECK-NEXT: Expressions re-written:
252 %iv = phi i64 [ %iv.next, %loop.1 ], [ 8, %entry ]
253 %arr.addr.0.i = phi ptr [ %incdec.ptr.i, %loop.1 ], [ %arr, %entry ]
254 %incdec.ptr.i = getelementptr inbounds ptr, ptr %arr.addr.0.i, i64 1
255 %0 = load ptr, ptr %arr.addr.0.i, align 8, !tbaa !6
256 %tobool.not.i = icmp eq ptr %0, null
257 %iv.next = add i64 %iv, 8
258 br i1 %tobool.not.i, label %loop.1.exit, label %loop.1
261 %iv.lcssa = phi i64 [ %iv, %loop.1 ]
265 %iv.1 = phi i64 [ 0, %loop.1.exit ], [ %iv.1.next, %loop.2 ]
266 %iv.2 = phi i64 [ %iv.lcssa, %loop.1.exit ], [ %iv.2.next, %loop.2 ]
267 %gep.iv.1 = getelementptr inbounds ptr, ptr %arr, i64 %iv.1
268 %l.1 = load ptr, ptr %gep.iv.1, align 8, !tbaa !6
269 %l.2 = load i64, ptr %l.1, align 8, !tbaa !13
270 %inc = add i64 %l.2, 1
271 store i64 %inc, ptr %l.1, align 8, !tbaa !13
272 %iv.2.next = add nsw i64 %iv.2, 1
273 %gep.arr2.iv.1 = getelementptr inbounds i64 , ptr %arr2, i64 %iv.1
274 %gep.arr2.iv.2 = getelementptr inbounds i64 , ptr %arr2, i64 %iv.2
275 %l.3 = load i64, ptr %gep.arr2.iv.1
276 %inc.2 = add i64 %l.3, 5
277 store i64 %inc.2, ptr %gep.arr2.iv.2, align 8, !tbaa !6
278 %iv.1.next = add nuw nsw i64 %iv.1, 1
279 %cmp = icmp ult i64 %iv.1.next, 1000
280 br i1 %cmp, label %loop.2, label %exit
286 !6 = !{!7, !7, i64 0}
287 !7 = !{!"any pointer", !8, i64 0}
288 !8 = !{!"omnipotent char", !9, i64 0}
289 !9 = !{!"Simple C/C++ TBAA"}
290 !13 = !{!14, !15, i64 0}
291 !14 = !{!"", !15, i64 0}
292 !15 = !{!"long long", !8, i64 0}