Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / LoopFusion / diagnostics_missed.ll
blobf30a070153742b179a6007c31d584fed8cb6bf78
1 ; RUN: opt -S -passes=loop-fusion -pass-remarks-missed=loop-fusion -disable-output < %s 2>&1 | FileCheck %s
2 ; REQUIRES: asserts
4 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
6 @B = common global [1024 x i32] zeroinitializer, align 16, !dbg !0
8 ; CHECK: remark: diagnostics_missed.c:18:3: [non_adjacent]: entry and for.end: Loops are not adjacent
9 define void @non_adjacent(ptr noalias %A) !dbg !14 {
10 entry:
11   br label %for.body
13 for.cond.cleanup:                                 ; preds = %for.inc
14   br label %for.end
16 for.body:                                         ; preds = %entry, %for.inc
17   %i.02 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
18   %sub = add nsw i64 %i.02, -3
19   %add = add nuw nsw i64 %i.02, 3
20   %mul = mul nsw i64 %sub, %add
21   %rem = srem i64 %mul, %i.02
22   %conv = trunc i64 %rem to i32
23   %arrayidx = getelementptr inbounds i32, ptr %A, i64 %i.02
24   store i32 %conv, ptr %arrayidx, align 4
25   br label %for.inc
27 for.inc:                                          ; preds = %for.body
28   %inc = add nuw nsw i64 %i.02, 1, !dbg !26
29   %exitcond1 = icmp ne i64 %inc, 100
30   br i1 %exitcond1, label %for.body, label %for.cond.cleanup, !llvm.loop !28
32 for.end:                                          ; preds = %for.cond.cleanup
33   br label %for.body6
35 for.cond.cleanup5:                                ; preds = %for.inc13
36   br label %for.end15
38 for.body6:                                        ; preds = %for.end, %for.inc13
39   %i1.01 = phi i64 [ 0, %for.end ], [ %inc14, %for.inc13 ]
40   %sub7 = add nsw i64 %i1.01, -3
41   %add8 = add nuw nsw i64 %i1.01, 3
42   %mul9 = mul nsw i64 %sub7, %add8
43   %rem10 = srem i64 %mul9, %i1.01
44   %conv11 = trunc i64 %rem10 to i32
45   %arrayidx12 = getelementptr inbounds [1024 x i32], ptr @B, i64 0, i64 %i1.01
46   store i32 %conv11, ptr %arrayidx12, align 4
47   br label %for.inc13
49 for.inc13:                                        ; preds = %for.body6
50   %inc14 = add nuw nsw i64 %i1.01, 1, !dbg !31
51   %exitcond = icmp ne i64 %inc14, 100
52   br i1 %exitcond, label %for.body6, label %for.cond.cleanup5, !llvm.loop !33
54 for.end15:                                        ; preds = %for.cond.cleanup5
55   ret void
58 ; CHECK: remark: diagnostics_missed.c:28:3: [different_bounds]: entry and for.end: Loop trip counts are not the same
59 define void @different_bounds(ptr noalias %A) !dbg !36 {
60 entry:
61   br label %for.body
63 for.cond.cleanup:                                 ; preds = %for.inc
64   br label %for.end
66 for.body:                                         ; preds = %entry, %for.inc
67   %i.02 = phi i64 [ 0, %entry ], [ %inc, %for.inc ]
68   %sub = add nsw i64 %i.02, -3
69   %add = add nuw nsw i64 %i.02, 3
70   %mul = mul nsw i64 %sub, %add
71   %rem = srem i64 %mul, %i.02
72   %conv = trunc i64 %rem to i32
73   %arrayidx = getelementptr inbounds i32, ptr %A, i64 %i.02
74   store i32 %conv, ptr %arrayidx, align 4
75   br label %for.inc
77 for.inc:                                          ; preds = %for.body
78   %inc = add nuw nsw i64 %i.02, 1, !dbg !43
79   %exitcond1 = icmp ne i64 %inc, 100
80   br i1 %exitcond1, label %for.body, label %for.cond.cleanup, !llvm.loop !45
82 for.end:                                          ; preds = %for.cond.cleanup
83   br label %for.body6
85 for.cond.cleanup5:                                ; preds = %for.inc13
86   br label %for.end15
88 for.body6:                                        ; preds = %for.end, %for.inc13
89   %i1.01 = phi i64 [ 0, %for.end ], [ %inc14, %for.inc13 ]
90   %sub7 = add nsw i64 %i1.01, -3
91   %add8 = add nuw nsw i64 %i1.01, 3
92   %mul9 = mul nsw i64 %sub7, %add8
93   %rem10 = srem i64 %mul9, %i1.01
94   %conv11 = trunc i64 %rem10 to i32
95   %arrayidx12 = getelementptr inbounds [1024 x i32], ptr @B, i64 0, i64 %i1.01
96   store i32 %conv11, ptr %arrayidx12, align 4
97   br label %for.inc13
99 for.inc13:                                        ; preds = %for.body6
100   %inc14 = add nuw nsw i64 %i1.01, 1
101   %exitcond = icmp ne i64 %inc14, 200
102   br i1 %exitcond, label %for.body6, label %for.cond.cleanup5, !llvm.loop !48
104 for.end15:                                        ; preds = %for.cond.cleanup5
105   ret void
108 ; CHECK: remark: diagnostics_missed.c:38:3: [negative_dependence]: entry and for.end: Dependencies prevent fusion
109 define void @negative_dependence(ptr noalias %A) !dbg !51 {
110 entry:
111   br label %for.body
113 for.body:                                         ; preds = %entry, %for.inc
114   %indvars.iv13 = phi i64 [ 0, %entry ], [ %indvars.iv.next2, %for.inc ]
115   %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv13
116   %tmp = trunc i64 %indvars.iv13 to i32
117   store i32 %tmp, ptr %arrayidx, align 4
118   br label %for.inc
120 for.inc:                                          ; preds = %for.body
121   %indvars.iv.next2 = add nuw nsw i64 %indvars.iv13, 1
122   %exitcond3 = icmp ne i64 %indvars.iv.next2, 100
123   br i1 %exitcond3, label %for.body, label %for.end, !llvm.loop !58
125 for.end:                                          ; preds = %for.inc
126   call void @llvm.dbg.value(metadata i32 0, metadata !56, metadata !DIExpression()), !dbg !61
127   br label %for.body5
129 for.body5:                                        ; preds = %for.end, %for.inc10
130   %indvars.iv2 = phi i64 [ 0, %for.end ], [ %indvars.iv.next, %for.inc10 ]
131   %indvars.iv.next = add nuw nsw i64 %indvars.iv2, 1
132   %arrayidx7 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv.next
133   %tmp4 = load i32, ptr %arrayidx7, align 4
134   %mul = shl nsw i32 %tmp4, 1
135   %arrayidx9 = getelementptr inbounds [1024 x i32], ptr @B, i64 0, i64 %indvars.iv2
136   store i32 %mul, ptr %arrayidx9, align 4
137   br label %for.inc10
139 for.inc10:                                        ; preds = %for.body5
140   %exitcond = icmp ne i64 %indvars.iv.next, 100
141   br i1 %exitcond, label %for.body5, label %for.end12
143 for.end12:                                        ; preds = %for.inc10
144   ret void, !dbg !62
147 ; CHECK: remark: diagnostics_missed.c:51:3: [sumTest]: entry and for.cond2.preheader: Dependencies prevent fusion
148 define i32 @sumTest(ptr noalias %A) !dbg !63 {
149 entry:
150   br label %for.body
152 for.cond2.preheader:                              ; preds = %for.inc
153   br label %for.body5
155 for.body:                                         ; preds = %entry, %for.inc
156   %sum.04 = phi i32 [ 0, %entry ], [ %add, %for.inc ]
157   %indvars.iv13 = phi i64 [ 0, %entry ], [ %indvars.iv.next2, %for.inc ]
158   br label %for.inc
160 for.inc:                                          ; preds = %for.body
161   %arrayidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv13
162   %tmp = load i32, ptr %arrayidx, align 4
163   %add = add nsw i32 %sum.04, %tmp
164   %indvars.iv.next2 = add nuw nsw i64 %indvars.iv13, 1
165   %exitcond3 = icmp ne i64 %indvars.iv.next2, 100
166   br i1 %exitcond3, label %for.body, label %for.cond2.preheader, !llvm.loop !73
168 for.body5:                                        ; preds = %for.cond2.preheader, %for.inc10
169   %indvars.iv2 = phi i64 [ 0, %for.cond2.preheader ], [ %indvars.iv.next, %for.inc10 ]
170   %arrayidx7 = getelementptr inbounds i32, ptr %A, i64 %indvars.iv2
171   %tmp4 = load i32, ptr %arrayidx7, align 4
172   %div = sdiv i32 %tmp4, %add
173   %arrayidx9 = getelementptr inbounds [1024 x i32], ptr @B, i64 0, i64 %indvars.iv2
174   store i32 %div, ptr %arrayidx9, align 4
175   br label %for.inc10
177 for.inc10:                                        ; preds = %for.body5
178   %indvars.iv.next = add nuw nsw i64 %indvars.iv2, 1
179   %exitcond = icmp ne i64 %indvars.iv.next, 100
180   br i1 %exitcond, label %for.body5, label %for.end12
182 for.end12:                                        ; preds = %for.inc10
183   ret i32 %add, !dbg !76
186 ; Function Attrs: nounwind readnone speculatable willreturn
187 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
189 ; CHECK: remark: diagnostics_missed.c:62:3: [unsafe_preheader]: for.first.preheader and for.second.preheader: Loop has a non-empty preheader with instructions that cannot be moved
190 define void @unsafe_preheader(ptr noalias %A, ptr noalias %B) {
191 for.first.preheader:
192   br label %for.first, !dbg !80
194 for.first:
195   %i.02 = phi i64 [ 0, %for.first.preheader ], [ %inc, %for.first ]
196   %arrayidx = getelementptr inbounds i32, ptr %A, i64 %i.02
197   store i32 0, ptr %arrayidx, align 4
198   %inc = add nsw i64 %i.02, 1
199   %cmp = icmp slt i64 %inc, 100
200   br i1 %cmp, label %for.first, label %for.second.preheader
202 for.second.preheader:
203   call void @bar()
204   br label %for.second
206 for.second:
207   %j.01 = phi i64 [ 0, %for.second.preheader ], [ %inc6, %for.second ]
208   %arrayidx4 = getelementptr inbounds i32, ptr %B, i64 %j.01
209   store i32 0, ptr %arrayidx4, align 4
210   %inc6 = add nsw i64 %j.01, 1
211   %cmp2 = icmp slt i64 %inc6, 100
212   br i1 %cmp2, label %for.second, label %for.end
214 for.end:
215   ret void
218 ; CHECK: remark: diagnostics_missed.c:67:3: [unsafe_exitblock]: for.first.preheader and for.second.preheader: Candidate has a non-empty exit block with instructions that cannot be moved
219 define void @unsafe_exitblock(ptr noalias %A, ptr noalias %B, i64 %N) {
220 for.first.guard:
221   %cmp3 = icmp slt i64 0, %N
222   br i1 %cmp3, label %for.first.preheader, label %for.second.guard
224 for.first.preheader:
225   br label %for.first, !dbg !83
227 for.first:
228   %i.04 = phi i64 [ %inc, %for.first ], [ 0, %for.first.preheader ]
229   %arrayidx = getelementptr inbounds i32, ptr %A, i64 %i.04
230   store i32 0, ptr %arrayidx, align 4
231   %inc = add nsw i64 %i.04, 1
232   %cmp = icmp slt i64 %inc, %N
233   br i1 %cmp, label %for.first, label %for.first.exit
235 for.first.exit:
236   call void @bar()
237   br label %for.second.guard
239 for.second.guard:
240   %cmp21 = icmp slt i64 0, %N
241   br i1 %cmp21, label %for.second.preheader, label %for.end
243 for.second.preheader:
244   br label %for.second
246 for.second:
247   %j.02 = phi i64 [ %inc6, %for.second ], [ 0, %for.second.preheader ]
248   %arrayidx4 = getelementptr inbounds i32, ptr %B, i64 %j.02
249   store i32 0, ptr %arrayidx4, align 4
250   %inc6 = add nsw i64 %j.02, 1
251   %cmp2 = icmp slt i64 %inc6, %N
252   br i1 %cmp2, label %for.second, label %for.second.exit
254 for.second.exit:
255   br label %for.end
257 for.end:
258   ret void
261 ; CHECK: remark: diagnostics_missed.c:72:3: [unsafe_guardblock]: for.first.preheader and for.second.preheader: Candidate has a non-empty guard block with instructions that cannot be moved
262 define void @unsafe_guardblock(ptr noalias %A, ptr noalias %B, i64 %N) {
263 for.first.guard:
264   %cmp3 = icmp slt i64 0, %N
265   br i1 %cmp3, label %for.first.preheader, label %for.second.guard
267 for.first.preheader:
268   br label %for.first, !dbg !86
270 for.first:
271   %i.04 = phi i64 [ %inc, %for.first ], [ 0, %for.first.preheader ]
272   %arrayidx = getelementptr inbounds i32, ptr %A, i64 %i.04
273   store i32 0, ptr %arrayidx, align 4
274   %inc = add nsw i64 %i.04, 1
275   %cmp = icmp slt i64 %inc, %N
276   br i1 %cmp, label %for.first, label %for.first.exit
278 for.first.exit:
279   br label %for.second.guard
281 for.second.guard:
282   call void @bar()
283   %cmp21 = icmp slt i64 0, %N
284   br i1 %cmp21, label %for.second.preheader, label %for.end
286 for.second.preheader:
287   br label %for.second
289 for.second:
290   %j.02 = phi i64 [ %inc6, %for.second ], [ 0, %for.second.preheader ]
291   %arrayidx4 = getelementptr inbounds i32, ptr %B, i64 %j.02
292   store i32 0, ptr %arrayidx4, align 4
293   %inc6 = add nsw i64 %j.02, 1
294   %cmp2 = icmp slt i64 %inc6, %N
295   br i1 %cmp2, label %for.second, label %for.second.exit
297 for.second.exit:
298   br label %for.end
300 for.end:
301   ret void
304 declare void @bar()
306 attributes #0 = { nounwind readnone speculatable willreturn }
308 !llvm.dbg.cu = !{!2}
309 !llvm.module.flags = !{!10, !11, !12, !13}
311 !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
312 !1 = distinct !DIGlobalVariable(name: "B", scope: !2, file: !3, line: 46, type: !6, isLocal: false, isDefinition: true)
313 !2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 9.0.0 (git@github.ibm.com:compiler/llvm-project.git 23c4baaa9f5b33d2d52eda981d376c6b0a7a3180)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: GNU)
314 !3 = !DIFile(filename: "diagnostics_missed.c", directory: "/tmp")
315 !4 = !{}
316 !5 = !{!0}
317 !6 = !DICompositeType(tag: DW_TAG_array_type, baseType: !7, size: 32768, elements: !8)
318 !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
319 !8 = !{!9}
320 !9 = !DISubrange(count: 1024)
321 !10 = !{i32 2, !"Dwarf Version", i32 4}
322 !11 = !{i32 2, !"Debug Info Version", i32 3}
323 !12 = !{i32 1, !"wchar_size", i32 4}
324 !13 = !{i32 7, !"PIC Level", i32 2}
325 !14 = distinct !DISubprogram(name: "non_adjacent", scope: !3, file: !3, line: 17, type: !15, scopeLine: 17, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !19)
326 !15 = !DISubroutineType(types: !16)
327 !16 = !{null, !17}
328 !17 = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: !18)
329 !18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
330 !19 = !{!20, !21, !24}
331 !20 = !DILocalVariable(name: "A", arg: 1, scope: !14, file: !3, line: 17, type: !17)
332 !21 = !DILocalVariable(name: "i", scope: !22, file: !3, line: 18, type: !23)
333 !22 = distinct !DILexicalBlock(scope: !14, file: !3, line: 18, column: 3)
334 !23 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
335 !24 = !DILocalVariable(name: "i", scope: !25, file: !3, line: 22, type: !23)
336 !25 = distinct !DILexicalBlock(scope: !14, file: !3, line: 22, column: 3)
337 !26 = !DILocation(line: 18, column: 30, scope: !27)
338 !27 = distinct !DILexicalBlock(scope: !22, file: !3, line: 18, column: 3)
339 !28 = distinct !{!28, !29, !30}
340 !29 = !DILocation(line: 18, column: 3, scope: !22)
341 !30 = !DILocation(line: 20, column: 3, scope: !22)
342 !31 = !DILocation(line: 22, column: 30, scope: !32)
343 !32 = distinct !DILexicalBlock(scope: !25, file: !3, line: 22, column: 3)
344 !33 = distinct !{!33, !34, !35}
345 !34 = !DILocation(line: 22, column: 3, scope: !25)
346 !35 = !DILocation(line: 24, column: 3, scope: !25)
347 !36 = distinct !DISubprogram(name: "different_bounds", scope: !3, file: !3, line: 27, type: !15, scopeLine: 27, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !37)
348 !37 = !{!38, !39, !41}
349 !38 = !DILocalVariable(name: "A", arg: 1, scope: !36, file: !3, line: 27, type: !17)
350 !39 = !DILocalVariable(name: "i", scope: !40, file: !3, line: 28, type: !23)
351 !40 = distinct !DILexicalBlock(scope: !36, file: !3, line: 28, column: 3)
352 !41 = !DILocalVariable(name: "i", scope: !42, file: !3, line: 32, type: !23)
353 !42 = distinct !DILexicalBlock(scope: !36, file: !3, line: 32, column: 3)
354 !43 = !DILocation(line: 28, column: 30, scope: !44)
355 !44 = distinct !DILexicalBlock(scope: !40, file: !3, line: 28, column: 3)
356 !45 = distinct !{!45, !46, !47}
357 !46 = !DILocation(line: 28, column: 3, scope: !40)
358 !47 = !DILocation(line: 30, column: 3, scope: !40)
359 !48 = distinct !{!48, !49, !50}
360 !49 = !DILocation(line: 32, column: 3, scope: !42)
361 !50 = !DILocation(line: 34, column: 3, scope: !42)
362 !51 = distinct !DISubprogram(name: "negative_dependence", scope: !3, file: !3, line: 37, type: !15, scopeLine: 37, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !52)
363 !52 = !{!53, !54, !56}
364 !53 = !DILocalVariable(name: "A", arg: 1, scope: !51, file: !3, line: 37, type: !17)
365 !54 = !DILocalVariable(name: "i", scope: !55, file: !3, line: 38, type: !7)
366 !55 = distinct !DILexicalBlock(scope: !51, file: !3, line: 38, column: 3)
367 !56 = !DILocalVariable(name: "i", scope: !57, file: !3, line: 42, type: !7)
368 !57 = distinct !DILexicalBlock(scope: !51, file: !3, line: 42, column: 3)
369 !58 = distinct !{!58, !59, !60}
370 !59 = !DILocation(line: 38, column: 3, scope: !55)
371 !60 = !DILocation(line: 40, column: 3, scope: !55)
372 !61 = !DILocation(line: 0, scope: !57)
373 !62 = !DILocation(line: 45, column: 1, scope: !51)
374 !63 = distinct !DISubprogram(name: "sumTest", scope: !3, file: !3, line: 48, type: !64, scopeLine: 48, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !66)
375 !64 = !DISubroutineType(types: !65)
376 !65 = !{!7, !17}
377 !66 = !{!67, !68, !69, !71}
378 !67 = !DILocalVariable(name: "A", arg: 1, scope: !63, file: !3, line: 48, type: !17)
379 !68 = !DILocalVariable(name: "sum", scope: !63, file: !3, line: 49, type: !7)
380 !69 = !DILocalVariable(name: "i", scope: !70, file: !3, line: 51, type: !7)
381 !70 = distinct !DILexicalBlock(scope: !63, file: !3, line: 51, column: 3)
382 !71 = !DILocalVariable(name: "i", scope: !72, file: !3, line: 54, type: !7)
383 !72 = distinct !DILexicalBlock(scope: !63, file: !3, line: 54, column: 3)
384 !73 = distinct !{!73, !74, !75}
385 !74 = !DILocation(line: 51, column: 3, scope: !70)
386 !75 = !DILocation(line: 52, column: 15, scope: !70)
387 !76 = !DILocation(line: 57, column: 3, scope: !63)
388 !77 = distinct !DISubprogram(name: "unsafe_preheader", scope: !3, file: !3, line: 60, type: !15, scopeLine: 60, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !78)
389 !78 = !{}
390 !79 = distinct !DILexicalBlock(scope: !77, file: !3, line: 3, column: 5)
391 !80 = !DILocation(line: 62, column: 3, scope: !79)
392 !81 = distinct !DISubprogram(name: "unsafe_exitblock", scope: !3, file: !3, line: 65, type: !15, scopeLine: 60, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !78)
393 !82 = distinct !DILexicalBlock(scope: !81, file: !3, line: 3, column: 5)
394 !83 = !DILocation(line: 67, column: 3, scope: !82)
395 !84 = distinct !DISubprogram(name: "unsafe_guardblock", scope: !3, file: !3, line: 70, type: !15, scopeLine: 60, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !78)
396 !85 = distinct !DILexicalBlock(scope: !84, file: !3, line: 3, column: 5)
397 !86 = !DILocation(line: 72, column: 3, scope: !85)