xref: /llvm-project/llvm/test/Transforms/LoopRotate/dbgvalue.ll (revision d7c12ea29e614db073641f204e4619d7e54b1ff5)
1; RUN: opt -S -passes=loop-rotate -verify-memoryssa < %s | FileCheck %s --implicit-check-not=dbg.value
2; RUN: opt -S -passes=loop-rotate -verify-memoryssa < %s --try-experimental-debuginfo-iterators | FileCheck %s --implicit-check-not=dbg.value
3
4declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone
5declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone
6
7
8; This function rotates the exit conditon into the entry block, moving the
9; dbg.values with it. Check that they resolve through the PHIs to the arguments
10; only in the entry block. In the loop block, the dbg.values shift down below
11; the calls and resolve to them. Then even more dbg.values are inserted on the
12; newly produced PHIs at the start.
13
14define i32 @tak(i32 %x, i32 %y, i32 %z) nounwind ssp !dbg !0 {
15; CHECK-LABEL: define i32 @tak(
16; CHECK: entry
17; CHECK-NEXT: #dbg_value(i32 %x
18; CHECK-NEXT: #dbg_value(i32 %y
19; CHECK-NEXT: #dbg_value(i32 %z
20; CHECK: if.then.lr.ph:
21; CHECK: if.then:
22; CHECK-NEXT: %z.tr4 = phi
23; CHECK-NEXT: %y.tr3 = phi
24; CHECK-NEXT: %x.tr2 = phi
25; CHECK-NEXT: #dbg_value(i32 %z.tr4
26; CHECK-NEXT: #dbg_value(i32 %y.tr3
27; CHECK-NEXT: #dbg_value(i32 %x.tr2
28; CHECK:      %call = tail call i32 @tak(i32
29; CHECK:      %call9 = tail call i32 @tak(i32
30; CHECK:      %call14 = tail call i32 @tak(i32
31; CHECK-NEXT: #dbg_value(i32 %call
32; CHECK-NEXT: #dbg_value(i32 %call9
33; CHECK-NEXT: #dbg_value(i32 %call14
34entry:
35  br label %tailrecurse
36
37tailrecurse:                                      ; preds = %if.then, %entry
38  %x.tr = phi i32 [ %x, %entry ], [ %call, %if.then ]
39  %y.tr = phi i32 [ %y, %entry ], [ %call9, %if.then ]
40  %z.tr = phi i32 [ %z, %entry ], [ %call14, %if.then ]
41  tail call void @llvm.dbg.value(metadata i32 %x.tr, metadata !6, metadata !DIExpression()), !dbg !7
42  tail call void @llvm.dbg.value(metadata i32 %y.tr, metadata !8, metadata !DIExpression()), !dbg !9
43  tail call void @llvm.dbg.value(metadata i32 %z.tr, metadata !10, metadata !DIExpression()), !dbg !11
44  %cmp = icmp slt i32 %y.tr, %x.tr, !dbg !12
45  br i1 %cmp, label %if.then, label %if.end, !dbg !12
46
47if.then:                                          ; preds = %tailrecurse
48  %sub = sub nsw i32 %x.tr, 1, !dbg !14
49  %call = tail call i32 @tak(i32 %sub, i32 %y.tr, i32 %z.tr), !dbg !14
50  %sub6 = sub nsw i32 %y.tr, 1, !dbg !14
51  %call9 = tail call i32 @tak(i32 %sub6, i32 %z.tr, i32 %x.tr), !dbg !14
52  %sub11 = sub nsw i32 %z.tr, 1, !dbg !14
53  %call14 = tail call i32 @tak(i32 %sub11, i32 %x.tr, i32 %y.tr), !dbg !14
54  br label %tailrecurse
55
56if.end:                                           ; preds = %tailrecurse
57  br label %return, !dbg !16
58
59return:                                           ; preds = %if.end
60  ret i32 %z.tr, !dbg !17
61}
62
63; Repeat of the tak function, with only one DILocalVariable, checking that we
64; don't insert duplicate debug intrinsics. The initial duplicates are preserved.
65; FIXME: this test checks for the de-duplication behaviour that loop-rotate
66; has today, however it might not be correct. In the if.then block the preserved
67; dbg.value is for %x -- should not the _last_dbg.value, for %z, have been
68; preserved?
69define i32 @tak_dup(i32 %x, i32 %y, i32 %z) nounwind ssp !dbg !50 {
70; CHECK-LABEL: define i32 @tak_dup(
71; CHECK: entry
72; CHECK-NEXT: #dbg_value(i32 %x
73; CHECK-NEXT: #dbg_value(i32 %y
74; CHECK-NEXT: #dbg_value(i32 %z
75; CHECK: if.then.lr.ph:
76; CHECK: if.then:
77; CHECK-NEXT: %z.tr4 = phi
78; CHECK-NEXT: %y.tr3 = phi
79; CHECK-NEXT: %x.tr2 = phi
80; CHECK-NEXT: #dbg_value(i32 %x.tr2
81; CHECK:      %call = tail call i32 @tak(i32
82; CHECK:      %call9 = tail call i32 @tak(i32
83; CHECK:      %call14 = tail call i32 @tak(i32
84; CHECK-NEXT: #dbg_value(i32 %call14
85entry:
86  br label %tailrecurse
87
88tailrecurse:                                      ; preds = %if.then, %entry
89  %x.tr = phi i32 [ %x, %entry ], [ %call, %if.then ]
90  %y.tr = phi i32 [ %y, %entry ], [ %call9, %if.then ]
91  %z.tr = phi i32 [ %z, %entry ], [ %call14, %if.then ]
92  tail call void @llvm.dbg.value(metadata i32 %x.tr, metadata !60, metadata !DIExpression()), !dbg !61
93  tail call void @llvm.dbg.value(metadata i32 %y.tr, metadata !60, metadata !DIExpression()), !dbg !61
94  tail call void @llvm.dbg.value(metadata i32 %z.tr, metadata !60, metadata !DIExpression()), !dbg !61
95  %cmp = icmp slt i32 %y.tr, %x.tr, !dbg !62
96  br i1 %cmp, label %if.then, label %if.end, !dbg !62
97
98if.then:                                          ; preds = %tailrecurse
99  %sub = sub nsw i32 %x.tr, 1, !dbg !64
100  %call = tail call i32 @tak(i32 %sub, i32 %y.tr, i32 %z.tr), !dbg !64
101  %sub6 = sub nsw i32 %y.tr, 1, !dbg !64
102  %call9 = tail call i32 @tak(i32 %sub6, i32 %z.tr, i32 %x.tr), !dbg !64
103  %sub11 = sub nsw i32 %z.tr, 1, !dbg !64
104  %call14 = tail call i32 @tak(i32 %sub11, i32 %x.tr, i32 %y.tr), !dbg !64
105  br label %tailrecurse
106
107if.end:                                           ; preds = %tailrecurse
108  br label %return, !dbg !66
109
110return:                                           ; preds = %if.end
111  ret i32 %z.tr, !dbg !67
112}
113
114; Check that the dbg.values move up to being immediately below the PHIs,
115; using their Values. However once we exit the loop, the x and y values
116; become irrelevant and poison, only z gets an LCSSA PHI to preserve it.
117;
118; Note that while the icmp is initially undominated by any dbg.value and thus
119; shouldn't get a variable location, the first iteration is peeled off into the
120; entry block. It's then safe to have it dominated by subsequent dbg.values as
121; every path to the icmp is preceeded by a dbg.value.
122;
123; FIXME: could we choose to preserve more information about the loop, x and y
124; might not be live out of the loop, but they might still be dominated by a
125; describable Value.
126
127define i32 @tak2(i32 %x, i32 %y, i32 %z) nounwind ssp !dbg !21 {
128; CHECK-LABEL: define i32 @tak2(
129; CHECK: if.then:
130; CHECK-NEXT: %z.tr4 = phi i32
131; CHECK-NEXT: %y.tr3 = phi i32
132; CHECK-NEXT: %x.tr2 = phi i32
133; CHECK-NEXT: #dbg_value(i32 %x.tr2
134; CHECK-NEXT: #dbg_value(i32 %y.tr3
135; CHECK-NEXT: #dbg_value(i32 %z.tr4
136; CHECK:      tail call i32 @tak(i32
137; CHECK:      tail call i32 @tak(i32
138; CHECK:      tail call i32 @tak(i32
139; CHECK: if.end:
140; CHECK-NEXT: z.tr.lcssa = phi i32
141; CHECK-NEXT: #dbg_value(i32 poison
142; CHECK-NEXT: #dbg_value(i32 poison
143; CHECK-NEXT: #dbg_value(i32 %z.tr.lcssa
144entry:
145  br label %tailrecurse
146
147tailrecurse:                                      ; preds = %if.then, %entry
148  %x.tr = phi i32 [ %x, %entry ], [ %call, %if.then ]
149  %y.tr = phi i32 [ %y, %entry ], [ %call9, %if.then ]
150  %z.tr = phi i32 [ %z, %entry ], [ %call14, %if.then ]
151  %cmp = icmp slt i32 %y.tr, %x.tr, !dbg !22
152  br i1 %cmp, label %if.then, label %if.end, !dbg !22
153
154if.then:                                          ; preds = %tailrecurse
155  tail call void @llvm.dbg.value(metadata i32 %x.tr, metadata !36, metadata !DIExpression()), !dbg !37
156  tail call void @llvm.dbg.value(metadata i32 %y.tr, metadata !38, metadata !DIExpression()), !dbg !39
157  tail call void @llvm.dbg.value(metadata i32 %z.tr, metadata !40, metadata !DIExpression()), !dbg !41
158  %sub = sub nsw i32 %x.tr, 1, !dbg !24
159  %call = tail call i32 @tak(i32 %sub, i32 %y.tr, i32 %z.tr), !dbg !24
160  %sub6 = sub nsw i32 %y.tr, 1, !dbg !24
161  %call9 = tail call i32 @tak(i32 %sub6, i32 %z.tr, i32 %x.tr), !dbg !24
162  %sub11 = sub nsw i32 %z.tr, 1, !dbg !24
163  %call14 = tail call i32 @tak(i32 %sub11, i32 %x.tr, i32 %y.tr), !dbg !24
164  br label %tailrecurse
165
166if.end:                                           ; preds = %tailrecurse
167  tail call void @llvm.dbg.value(metadata i32 %x.tr, metadata !36, metadata !DIExpression()), !dbg !37
168  tail call void @llvm.dbg.value(metadata i32 %y.tr, metadata !38, metadata !DIExpression()), !dbg !39
169  tail call void @llvm.dbg.value(metadata i32 %z.tr, metadata !40, metadata !DIExpression()), !dbg !41
170  br label %return, !dbg !26
171
172return:                                           ; preds = %if.end
173  ret i32 %z.tr, !dbg !27
174}
175
176@channelColumns = external global i64
177@horzPlane = external global ptr, align 8
178
179define void @FindFreeHorzSeg(i64 %startCol, i64 %row, ptr %rowStart) {
180; Ensure that the loop increment basic block is rotated into the tail of the
181; body, even though it contains a debug intrinsic call.
182; CHECK-LABEL: define void @FindFreeHorzSeg(
183; CHECK: %dec = add
184; CHECK-NEXT: #dbg_value
185; CHECK: %cmp = icmp
186; CHECK: br i1 %cmp
187; CHECK: phi i64 [ %{{[^,]*}}, %{{[^,]*}} ]
188; CHECK-NEXT: br label %for.end
189
190
191entry:
192  br label %for.cond
193
194for.cond:
195  %i.0 = phi i64 [ %startCol, %entry ], [ %dec, %for.inc ]
196  %cmp = icmp eq i64 %i.0, 0
197  br i1 %cmp, label %for.end, label %for.body
198
199for.body:
200  %0 = load i64, ptr @channelColumns, align 8
201  %mul = mul i64 %0, %row
202  %add = add i64 %mul, %i.0
203  %1 = load ptr, ptr @horzPlane, align 8
204  %arrayidx = getelementptr inbounds i8, ptr %1, i64 %add
205  %2 = load i8, ptr %arrayidx, align 1
206  %tobool = icmp eq i8 %2, 0
207  br i1 %tobool, label %for.inc, label %for.end
208
209for.inc:
210  %dec = add i64 %i.0, -1
211  tail call void @llvm.dbg.value(metadata i64 %dec, metadata !DILocalVariable(scope: !0), metadata !DIExpression()), !dbg !DILocation(scope: !0)
212  br label %for.cond
213
214for.end:
215  %add1 = add i64 %i.0, 1
216  store i64 %add1, ptr %rowStart, align 8
217  ret void
218}
219
220; Test that dbg.value intrinsincs adjacent to the `icmp slt i32 0, 0` get
221; rotated as expected. The icmp is loop-invariant and so gets hoisted to the
222; preheader via a different code path. This is more difficult for DbgVariableRecord
223; debug-info records to handle, because they have to get detached and moved
224; somewhere else during rotation.
225define void @invariant_hoist() !dbg !70 {
226; CHECK-LABEL: define void @invariant_hoist()
227; CHECK: entry:
228; CHECK-NEXT: br label %L0.preheader
229; CHECK: L0.preheader:
230; CHECK-NEXT: #dbg_value(i32 0,
231; CHECK-NEXT: %cmp = icmp slt i32 0, 0,
232; CHECK: L1.preheader:
233; CHECK-NEXT: %spec.select3 = phi i32
234; CHECK-NEXT: %k.02 = phi i32
235; CHECK-NEXT: #dbg_value(i32 %k.02,
236; CHECK: L0.latch:
237; CHECK-NEXT: #dbg_value(i32 %spec.select3,
238entry:
239  br label %L0.preheader, !dbg !77
240
241L0.preheader:
242  br label %L0, !dbg !77
243
244L0:
245  %k.0 = phi i32 [ 0, %L0.preheader ], [ %spec.select, %L0.latch ]
246  call void @llvm.dbg.value(metadata i32 %k.0, metadata !80, metadata !DIExpression()), !dbg !77
247  %cmp = icmp slt i32 0, 0, !dbg !77
248  %inc = zext i1 %cmp to i32, !dbg !77
249  %spec.select = add nsw i32 %k.0, %inc, !dbg !77
250  %tobool3.not = icmp eq i32 %spec.select, 0, !dbg !77
251  br i1 %tobool3.not, label %L0.preheader, label %L1.preheader, !dbg !77
252
253L1.preheader:
254  %tobool8.not = icmp eq i32 %k.0, 0, !dbg !77
255  br label %L1, !dbg !77
256
257L1:
258  br i1 %tobool8.not, label %L1.latch, label %L0.latch, !dbg !77
259
260L1.latch:
261  br i1 false, label %L1, label %L0.latch, !dbg !77
262
263L0.latch:
264  br label %L0, !dbg !77
265}
266
267!llvm.module.flags = !{!20}
268!llvm.dbg.cu = !{!2}
269
270!0 = distinct !DISubprogram(name: "tak", line: 32, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !18, scope: !1, type: !3)
271!1 = !DIFile(filename: "/Volumes/Lalgate/cj/llvm/projects/llvm-test/SingleSource/Benchmarks/BenchmarkGame/recursive.c", directory: "/Volumes/Lalgate/cj/D/projects/llvm-test/SingleSource/Benchmarks/BenchmarkGame")
272!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang version 2.9 (trunk 125492)", isOptimized: true, emissionKind: FullDebug, file: !18)
273!3 = !DISubroutineType(types: !4)
274!4 = !{!5}
275!5 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
276!6 = !DILocalVariable(name: "x", line: 32, arg: 1, scope: !0, file: !1, type: !5)
277!7 = !DILocation(line: 32, column: 13, scope: !0)
278!8 = !DILocalVariable(name: "y", line: 32, arg: 2, scope: !0, file: !1, type: !5)
279!9 = !DILocation(line: 32, column: 20, scope: !0)
280!10 = !DILocalVariable(name: "z", line: 32, arg: 3, scope: !0, file: !1, type: !5)
281!11 = !DILocation(line: 32, column: 27, scope: !0)
282!12 = !DILocation(line: 33, column: 3, scope: !13)
283!13 = distinct !DILexicalBlock(line: 32, column: 30, file: !18, scope: !0)
284!14 = !DILocation(line: 34, column: 5, scope: !15)
285!15 = distinct !DILexicalBlock(line: 33, column: 14, file: !18, scope: !13)
286!16 = !DILocation(line: 36, column: 3, scope: !13)
287!17 = !DILocation(line: 37, column: 1, scope: !13)
288!18 = !DIFile(filename: "/Volumes/Lalgate/cj/llvm/projects/llvm-test/SingleSource/Benchmarks/BenchmarkGame/recursive.c", directory: "/Volumes/Lalgate/cj/D/projects/llvm-test/SingleSource/Benchmarks/BenchmarkGame")
289!20 = !{i32 1, !"Debug Info Version", i32 3}
290!21 = distinct !DISubprogram(name: "tak", line: 32, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !18, scope: !1, type: !3)
291!22 = !DILocation(line: 33, column: 3, scope: !23)
292!23 = distinct !DILexicalBlock(line: 32, column: 30, file: !18, scope: !21)
293!24 = !DILocation(line: 34, column: 5, scope: !25)
294!25 = distinct !DILexicalBlock(line: 33, column: 14, file: !18, scope: !23)
295!26 = !DILocation(line: 36, column: 3, scope: !23)
296!27 = !DILocation(line: 37, column: 1, scope: !23)
297!36 = !DILocalVariable(name: "x", line: 32, arg: 1, scope: !21, file: !1, type: !5)
298!37 = !DILocation(line: 32, column: 13, scope: !21)
299!38 = !DILocalVariable(name: "y", line: 32, arg: 2, scope: !21, file: !1, type: !5)
300!39 = !DILocation(line: 32, column: 20, scope: !21)
301!40 = !DILocalVariable(name: "z", line: 32, arg: 3, scope: !21, file: !1, type: !5)
302!41 = !DILocation(line: 32, column: 27, scope: !21)
303!50 = distinct !DISubprogram(name: "tak_dup", line: 32, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !18, scope: !1, type: !3)
304!57 = !DILocation(line: 32, column: 13, scope: !50)
305!59 = !DILocation(line: 32, column: 20, scope: !50)
306!60 = !DILocalVariable(name: "z", line: 32, arg: 3, scope: !50, file: !1, type: !5)
307!61 = !DILocation(line: 32, column: 27, scope: !50)
308!62 = !DILocation(line: 33, column: 3, scope: !63)
309!63 = distinct !DILexicalBlock(line: 32, column: 30, file: !18, scope: !50)
310!64 = !DILocation(line: 34, column: 5, scope: !65)
311!65 = distinct !DILexicalBlock(line: 33, column: 14, file: !18, scope: !63)
312!66 = !DILocation(line: 36, column: 3, scope: !63)
313!67 = !DILocation(line: 37, column: 1, scope: !63)
314!70 = distinct !DISubprogram(name: "invariant_hoist", line: 32, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !18, scope: !1, type: !3)
315!77 = !DILocation(line: 32, column: 13, scope: !70)
316!79 = !DILocation(line: 32, column: 20, scope: !70)
317!80 = !DILocalVariable(name: "z", line: 32, arg: 3, scope: !70, file: !1, type: !5)
318!81 = !DILocation(line: 32, column: 27, scope: !70)
319!82 = !DILocation(line: 33, column: 3, scope: !83)
320!83 = distinct !DILexicalBlock(line: 32, column: 30, file: !18, scope: !70)
321!84 = !DILocation(line: 34, column: 5, scope: !85)
322!85 = distinct !DILexicalBlock(line: 33, column: 14, file: !18, scope: !83)
323!86 = !DILocation(line: 36, column: 3, scope: !83)
324!87 = !DILocation(line: 37, column: 1, scope: !83)
325