xref: /llvm-project/llvm/test/Transforms/LoopVectorize/memory-dep-remarks.ll (revision 46cb7e4eeae3a3d64d2d6ba82a6309162bbb9808)
1; RUN: opt -passes='function(loop-vectorize,require<access-info>)' -disable-output -pass-remarks-analysis=loop-vectorize < %s 2>&1 | FileCheck %s
2; RUN: opt < %s -passes='function(require<access-info>,loop-vectorize)' -o /dev/null -pass-remarks-output=%t.yaml
3; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s
4
5target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
6
7; // Loop has an array element B[i] (%arrayidx in IR) being used as index to
8; // another array (A), and since the value of B[i] is unknown,
9; // the bound for array A is unknown.
10; void test_unknown_bounds(int n, int* A, int* B) {
11;     for(int i = 0; i < n ; ++i)
12;         A[i] = A[B[i]] + 1;
13; }
14
15; CHECK: remark: source.c:4:16: loop not vectorized: cannot identify array bounds
16
17define void @test_unknown_bounds(i64 %n, ptr nocapture %A, ptr nocapture readonly %B) !dbg !13 {
18entry:
19  %cmp10 = icmp sgt i64 %n, 0
20  br i1 %cmp10, label %for.body, label %for.cond.cleanup
21
22for.body:                                         ; preds = %entry, %for.body
23  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
24  %arrayidx = getelementptr inbounds i32, ptr %B, i64 %indvars.iv
25  %0 = load i32, ptr %arrayidx, align 4
26  %idxprom1 = sext i32 %0 to i64, !dbg !35
27  %arrayidx2 = getelementptr inbounds i32, ptr %A, i64 %idxprom1, !dbg !35
28  %1 = load i32, ptr %arrayidx2, align 4, !dbg !35
29  %add = add nsw i32 %1, 1
30  %arrayidx4 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv
31  store i32 %add, ptr %arrayidx4, align 4
32  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
33  %exitcond.not = icmp eq i64 %indvars.iv.next, %n
34  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !dbg !28
35
36for.cond.cleanup:                                 ; preds = %for.body, %entry
37  ret void
38}
39
40; // a) Dependence::NoDep
41; // Loop containing only reads (here of the array A) does not hinder vectorization
42; void test_nodep(int n, int* A, int* B) {
43;   for(int i = 1; i < n ; ++i) {
44;     B[i] = A[i-1] + A[i+2];
45;   }
46; }
47
48; CHECK-NOT: remark: source.c:{{0-9]+}}:{{[0-9]+}}:
49
50define void @test_nodep(i64 %n, ptr nocapture readonly %A, ptr nocapture %B) !dbg !44 {
51entry:
52  %cmp12 = icmp sgt i64 %n, 1
53  br i1 %cmp12, label %for.body, label %for.cond.cleanup
54
55for.body:                                         ; preds = %entry, %for.body
56  %indvars.iv = phi i64 [ 1, %entry ], [ %indvars.iv.next, %for.body ]
57  %0 = add nsw i64 %indvars.iv, -1
58  %arrayidx = getelementptr inbounds i32, ptr %A, i64 %0, !dbg !61
59  %1 = load i32, ptr %arrayidx, align 4, !dbg !61
60  %2 = add nuw nsw i64 %indvars.iv, 2
61  %arrayidx2 = getelementptr inbounds i32, ptr %A, i64 %2, !dbg !63
62  %3 = load i32, ptr %arrayidx2, align 4, !dbg !63
63  %add3 = add nsw i32 %3, %1
64  %arrayidx5 = getelementptr inbounds i32, ptr %B, i64 %indvars.iv
65  store i32 %add3, ptr %arrayidx5, align 4
66  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
67  %exitcond.not = icmp eq i64 %indvars.iv.next, %n
68  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
69
70for.cond.cleanup:                                 ; preds = %for.body, %entry
71  ret void
72}
73
74
75; // b) Dependence::Forward
76; // Loop gets vectorized since it contains only a forward
77; // dependency between A[i-2] and A[i]
78; void test_forward(int n, int* A, int* B) {
79;   for(int i=1; i < n; ++i) {
80;     A[i] = 10;
81;     B[i] = A[i-2];
82;   }
83; }
84
85; CHECK-NOT: remark: source.c:{{0-9]+}}:{{[0-9]+}}:
86define dso_local void @test_forward(i64 %n, ptr nocapture %A, ptr nocapture %B) !dbg !70 {
87entry:
88  %cmp11 = icmp sgt i64 %n, 1
89  br i1 %cmp11, label %for.body, label %for.cond.cleanup, !dbg !81
90
91for.body:                                         ; preds = %entry, %for.body
92  %indvars.iv = phi i64 [ 1, %entry ], [ %indvars.iv.next, %for.body ]
93  %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv, !dbg !83
94  store i32 10, ptr %arrayidx, align 4
95  %0 = add nsw i64 %indvars.iv, -2
96  %arrayidx2 = getelementptr inbounds i32, ptr %A, i64 %0, !dbg !87
97  %1 = load i32, ptr %arrayidx2, align 4, !dbg !87
98  %arrayidx4 = getelementptr inbounds i32, ptr %B, i64 %indvars.iv, !dbg !88
99  store i32 %1, ptr %arrayidx4, align 4, !dbg !89
100  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
101  %exitcond.not = icmp eq i64 %indvars.iv.next, %n
102  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !dbg !81
103
104  for.cond.cleanup:                                 ; preds = %for.body, %entry
105    ret void
106}
107
108
109; // c) Dependence::BackwardVectorizable
110; // Loop gets vectorized since it contains a backward dependency
111; // between A[i] and A[i-4], but the dependency distance (4) is
112; // greater than the minimum possible VF (2 in this case)
113; void test_backwardVectorizable(int n, int* A) {
114;   for(int i=4; i < n; ++i) {
115;     A[i] = A[i-4] + 1;
116;   }
117; }
118
119; CHECK-NOT: remark: source.c:{{0-9]+}}:{{[0-9]+}}:
120
121define dso_local void @test_backwardVectorizable(i64 %n, ptr nocapture %A) !dbg !93 {
122entry:
123  %cmp8 = icmp sgt i64 %n, 4
124  br i1 %cmp8, label %for.body, label %for.cond.cleanup
125
126for.body:                                         ; preds = %entry, %for.body
127  %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ]
128  %0 = add nsw i64 %indvars.iv, -4, !dbg !106
129  %arrayidx = getelementptr inbounds i32, ptr %A, i64 %0, !dbg !108
130  %1 = load i32, ptr %arrayidx, align 4, !dbg !108
131  %add = add nsw i32 %1, 1
132  %arrayidx2 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv, !dbg !110
133  store i32 %add, ptr %arrayidx2, align 4, !dbg !111
134  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
135  %exitcond.not = icmp eq i64 %indvars.iv.next, %n
136  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
137
138  for.cond.cleanup:                                 ; preds = %for.body, %entry
139    ret void
140}
141
142; // d) Dependence::Backward
143; // Loop does not get vectorized since it contains a backward
144; // dependency between A[i] and A[i+3].
145; void test_backward_dep(int n, int *A) {
146;   for (int i = 1; i <= n - 3; i += 3) {
147;     A[i] = A[i-1];
148;     A[i+1] = A[i+3];
149;   }
150; }
151
152; CHECK: remark: source.c:48:14: loop not vectorized: 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
153; CHECK-NEXT: Backward loop carried data dependence. Memory location is the same as accessed at source.c:47:5
154
155define void @test_backward_dep(i64 %n, ptr nocapture %A) {
156entry:
157  %cmp.not19 = icmp slt i64 %n, 4
158  br i1 %cmp.not19, label %for.cond.cleanup, label %for.body.preheader
159
160for.body.preheader:                               ; preds = %entry
161  %sub = add nsw i64 %n, -3
162  br label %for.body
163
164for.body:                                         ; preds = %for.body.preheader, %for.body
165  %indvars.iv = phi i64 [ 1, %for.body.preheader ], [ %indvars.iv.next, %for.body ]
166  %0 = add nsw i64 %indvars.iv, -1
167  %arrayidx = getelementptr inbounds i32, ptr %A, i64 %0
168  %1 = load i32, ptr %arrayidx, align 8
169  %arrayidx3 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv, !dbg !157
170  store i32 %1, ptr %arrayidx3, align 8
171  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 3
172  %arrayidx5 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv.next, !dbg !160
173  %2 = load i32, ptr %arrayidx5, align 8, !dbg !160
174  %3 = add nuw nsw i64 %indvars.iv, 1
175  %arrayidx8 = getelementptr inbounds i32, ptr %A, i64 %3
176  store i32 %2, ptr %arrayidx8, align 8
177  %cmp.not = icmp ugt i64 %indvars.iv.next, %n
178  br i1 %cmp.not, label %for.cond.cleanup, label %for.body
179
180  for.cond.cleanup:                                 ; preds = %for.body, %entry
181    ret void
182}
183
184; // e) Dependence::ForwardButPreventsForwarding
185; // Loop does not get vectorized despite only having a forward
186; // dependency between A[i] and A[i-3].
187; // This is because the store-to-load forwarding distance (here 3)
188; // needs to be a multiple of vector factor otherwise the
189; // store (A[5:6] in i=5) and load (A[4:5],A[6:7] in i=7,9) are unaligned.
190; void test_forwardButPreventsForwarding_dep(int n, int* A, int* B) {
191;   for(int i=3; i < n; ++i) {
192;     A[i] = 10;
193;     B[i] = A[i-3];
194;   }
195; }
196
197; CHECK: remark: source.c:61:12: loop not vectorized: 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
198; CHECK-NEXT: Forward loop carried data dependence that prevents store-to-load forwarding. Memory location is the same as accessed at source.c:60:5
199
200define void @test_forwardButPreventsForwarding_dep(i64 %n, ptr nocapture %A, ptr nocapture %B) !dbg !166 {
201entry:
202  %cmp11 = icmp sgt i64 %n, 3
203  br i1 %cmp11, label %for.body, label %for.cond.cleanup
204
205for.body:                                         ; preds = %entry, %for.body
206  %indvars.iv = phi i64 [ 3, %entry ], [ %indvars.iv.next, %for.body ]
207  %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv, !dbg !179
208  store i32 10, ptr %arrayidx, align 4
209  %0 = add nsw i64 %indvars.iv, -3
210  %arrayidx2 = getelementptr inbounds i32, ptr %A, i64 %0, !dbg !183
211  %1 = load i32, ptr %arrayidx2, align 4, !dbg !183
212  %arrayidx4 = getelementptr inbounds i32, ptr %B, i64 %indvars.iv
213  store i32 %1, ptr %arrayidx4, align 4
214  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
215  %exitcond.not = icmp eq i64 %indvars.iv.next, %n
216  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
217
218  for.cond.cleanup:                                 ; preds = %for.body, %entry
219    ret void
220}
221
222; // f) Dependence::BackwardVectorizableButPreventsForwarding
223; // Loop does not get vectorized despite having a backward
224; // but vectorizable dependency between A[i] and A[i-15].
225; //
226; // This is because the store-to-load forwarding distance (here 15)
227; // needs to be a multiple of vector factor otherwise
228; // store (A[16:17] in i=16) and load (A[15:16], A[17:18] in i=30,32) are unaligned.
229; void test_backwardVectorizableButPreventsForwarding(int n, int* A) {
230;   for(int i=15; i < n; ++i) {
231;     A[i] = A[i-2] + A[i-15];
232;   }
233; }
234
235; CHECK: remark: source.c:74:5: loop not vectorized: 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
236; CHECK: Backward loop carried data dependence that prevents store-to-load forwarding. Memory location is the same as accessed at source.c:74:21
237
238define void @test_backwardVectorizableButPreventsForwarding(i64 %n, ptr nocapture %A) !dbg !189 {
239entry:
240  %cmp13 = icmp sgt i64 %n, 15
241  br i1 %cmp13, label %for.body, label %for.cond.cleanup
242
243for.body:                                         ; preds = %entry, %for.body
244  %indvars.iv = phi i64 [ 15, %entry ], [ %indvars.iv.next, %for.body ]
245  %0 = add nsw i64 %indvars.iv, -2
246  %arrayidx = getelementptr inbounds i32, ptr %A, i64 %0
247  %1 = load i32, ptr %arrayidx, align 4
248  %2 = add nsw i64 %indvars.iv, -15
249  %arrayidx3 = getelementptr inbounds i32, ptr %A, i64 %2, !dbg !207
250  %3 = load i32, ptr %arrayidx3, align 4
251  %add = add nsw i32 %3, %1
252  %arrayidx5 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv, !dbg !209
253  store i32 %add, ptr %arrayidx5, align 4, !dbg !209
254  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
255  %exitcond.not = icmp eq i64 %indvars.iv.next, %n
256  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
257
258  for.cond.cleanup:                                 ; preds = %for.body, %entry
259    ret void
260}
261
262; // g) Dependence::Unknown
263; // Different stride lengths
264; void test_unknown_dep(int n, int* A) {
265;   for(int i=0; i < n; ++i) {
266;       A[(i+1)*4] = 10;
267;       A[i] = 100;
268;   }
269; }
270
271; CHECK: remark: source.c:83:7: loop not vectorized: 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
272; CHECK: Unknown data dependence. Memory location is the same as accessed at source.c:82:7
273
274define void @test_unknown_dep(i64 %n, ptr nocapture %A) !dbg !214 {
275entry:
276  %cmp8 = icmp sgt i64 %n, 0
277  br i1 %cmp8, label %for.body, label %for.cond.cleanup
278
279for.body:                                         ; preds = %entry, %for.body
280  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
281  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
282  %0 = shl nsw i64 %indvars.iv.next, 2
283  %arrayidx = getelementptr inbounds i32, ptr %A, i64 %0, !dbg !229
284  store i32 10, ptr %arrayidx, align 4
285  %arrayidx2 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv, !dbg !231
286  store i32 100, ptr %arrayidx2, align 4, !dbg !231
287  %exitcond.not = icmp eq i64 %indvars.iv.next, %n
288  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body
289
290  for.cond.cleanup:                                 ; preds = %for.body, %entry
291    ret void
292}
293
294; YAML:      --- !Analysis
295; YAML-NEXT: Pass:            loop-vectorize
296; YAML-NEXT: Name:            CantIdentifyArrayBounds
297; YAML-NEXT: DebugLoc:        { File: source.c, Line: 4, Column: 16 }
298; YAML-NEXT: Function:        test_unknown_bounds
299; YAML-NEXT: Args:
300; YAML-NEXT:   - String:          'loop not vectorized: '
301; YAML-NEXT:   - String:          cannot identify array bounds
302; YAML-NEXT: ...
303; YAML-NEXT: --- !Missed
304; YAML-NEXT: Pass:            loop-vectorize
305; YAML-NEXT: Name:            MissedDetails
306; YAML-NEXT: DebugLoc:        { File: source.c, Line: 3, Column: 5 }
307; YAML-NEXT: Function:        test_unknown_bounds
308; YAML-NEXT: Args:
309; YAML-NEXT:   - String:          loop not vectorized
310; YAML-NEXT: ...
311; YAML:      --- !Analysis
312; YAML-NEXT: Pass:            loop-vectorize
313; YAML-NEXT: Name:            UnsafeDep
314; YAML-NEXT: DebugLoc:        { File: source.c, Line: 48, Column: 14 }
315; YAML-NEXT: Function:        test_backward_dep
316; YAML-NEXT: Args:
317; YAML-NEXT:   - String:          'loop not vectorized: '
318; YAML-NEXT:   - String:          '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'
319; YAML-NEXT:   - String:          "\nBackward loop carried data dependence."
320; YAML-NEXT:   - String:          ' Memory location is the same as accessed at '
321; YAML-NEXT:   - Location:        'source.c:47:5'
322; YAML-NEXT:     DebugLoc:        { File: source.c, Line: 47, Column: 5 }
323; YAML-NEXT: ...
324; YAML-NEXT: --- !Missed
325; YAML-NEXT: Pass:            loop-vectorize
326; YAML-NEXT: Name:            MissedDetails
327; YAML-NEXT: Function:        test_backward_dep
328; YAML-NEXT: Args:
329; YAML-NEXT:   - String:          loop not vectorized
330; YAML-NEXT: ...
331; YAML-NEXT: --- !Analysis
332; YAML-NEXT: Pass:            loop-vectorize
333; YAML-NEXT: Name:            UnsafeDep
334; YAML-NEXT: DebugLoc:        { File: source.c, Line: 61, Column: 12 }
335; YAML-NEXT: Function:        test_forwardButPreventsForwarding_dep
336; YAML-NEXT: Args:
337; YAML-NEXT:   - String:          'loop not vectorized: '
338; YAML-NEXT:   - String:          '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; YAML-NEXT:   - String:          "\nForward loop carried data dependence that prevents store-to-load forwarding."
340; YAML-NEXT:   - String:          ' Memory location is the same as accessed at '
341; YAML-NEXT:   - Location:        'source.c:60:5'
342; YAML-NEXT:     DebugLoc:        { File: source.c, Line: 60, Column: 5 }
343; YAML-NEXT: ...
344; YAML-NEXT: --- !Missed
345; YAML-NEXT: Pass:            loop-vectorize
346; YAML-NEXT: Name:            MissedDetails
347; YAML-NEXT: Function:        test_forwardButPreventsForwarding_dep
348; YAML-NEXT: Args:
349; YAML-NEXT:   - String:          loop not vectorized
350; YAML-NEXT: ...
351; YAML-NEXT: --- !Analysis
352; YAML-NEXT: Pass:            loop-vectorize
353; YAML-NEXT: Name:            UnsafeDep
354; YAML-NEXT: DebugLoc:        { File: source.c, Line: 74, Column: 5 }
355; YAML-NEXT: Function:        test_backwardVectorizableButPreventsForwarding
356; YAML-NEXT: Args:
357; YAML-NEXT:   - String:          'loop not vectorized: '
358; YAML-NEXT:   - String:          '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'
359; YAML-NEXT:   - String:          "\nBackward loop carried data dependence that prevents store-to-load forwarding."
360; YAML-NEXT:   - String:          ' Memory location is the same as accessed at '
361; YAML-NEXT:   - Location:        'source.c:74:21'
362; YAML-NEXT:     DebugLoc:        { File: source.c, Line: 74, Column: 21 }
363; YAML-NEXT: ...
364; YAML-NEXT: --- !Missed
365; YAML-NEXT: Pass:            loop-vectorize
366; YAML-NEXT: Name:            MissedDetails
367; YAML-NEXT: Function:        test_backwardVectorizableButPreventsForwarding
368; YAML-NEXT: Args:
369; YAML-NEXT:   - String:          loop not vectorized
370; YAML-NEXT: ...
371; YAML-NEXT: --- !Analysis
372; YAML-NEXT: Pass:            loop-vectorize
373; YAML-NEXT: Name:            UnsafeDep
374; YAML-NEXT: DebugLoc:        { File: source.c, Line: 83, Column: 7 }
375; YAML-NEXT: Function:        test_unknown_dep
376; YAML-NEXT: Args:
377; YAML-NEXT:   - String:          'loop not vectorized: '
378; YAML-NEXT:   - String:          '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'
379; YAML-NEXT:   - String:          "\nUnknown data dependence."
380; YAML-NEXT:   - String:          ' Memory location is the same as accessed at '
381; YAML-NEXT:   - Location:        'source.c:82:7'
382; YAML-NEXT:     DebugLoc:        { File: source.c, Line: 82, Column: 7 }
383; YAML-NEXT: ...
384; YAML-NEXT: --- !Missed
385; YAML-NEXT: Pass:            loop-vectorize
386; YAML-NEXT: Name:            MissedDetails
387; YAML-NEXT: Function:        test_unknown_dep
388; YAML-NEXT: Args:
389; YAML-NEXT:   - String:          loop not vectorized
390; YAML-NEXT: ...
391
392
393!llvm.dbg.cu = !{!0}
394!llvm.module.flags = !{!4}
395
396!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 14.0.0 (https://github.com/llvm/llvm-project.git 54f0f826c5c7d0ff16c230b259cb6aad33e18d97)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
397!1 = !DIFile(filename: "source.c", directory: "")
398!2 = !{}
399!4 = !{i32 2, !"Debug Info Version", i32 3}
400!13 = distinct !DISubprogram(name: "test_unknown_bounds", scope: !1, file: !1, line: 2, type: !45, scopeLine: 2, unit: !0, retainedNodes: !2)
401!23 = distinct !DILexicalBlock(scope: !13, file: !1, line: 3, column: 5)
402!27 = distinct !DILexicalBlock(scope: !23, file: !1, line: 3, column: 5)
403!28 = !DILocation(line: 3, column: 5, scope: !23)
404!35 = !DILocation(line: 4, column: 16, scope: !27)
405!44 = distinct !DISubprogram(name: "test_nodep", scope: !1, file: !1, line: 14, type: !45, scopeLine: 14, unit: !0, retainedNodes: !2)
406!45 = !DISubroutineType(types: !46)
407!46 = !{null, !18, !16, !16}
408!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !17, size: 64)
409!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
410!18 = !DIBasicType(name: "int", size: 64, encoding: DW_ATE_signed)
411!52 = distinct !DILexicalBlock(scope: !44, file: !1, line: 15, column: 3)
412!56 = distinct !DILexicalBlock(scope: !52, file: !1, line: 15, column: 3)
413!60 = distinct !DILexicalBlock(scope: !56, file: !1, line: 15, column: 31)
414!61 = !DILocation(line: 16, column: 12, scope: !60)
415!63 = !DILocation(line: 16, column: 21, scope: !60)
416!70 = distinct !DISubprogram(name: "test_forward", scope: !1, file: !1, line: 24, type: !45, scopeLine: 24, unit: !0, retainedNodes: !2)
417!77 = distinct !DILexicalBlock(scope: !70, file: !1, line: 25, column: 3)
418!80 = distinct !DILexicalBlock(scope: !77, file: !1, line: 25, column: 3)
419!81 = !DILocation(line: 25, column: 3, scope: !77)
420!83 = !DILocation(line: 26, column: 5, scope: !84)
421!84 = distinct !DILexicalBlock(scope: !80, file: !1, line: 25, column: 28)
422!87 = !DILocation(line: 27, column: 12, scope: !84)
423!88 = !DILocation(line: 27, column: 5, scope: !84)
424!89 = !DILocation(line: 27, column: 10, scope: !84)
425!93 = distinct !DISubprogram(name: "test_backwardVectorizable", scope: !1, file: !1, line: 36, type: !95, scopeLine: 36, unit: !0, retainedNodes: !2)
426!95 = !DISubroutineType(types: !96)
427!96 = !{null, !18, !16}
428!99 = distinct !DILexicalBlock(scope: !93, file: !1, line: 37, column: 3)
429!103 = distinct !DILexicalBlock(scope: !99, file: !1, line: 37, column: 3)
430!106 = !DILocation(line: 38, column: 15, scope: !107)
431!107 = distinct !DILexicalBlock(scope: !103, file: !1, line: 37, column: 28)
432!108 = !DILocation(line: 38, column: 12, scope: !107)
433!110 = !DILocation(line: 38, column: 5, scope: !107)
434!111 = !DILocation(line: 38, column: 10, scope: !107)
435!136 = distinct !DISubprogram(name: "test_backward_dep", scope: !1, file: !1, line: 45, type: !95, scopeLine: 45, unit: !0, retainedNodes: !2)
436!145 = distinct !DILexicalBlock(scope: !136, file: !1, line: 46, column: 3)
437!149 = distinct !DILexicalBlock(scope: !145, file: !1, line: 46, column: 3)
438!153 = distinct !DILexicalBlock(scope: !149, file: !1, line: 46, column: 39)
439!157 = !DILocation(line: 47, column: 5, scope: !153)
440!160 = !DILocation(line: 48, column: 14, scope: !153)
441!166 = distinct !DISubprogram(name: "test_forwardButPreventsForwarding_dep", scope: !1, file: !1, line: 58, type: !45, scopeLine: 58, unit: !0, retainedNodes: !2)
442!172 = distinct !DILexicalBlock(scope: !166, file: !1, line: 59, column: 3)
443!176 = distinct !DILexicalBlock(scope: !172, file: !1, line: 59, column: 3)
444!179 = !DILocation(line: 60, column: 5, scope: !180)
445!180 = distinct !DILexicalBlock(scope: !176, file: !1, line: 59, column: 28)
446!183 = !DILocation(line: 61, column: 12, scope: !180)
447!189 = distinct !DISubprogram(name: "test_backwardVectorizableButPreventsForwarding", scope: !1, file: !1, line: 72, type: !95, scopeLine: 72, unit: !0, retainedNodes: !2)
448!196 = distinct !DILexicalBlock(scope: !189, file: !1, line: 73, column: 3)
449!200 = distinct !DILexicalBlock(scope: !196, file: !1, line: 73, column: 3)
450!204 = distinct !DILexicalBlock(scope: !200, file: !1, line: 73, column: 29)
451!207 = !DILocation(line: 74, column: 21, scope: !204)
452!209 = !DILocation(line: 74, column: 5, scope: !204)
453!214 = distinct !DISubprogram(name: "test_unknown_dep", scope: !1, file: !1, line: 80, type: !95, scopeLine: 80, unit: !0, retainedNodes: !2)
454!219 = distinct !DILexicalBlock(scope: !214, file: !1, line: 81, column: 3)
455!223 = distinct !DILexicalBlock(scope: !219, file: !1, line: 81, column: 3)
456!227 = distinct !DILexicalBlock(scope: !223, file: !1, line: 81, column: 28)
457!229 = !DILocation(line: 82, column: 7, scope: !227)
458!231 = !DILocation(line: 83, column: 7, scope: !227)
459