1//===- llvm/unittest/IR/BasicBlockTest.cpp - BasicBlock unit tests --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/IR/BasicBlock.h"
10#include "llvm/IR/DebugInfo.h"
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/AsmParser/Parser.h"
13#include "llvm/IR/Function.h"
14#include "llvm/IR/IRBuilder.h"
15#include "llvm/IR/Instruction.h"
16#include "llvm/IR/Instructions.h"
17#include "llvm/IR/LLVMContext.h"
18#include "llvm/IR/Module.h"
19#include "llvm/IR/NoFolder.h"
20#include "llvm/IR/Verifier.h"
21#include "llvm/Support/SourceMgr.h"
22#include "gmock/gmock-matchers.h"
23#include "gtest/gtest.h"
24#include <memory>
25
26using namespace llvm;
27
28extern cl::opt<bool> UseNewDbgInfoFormat;
29
30static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
31 SMDiagnostic Err;
32 std::unique_ptr<Module> Mod = parseAssemblyString(AsmString: IR, Err, Context&: C);
33 if (!Mod)
34 Err.print(ProgName: "BasicBlockDbgInfoTest", S&: errs());
35 return Mod;
36}
37
38namespace {
39
40// We can occasionally moveAfter an instruction so that it moves to the
41// position that it already resides at. This is fine -- but gets complicated
42// with dbg.value intrinsics. By moving an instruction, we can end up changing
43// nothing but the location of debug-info intrinsics. That has to be modelled
44// by DbgVariableRecords, the dbg.value replacement.
45TEST(BasicBlockDbgInfoTest, InsertAfterSelf) {
46 LLVMContext C;
47 UseNewDbgInfoFormat = true;
48
49 std::unique_ptr<Module> M = parseIR(C, IR: R"(
50 define i16 @f(i16 %a) !dbg !6 {
51 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
52 %b = add i16 %a, 1, !dbg !11
53 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
54 %c = add i16 %b, 1, !dbg !11
55 ret i16 0, !dbg !11
56 }
57 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
58 attributes #0 = { nounwind readnone speculatable willreturn }
59
60 !llvm.dbg.cu = !{!0}
61 !llvm.module.flags = !{!5}
62
63 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
64 !1 = !DIFile(filename: "t.ll", directory: "/")
65 !2 = !{}
66 !5 = !{i32 2, !"Debug Info Version", i32 3}
67 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
68 !7 = !DISubroutineType(types: !2)
69 !8 = !{!9}
70 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
71 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
72 !11 = !DILocation(line: 1, column: 1, scope: !6)
73)");
74
75 // Convert the module to "new" form debug-info.
76 M->convertToNewDbgValues();
77 // Fetch the entry block.
78 BasicBlock &BB = M->getFunction(Name: "f")->getEntryBlock();
79
80 Instruction *Inst1 = &*BB.begin();
81 Instruction *Inst2 = &*std::next(x: BB.begin());
82 Instruction *RetInst = &*std::next(x: Inst2->getIterator());
83 EXPECT_TRUE(Inst1->hasDbgRecords());
84 EXPECT_TRUE(Inst2->hasDbgRecords());
85 EXPECT_FALSE(RetInst->hasDbgRecords());
86
87 // If we move Inst2 to be after Inst1, then it comes _immediately_ after. Were
88 // we in dbg.value form we would then have:
89 // dbg.value
90 // %b = add
91 // %c = add
92 // dbg.value
93 // Check that this is replicated by DbgVariableRecords.
94 Inst2->moveAfter(MovePos: Inst1);
95
96 // Inst1 should only have one DbgVariableRecord on it.
97 EXPECT_TRUE(Inst1->hasDbgRecords());
98 auto Range1 = Inst1->getDbgRecordRange();
99 EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), 1u);
100 // Inst2 should have none.
101 EXPECT_FALSE(Inst2->hasDbgRecords());
102 // While the return inst should now have one on it.
103 EXPECT_TRUE(RetInst->hasDbgRecords());
104 auto Range2 = RetInst->getDbgRecordRange();
105 EXPECT_EQ(std::distance(Range2.begin(), Range2.end()), 1u);
106
107 M->convertFromNewDbgValues();
108
109 UseNewDbgInfoFormat = false;
110}
111
112TEST(BasicBlockDbgInfoTest, MarkerOperations) {
113 LLVMContext C;
114 UseNewDbgInfoFormat = true;
115
116 std::unique_ptr<Module> M = parseIR(C, IR: R"(
117 define i16 @f(i16 %a) !dbg !6 {
118 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
119 %b = add i16 %a, 1, !dbg !11
120 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
121 ret i16 0, !dbg !11
122 }
123 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
124 attributes #0 = { nounwind readnone speculatable willreturn }
125
126 !llvm.dbg.cu = !{!0}
127 !llvm.module.flags = !{!5}
128
129 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
130 !1 = !DIFile(filename: "t.ll", directory: "/")
131 !2 = !{}
132 !5 = !{i32 2, !"Debug Info Version", i32 3}
133 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
134 !7 = !DISubroutineType(types: !2)
135 !8 = !{!9}
136 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
137 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
138 !11 = !DILocation(line: 1, column: 1, scope: !6)
139)");
140
141 // Fetch the entry block,
142 BasicBlock &BB = M->getFunction(Name: "f")->getEntryBlock();
143 // Convert the module to "new" form debug-info.
144 M->convertToNewDbgValues();
145 EXPECT_EQ(BB.size(), 2u);
146
147 // Fetch out our two markers,
148 Instruction *Instr1 = &*BB.begin();
149 Instruction *Instr2 = Instr1->getNextNode();
150 DbgMarker *Marker1 = Instr1->DebugMarker;
151 DbgMarker *Marker2 = Instr2->DebugMarker;
152 // There's no TrailingDbgRecords marker allocated yet.
153 DbgMarker *EndMarker = nullptr;
154
155 // Check that the "getMarker" utilities operate as expected.
156 EXPECT_EQ(BB.getMarker(Instr1->getIterator()), Marker1);
157 EXPECT_EQ(BB.getMarker(Instr2->getIterator()), Marker2);
158 EXPECT_EQ(BB.getNextMarker(Instr1), Marker2);
159 EXPECT_EQ(BB.getNextMarker(Instr2), EndMarker); // Is nullptr.
160
161 // There should be two DbgVariableRecords,
162 EXPECT_EQ(Marker1->StoredDbgRecords.size(), 1u);
163 EXPECT_EQ(Marker2->StoredDbgRecords.size(), 1u);
164
165 // Unlink them and try to re-insert them through the basic block.
166 DbgRecord *DVR1 = &*Marker1->StoredDbgRecords.begin();
167 DbgRecord *DVR2 = &*Marker2->StoredDbgRecords.begin();
168 DVR1->removeFromParent();
169 DVR2->removeFromParent();
170 EXPECT_TRUE(Marker1->StoredDbgRecords.empty());
171 EXPECT_TRUE(Marker2->StoredDbgRecords.empty());
172
173 // This should appear in Marker1.
174 BB.insertDbgRecordBefore(DR: DVR1, Here: BB.begin());
175 EXPECT_EQ(Marker1->StoredDbgRecords.size(), 1u);
176 EXPECT_EQ(DVR1, &*Marker1->StoredDbgRecords.begin());
177
178 // This should attach to Marker2.
179 BB.insertDbgRecordAfter(DR: DVR2, I: &*BB.begin());
180 EXPECT_EQ(Marker2->StoredDbgRecords.size(), 1u);
181 EXPECT_EQ(DVR2, &*Marker2->StoredDbgRecords.begin());
182
183 // Now, how about removing instructions? That should cause any
184 // DbgVariableRecords to "fall down".
185 Instr1->removeFromParent();
186 Marker1 = nullptr;
187 // DbgVariableRecords should now be in Marker2.
188 EXPECT_EQ(BB.size(), 1u);
189 EXPECT_EQ(Marker2->StoredDbgRecords.size(), 2u);
190 // They should also be in the correct order.
191 SmallVector<DbgRecord *, 2> DVRs;
192 for (DbgRecord &DVR : Marker2->getDbgRecordRange())
193 DVRs.push_back(Elt: &DVR);
194 EXPECT_EQ(DVRs[0], DVR1);
195 EXPECT_EQ(DVRs[1], DVR2);
196
197 // If we remove the end instruction, the DbgVariableRecords should fall down
198 // into the trailing marker.
199 EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr);
200 Instr2->removeFromParent();
201 EXPECT_TRUE(BB.empty());
202 EndMarker = BB.getTrailingDbgRecords();
203 ASSERT_NE(EndMarker, nullptr);
204 EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u);
205 // Again, these should arrive in the correct order.
206
207 DVRs.clear();
208 for (DbgRecord &DVR : EndMarker->getDbgRecordRange())
209 DVRs.push_back(Elt: &DVR);
210 EXPECT_EQ(DVRs[0], DVR1);
211 EXPECT_EQ(DVRs[1], DVR2);
212
213 // Inserting a normal instruction at the beginning: shouldn't dislodge the
214 // DbgVariableRecords. It's intended to not go at the start.
215 Instr1->insertBefore(BB, InsertPos: BB.begin());
216 EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u);
217 Instr1->removeFromParent();
218
219 // Inserting at end(): should dislodge the DbgVariableRecords, if they were
220 // dbg.values then they would sit "above" the new instruction.
221 Instr1->insertBefore(BB, InsertPos: BB.end());
222 EXPECT_EQ(Instr1->DebugMarker->StoredDbgRecords.size(), 2u);
223 // We should de-allocate the trailing marker when something is inserted
224 // at end().
225 EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr);
226
227 // Remove Instr1: now the DbgVariableRecords will fall down again,
228 Instr1->removeFromParent();
229 EndMarker = BB.getTrailingDbgRecords();
230 EXPECT_EQ(EndMarker->StoredDbgRecords.size(), 2u);
231
232 // Inserting a terminator, however it's intended, should dislodge the
233 // trailing DbgVariableRecords, as it's the clear intention of the caller that
234 // this be the final instr in the block, and DbgVariableRecords aren't allowed
235 // to live off the end forever.
236 Instr2->insertBefore(BB, InsertPos: BB.begin());
237 EXPECT_EQ(Instr2->DebugMarker->StoredDbgRecords.size(), 2u);
238 EXPECT_EQ(BB.getTrailingDbgRecords(), nullptr);
239
240 // Teardown,
241 Instr1->insertBefore(BB, InsertPos: BB.begin());
242
243 UseNewDbgInfoFormat = false;
244}
245
246TEST(BasicBlockDbgInfoTest, HeadBitOperations) {
247 LLVMContext C;
248 UseNewDbgInfoFormat = true;
249
250 std::unique_ptr<Module> M = parseIR(C, IR: R"(
251 define i16 @f(i16 %a) !dbg !6 {
252 %b = add i16 %a, 1, !dbg !11
253 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
254 %c = add i16 %a, 1, !dbg !11
255 %d = add i16 %a, 1, !dbg !11
256 ret i16 0, !dbg !11
257 }
258 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
259 attributes #0 = { nounwind readnone speculatable willreturn }
260
261 !llvm.dbg.cu = !{!0}
262 !llvm.module.flags = !{!5}
263
264 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
265 !1 = !DIFile(filename: "t.ll", directory: "/")
266 !2 = !{}
267 !5 = !{i32 2, !"Debug Info Version", i32 3}
268 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
269 !7 = !DISubroutineType(types: !2)
270 !8 = !{!9}
271 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
272 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
273 !11 = !DILocation(line: 1, column: 1, scope: !6)
274)");
275
276 // Test that the movement of debug-data when using moveBefore etc and
277 // insertBefore etc are governed by the "head" bit of iterators.
278 BasicBlock &BB = M->getFunction(Name: "f")->getEntryBlock();
279 // Convert the module to "new" form debug-info.
280 M->convertToNewDbgValues();
281
282 // Test that the head bit behaves as expected: it should be set when the
283 // code wants the _start_ of the block, but not otherwise.
284 EXPECT_TRUE(BB.getFirstInsertionPt().getHeadBit());
285 BasicBlock::iterator BeginIt = BB.begin();
286 EXPECT_TRUE(BeginIt.getHeadBit());
287 // If you launder the instruction pointer through dereferencing and then
288 // get the iterator again with getIterator, the head bit is lost. This is
289 // deliberate: if you're calling getIterator, then you're requesting an
290 // iterator for the position of _this_ instruction, not "the start of this
291 // block".
292 BasicBlock::iterator BeginIt2 = BeginIt->getIterator();
293 EXPECT_FALSE(BeginIt2.getHeadBit());
294
295 // Fetch some instruction pointers.
296 Instruction *BInst = &*BeginIt;
297 Instruction *CInst = BInst->getNextNode();
298 Instruction *DInst = CInst->getNextNode();
299 // CInst should have debug-info.
300 ASSERT_TRUE(CInst->DebugMarker);
301 EXPECT_FALSE(CInst->DebugMarker->StoredDbgRecords.empty());
302
303 // If we move "c" to the start of the block, just normally, then the
304 // DbgVariableRecords should fall down to "d".
305 CInst->moveBefore(BB, I: BeginIt2);
306 EXPECT_TRUE(!CInst->DebugMarker ||
307 CInst->DebugMarker->StoredDbgRecords.empty());
308 ASSERT_TRUE(DInst->DebugMarker);
309 EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty());
310
311 // Wheras if we move D to the start of the block with moveBeforePreserving,
312 // the DbgVariableRecords should move with it.
313 DInst->moveBeforePreserving(BB, I: BB.begin());
314 EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty());
315 EXPECT_EQ(&*BB.begin(), DInst);
316
317 // Similarly, moveAfterPreserving "D" to "C" should move DbgVariableRecords
318 // with "D".
319 DInst->moveAfterPreserving(MovePos: CInst);
320 EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty());
321
322 // (move back to the start...)
323 DInst->moveBeforePreserving(BB, I: BB.begin());
324
325 // Current order of insts: "D -> C -> B -> Ret". DbgVariableRecords on "D".
326 // If we move "C" to the beginning of the block, it should go before the
327 // DbgVariableRecords. They'll stay on "D".
328 CInst->moveBefore(BB, I: BB.begin());
329 EXPECT_TRUE(!CInst->DebugMarker ||
330 CInst->DebugMarker->StoredDbgRecords.empty());
331 EXPECT_FALSE(DInst->DebugMarker->StoredDbgRecords.empty());
332 EXPECT_EQ(&*BB.begin(), CInst);
333 EXPECT_EQ(CInst->getNextNode(), DInst);
334
335 // Move back.
336 CInst->moveBefore(MovePos: BInst);
337 EXPECT_EQ(&*BB.begin(), DInst);
338
339 // Current order of insts: "D -> C -> B -> Ret". DbgVariableRecords on "D".
340 // Now move CInst to the position of DInst, but using getIterator instead of
341 // BasicBlock::begin. This signals that we want the "C" instruction to be
342 // immediately before "D", with any DbgVariableRecords on "D" now moving to
343 // "C". It's the equivalent of moving an instruction to the position between a
344 // run of dbg.values and the next instruction.
345 CInst->moveBefore(BB, I: DInst->getIterator());
346 // CInst gains the DbgVariableRecords.
347 EXPECT_TRUE(!DInst->DebugMarker ||
348 DInst->DebugMarker->StoredDbgRecords.empty());
349 EXPECT_FALSE(CInst->DebugMarker->StoredDbgRecords.empty());
350 EXPECT_EQ(&*BB.begin(), CInst);
351
352 UseNewDbgInfoFormat = false;
353}
354
355TEST(BasicBlockDbgInfoTest, InstrDbgAccess) {
356 LLVMContext C;
357 UseNewDbgInfoFormat = true;
358
359 std::unique_ptr<Module> M = parseIR(C, IR: R"(
360 define i16 @f(i16 %a) !dbg !6 {
361 %b = add i16 %a, 1, !dbg !11
362 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
363 %c = add i16 %a, 1, !dbg !11
364 %d = add i16 %a, 1, !dbg !11
365 ret i16 0, !dbg !11
366 }
367 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
368 attributes #0 = { nounwind readnone speculatable willreturn }
369
370 !llvm.dbg.cu = !{!0}
371 !llvm.module.flags = !{!5}
372
373 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
374 !1 = !DIFile(filename: "t.ll", directory: "/")
375 !2 = !{}
376 !5 = !{i32 2, !"Debug Info Version", i32 3}
377 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
378 !7 = !DISubroutineType(types: !2)
379 !8 = !{!9}
380 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
381 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
382 !11 = !DILocation(line: 1, column: 1, scope: !6)
383)");
384
385 // Check that DbgVariableRecords can be accessed from Instructions without
386 // digging into the depths of DbgMarkers.
387 BasicBlock &BB = M->getFunction(Name: "f")->getEntryBlock();
388 // Convert the module to "new" form debug-info.
389 M->convertToNewDbgValues();
390
391 Instruction *BInst = &*BB.begin();
392 Instruction *CInst = BInst->getNextNode();
393 Instruction *DInst = CInst->getNextNode();
394
395 ASSERT_FALSE(BInst->DebugMarker);
396 ASSERT_TRUE(CInst->DebugMarker);
397 ASSERT_EQ(CInst->DebugMarker->StoredDbgRecords.size(), 1u);
398 DbgRecord *DVR1 = &*CInst->DebugMarker->StoredDbgRecords.begin();
399 ASSERT_TRUE(DVR1);
400 EXPECT_FALSE(BInst->hasDbgRecords());
401
402 // Clone DbgVariableRecords from one inst to another. Other arguments to clone
403 // are tested in DbgMarker test.
404 auto Range1 = BInst->cloneDebugInfoFrom(From: CInst);
405 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u);
406 DbgRecord *DVR2 = &*BInst->DebugMarker->StoredDbgRecords.begin();
407 EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), 1u);
408 EXPECT_EQ(&*Range1.begin(), DVR2);
409 EXPECT_NE(DVR1, DVR2);
410
411 // We should be able to get a range over exactly the same information.
412 auto Range2 = BInst->getDbgRecordRange();
413 EXPECT_EQ(Range1.begin(), Range2.begin());
414 EXPECT_EQ(Range1.end(), Range2.end());
415
416 // We should be able to query if there are DbgVariableRecords,
417 EXPECT_TRUE(BInst->hasDbgRecords());
418 EXPECT_TRUE(CInst->hasDbgRecords());
419 EXPECT_FALSE(DInst->hasDbgRecords());
420
421 // Dropping should be easy,
422 BInst->dropDbgRecords();
423 EXPECT_FALSE(BInst->hasDbgRecords());
424 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 0u);
425
426 // And we should be able to drop individual DbgVariableRecords.
427 CInst->dropOneDbgRecord(I: DVR1);
428 EXPECT_FALSE(CInst->hasDbgRecords());
429 EXPECT_EQ(CInst->DebugMarker->StoredDbgRecords.size(), 0u);
430
431 UseNewDbgInfoFormat = false;
432}
433
434/* Let's recall the big illustration from BasicBlock::spliceDebugInfo:
435
436 Dest
437 |
438 this-block: A----A----A ====A----A----A----A---A---A
439 Src-block ++++B---B---B---B:::C
440 | |
441 First Last
442
443 in all it's glory. Depending on the bit-configurations for the iterator head
444 / tail bits on the three named iterators, there are eight ways for a splice to
445 occur. To save the amount of thinking needed to pack this into one unit test,
446 just test the same IR eight times with difference splices. The IR shall be
447 thus:
448
449 define i16 @f(i16 %a) !dbg !6 {
450 entry:
451 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
452 %b = add i16 %a, 1, !dbg !11
453 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
454 br label %exit, !dbg !11
455
456 exit:
457 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
458 %c = add i16 %b, 1, !dbg !11
459 ret i16 0, !dbg !11
460 }
461
462 The iterators will be:
463 Dest: exit block, "c" instruction.
464 First: entry block, "b" instruction.
465 Last: entry block, branch instruction.
466
467 The numbered configurations will be:
468
469 | Dest-Head | First-Head | Last-tail
470 ----+----------------+----------------+------------
471 0 | false | false | false
472 1 | true | false | false
473 2 | false | true | false
474 3 | true | true | false
475 4 | false | false | true
476 5 | true | false | true
477 6 | false | true | true
478 7 | true | true | true
479
480 Each numbered test scenario will also have a short explanation indicating what
481 this bit configuration represents.
482*/
483
484static const std::string SpliceTestIR = R"(
485 define i16 @f(i16 %a) !dbg !6 {
486 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
487 %b = add i16 %a, 1, !dbg !11
488 call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()), !dbg !11
489 br label %exit, !dbg !11
490
491 exit:
492 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
493 %c = add i16 %b, 1, !dbg !11
494 ret i16 0, !dbg !11
495 }
496 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
497 attributes #0 = { nounwind readnone speculatable willreturn }
498
499 !llvm.dbg.cu = !{!0}
500 !llvm.module.flags = !{!5}
501
502 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
503 !1 = !DIFile(filename: "t.ll", directory: "/")
504 !2 = !{}
505 !5 = !{i32 2, !"Debug Info Version", i32 3}
506 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
507 !7 = !DISubroutineType(types: !2)
508 !8 = !{!9}
509 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
510 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
511 !11 = !DILocation(line: 1, column: 1, scope: !6)
512)";
513
514class DbgSpliceTest : public ::testing::Test {
515protected:
516 LLVMContext C;
517 std::unique_ptr<Module> M;
518 BasicBlock *BBEntry, *BBExit;
519 BasicBlock::iterator Dest, First, Last;
520 Instruction *BInst, *Branch, *CInst;
521 DbgVariableRecord *DVRA, *DVRB, *DVRConst;
522
523 void SetUp() override {
524 UseNewDbgInfoFormat = true;
525 M = parseIR(C, IR: SpliceTestIR.c_str());
526 M->convertToNewDbgValues();
527
528 BBEntry = &M->getFunction(Name: "f")->getEntryBlock();
529 BBExit = BBEntry->getNextNode();
530
531 Dest = BBExit->begin();
532 First = BBEntry->begin();
533 Last = BBEntry->getTerminator()->getIterator();
534 BInst = &*First;
535 Branch = &*Last;
536 CInst = &*Dest;
537
538 DVRA =
539 cast<DbgVariableRecord>(Val: &*BInst->DebugMarker->StoredDbgRecords.begin());
540 DVRB = cast<DbgVariableRecord>(
541 Val: &*Branch->DebugMarker->StoredDbgRecords.begin());
542 DVRConst =
543 cast<DbgVariableRecord>(Val: &*CInst->DebugMarker->StoredDbgRecords.begin());
544 }
545
546 void TearDown() override { UseNewDbgInfoFormat = false; }
547
548 bool InstContainsDbgVariableRecord(Instruction *I, DbgVariableRecord *DVR) {
549 for (DbgRecord &D : I->getDbgRecordRange()) {
550 if (&D == DVR) {
551 // Confirm too that the links between the records are correct.
552 EXPECT_EQ(DVR->Marker, I->DebugMarker);
553 EXPECT_EQ(I->DebugMarker->MarkedInstr, I);
554 return true;
555 }
556 }
557 return false;
558 }
559
560 bool CheckDVROrder(Instruction *I,
561 SmallVector<DbgVariableRecord *> CheckVals) {
562 SmallVector<DbgRecord *> Vals;
563 for (DbgRecord &D : I->getDbgRecordRange())
564 Vals.push_back(Elt: &D);
565
566 EXPECT_EQ(Vals.size(), CheckVals.size());
567 if (Vals.size() != CheckVals.size())
568 return false;
569
570 for (unsigned int I = 0; I < Vals.size(); ++I) {
571 EXPECT_EQ(Vals[I], CheckVals[I]);
572 // Provide another expectation failure to let us localise what goes wrong,
573 // by returning a flag to the caller.
574 if (Vals[I] != CheckVals[I])
575 return false;
576 }
577 return true;
578 }
579};
580
581TEST_F(DbgSpliceTest, DbgSpliceTest0) {
582 Dest.setHeadBit(false);
583 First.setHeadBit(false);
584 Last.setTailBit(false);
585
586 /*
587 define i16 @f(i16 %a) !dbg !6 {
588BBEntry entry:
589DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
590!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
591void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
592!dbg !11 Last br label %exit, !dbg !11
593
594BBExit exit:
595DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
596!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
597!dbg !11
598 }
599
600 Splice from First, not including leading dbg.value, to Last, including the
601 trailing dbg.value. Place at Dest, between the constant dbg.value and %c.
602 %b, and the following dbg.value, should move, to:
603
604 define i16 @f(i16 %a) !dbg !6 {
605BBEntry entry:
606DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
607!DIExpression()), !dbg !11 Last br label %exit, !dbg !11
608
609BBExit exit:
610DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
611!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
612void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
613!dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11
614 }
615
616
617 */
618 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: First, FromEndIt: Last);
619 EXPECT_EQ(BInst->getParent(), BBExit);
620 EXPECT_EQ(CInst->getParent(), BBExit);
621 EXPECT_EQ(Branch->getParent(), BBEntry);
622
623 // DVRB: should be on Dest, in exit block.
624 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB));
625
626 // DVRA, should have "fallen" onto the branch, remained in entry block.
627 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA));
628
629 // DVRConst should be on the moved %b instruction.
630 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst));
631}
632
633TEST_F(DbgSpliceTest, DbgSpliceTest1) {
634 Dest.setHeadBit(true);
635 First.setHeadBit(false);
636 Last.setTailBit(false);
637
638 /*
639 define i16 @f(i16 %a) !dbg !6 {
640BBEntry entry:
641DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
642!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
643void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
644!dbg !11 Last br label %exit, !dbg !11
645
646BBExit exit:
647DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
648!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
649!dbg !11
650 }
651
652 Splice from First, not including leading dbg.value, to Last, including the
653 trailing dbg.value. Place at the head of Dest, i.e. at the very start of
654 BBExit, before any debug-info there. Becomes:
655
656 define i16 @f(i16 %a) !dbg !6 {
657BBEntry entry:
658DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
659!DIExpression()), !dbg !11 Last br label %exit, !dbg !11
660
661BBExit exit:
662First %b = add i16 %a, 1, !dbg !11
663DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
664!DIExpression()), !dbg !11 DVRConst call void @llvm.dbg.value(metadata i16 0,
665metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1,
666!dbg !11 ret i16 0, !dbg !11
667 }
668
669
670 */
671 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: First, FromEndIt: Last);
672 EXPECT_EQ(BInst->getParent(), BBExit);
673 EXPECT_EQ(CInst->getParent(), BBExit);
674 EXPECT_EQ(Branch->getParent(), BBEntry);
675
676 // DVRB: should be on CInst, in exit block.
677 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB));
678
679 // DVRA, should have "fallen" onto the branch, remained in entry block.
680 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA));
681
682 // DVRConst should be behind / after the moved instructions, remain on CInst.
683 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
684
685 // Order of DVRB and DVRConst should be thus:
686 EXPECT_TRUE(CheckDVROrder(CInst, {DVRB, DVRConst}));
687}
688
689TEST_F(DbgSpliceTest, DbgSpliceTest2) {
690 Dest.setHeadBit(false);
691 First.setHeadBit(true);
692 Last.setTailBit(false);
693
694 /*
695 define i16 @f(i16 %a) !dbg !6 {
696BBEntry entry:
697DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
698!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
699void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
700!dbg !11 Last br label %exit, !dbg !11
701
702BBExit exit:
703DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
704!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
705!dbg !11
706 }
707
708 Splice from head of First, which includes the leading dbg.value, to Last,
709 including the trailing dbg.value. Place in front of Dest, but after any
710 debug-info there. Becomes:
711
712 define i16 @f(i16 %a) !dbg !6 {
713BBEntry entry:
714Last br label %exit, !dbg !11
715
716BBExit exit:
717DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
718!DIExpression()), !dbg !11 DVRA call void @llvm.dbg.value(metadata i16 %a,
719metadata !9, metadata !DIExpression()), !dbg !11 First %b = add i16 %a, 1,
720!dbg !11 DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9,
721metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret
722i16 0, !dbg !11
723 }
724
725
726 */
727 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: First, FromEndIt: Last);
728 EXPECT_EQ(BInst->getParent(), BBExit);
729 EXPECT_EQ(CInst->getParent(), BBExit);
730
731 // DVRB: should be on CInst, in exit block.
732 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB));
733
734 // DVRA, should have transferred with the spliced instructions, remains on
735 // the "b" inst.
736 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA));
737
738 // DVRConst should be ahead of the moved instructions, ahead of BInst.
739 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst));
740
741 // Order of DVRA and DVRConst should be thus:
742 EXPECT_TRUE(CheckDVROrder(BInst, {DVRConst, DVRA}));
743}
744
745TEST_F(DbgSpliceTest, DbgSpliceTest3) {
746 Dest.setHeadBit(true);
747 First.setHeadBit(true);
748 Last.setTailBit(false);
749
750 /*
751 define i16 @f(i16 %a) !dbg !6 {
752BBEntry entry:
753DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
754!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
755void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
756!dbg !11 Last br label %exit, !dbg !11
757
758BBExit exit:
759DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
760!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
761!dbg !11
762 }
763
764 Splice from head of First, which includes the leading dbg.value, to Last,
765 including the trailing dbg.value. Place at head of Dest, before any
766 debug-info there. Becomes:
767
768 define i16 @f(i16 %a) !dbg !6 {
769BBEntry entry:
770Last br label %exit, !dbg !11
771
772BBExit exit:
773DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
774!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
775void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
776!dbg !11 DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9,
777metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret
778i16 0, !dbg !11
779 }
780
781 */
782 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: First, FromEndIt: Last);
783 EXPECT_EQ(BInst->getParent(), BBExit);
784 EXPECT_EQ(CInst->getParent(), BBExit);
785
786 // DVRB: should be on CInst, in exit block.
787 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRB));
788
789 // DVRA, should have transferred with the spliced instructions, remains on
790 // the "b" inst.
791 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA));
792
793 // DVRConst should be behind the moved instructions, ahead of CInst.
794 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
795
796 // Order of DVRB and DVRConst should be thus:
797 EXPECT_TRUE(CheckDVROrder(CInst, {DVRB, DVRConst}));
798}
799
800TEST_F(DbgSpliceTest, DbgSpliceTest4) {
801 Dest.setHeadBit(false);
802 First.setHeadBit(false);
803 Last.setTailBit(true);
804
805 /*
806 define i16 @f(i16 %a) !dbg !6 {
807BBEntry entry:
808DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
809!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
810void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
811!dbg !11 Last br label %exit, !dbg !11
812
813BBExit exit:
814DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
815!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
816!dbg !11
817 }
818
819 Splice from First, not including the leading dbg.value, to Last, but NOT
820 including the trailing dbg.value because the tail bit is set. Place at Dest,
821 after any debug-info there. Becomes:
822
823 define i16 @f(i16 %a) !dbg !6 {
824BBEntry entry:
825DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
826!DIExpression()), !dbg !11 DVRB call void @llvm.dbg.value(metadata i16 %b,
827metadata !9, metadata !DIExpression()), !dbg !11 Last br label %exit, !dbg
828!11
829
830BBExit exit:
831DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
832!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 Dest %c =
833add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11
834 }
835
836 */
837 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: First, FromEndIt: Last);
838 EXPECT_EQ(BInst->getParent(), BBExit);
839 EXPECT_EQ(CInst->getParent(), BBExit);
840 EXPECT_EQ(Branch->getParent(), BBEntry);
841
842 // DVRB: should be on Branch as before, remain in entry block.
843 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
844
845 // DVRA, should have remained in entry block, falls onto Branch inst.
846 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA));
847
848 // DVRConst should be ahead of the moved instructions, BInst.
849 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst));
850
851 // Order of DVRA and DVRA should be thus:
852 EXPECT_TRUE(CheckDVROrder(Branch, {DVRA, DVRB}));
853}
854
855TEST_F(DbgSpliceTest, DbgSpliceTest5) {
856 Dest.setHeadBit(true);
857 First.setHeadBit(false);
858 Last.setTailBit(true);
859
860 /*
861 define i16 @f(i16 %a) !dbg !6 {
862BBEntry entry:
863DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
864!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
865void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
866!dbg !11 Last br label %exit, !dbg !11
867
868BBExit exit:
869DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
870!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
871!dbg !11
872 }
873
874 Splice from First, not including the leading dbg.value, to Last, but NOT
875 including the trailing dbg.value because the tail bit is set. Place at head
876 of Dest, before any debug-info there. Becomes:
877
878 define i16 @f(i16 %a) !dbg !6 {
879BBEntry entry:
880DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
881!DIExpression()), !dbg !11 DVRB call void @llvm.dbg.value(metadata i16 %b,
882metadata !9, metadata !DIExpression()), !dbg !11 Last br label %exit, !dbg
883!11
884
885BBExit exit:
886First %b = add i16 %a, 1, !dbg !11
887DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
888!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
889!dbg !11
890 }
891
892 */
893 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: First, FromEndIt: Last);
894 EXPECT_EQ(BInst->getParent(), BBExit);
895 EXPECT_EQ(CInst->getParent(), BBExit);
896 EXPECT_EQ(Branch->getParent(), BBEntry);
897
898 // DVRB: should be on Branch as before, remain in entry block.
899 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
900
901 // DVRA, should have remained in entry block, falls onto Branch inst.
902 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRA));
903
904 // DVRConst should be behind of the moved instructions, on CInst.
905 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
906
907 // Order of DVRA and DVRB should be thus:
908 EXPECT_TRUE(CheckDVROrder(Branch, {DVRA, DVRB}));
909}
910
911TEST_F(DbgSpliceTest, DbgSpliceTest6) {
912 Dest.setHeadBit(false);
913 First.setHeadBit(true);
914 Last.setTailBit(true);
915
916 /*
917 define i16 @f(i16 %a) !dbg !6 {
918BBEntry entry:
919DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
920!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
921void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
922!dbg !11 Last br label %exit, !dbg !11
923
924BBExit exit:
925DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
926!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
927!dbg !11
928 }
929
930 Splice from First, including the leading dbg.value, to Last, but NOT
931 including the trailing dbg.value because the tail bit is set. Place at Dest,
932 after any debug-info there. Becomes:
933
934 define i16 @f(i16 %a) !dbg !6 {
935BBEntry entry:
936DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
937!DIExpression()), !dbg !11 Last br label %exit, !dbg !11
938
939BBExit exit:
940DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
941!DIExpression()), !dbg !11 DVRA call void @llvm.dbg.value(metadata i16 %a,
942metadata !9, metadata !DIExpression()), !dbg !11 First %b = add i16 %a, 1,
943!dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11
944 }
945
946 */
947 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: First, FromEndIt: Last);
948 EXPECT_EQ(BInst->getParent(), BBExit);
949 EXPECT_EQ(CInst->getParent(), BBExit);
950 EXPECT_EQ(Branch->getParent(), BBEntry);
951
952 // DVRB: should be on Branch as before, remain in entry block.
953 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
954
955 // DVRA, should have transferred to BBExit, on B inst.
956 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA));
957
958 // DVRConst should be ahead of the moved instructions, on BInst.
959 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRConst));
960
961 // Order of DVRA and DVRConst should be thus:
962 EXPECT_TRUE(CheckDVROrder(BInst, {DVRConst, DVRA}));
963}
964
965TEST_F(DbgSpliceTest, DbgSpliceTest7) {
966 Dest.setHeadBit(true);
967 First.setHeadBit(true);
968 Last.setTailBit(true);
969
970 /*
971 define i16 @f(i16 %a) !dbg !6 {
972BBEntry entry:
973DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
974!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
975void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
976!dbg !11 Last br label %exit, !dbg !11
977
978BBExit exit:
979DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
980!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
981!dbg !11
982 }
983
984 Splice from First, including the leading dbg.value, to Last, but NOT
985 including the trailing dbg.value because the tail bit is set. Place at head
986 of Dest, before any debug-info there. Becomes:
987
988 define i16 @f(i16 %a) !dbg !6 {
989BBEntry entry:
990DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
991!DIExpression()), !dbg !11 Last br label %exit, !dbg !11
992
993BBExit exit:
994DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
995!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRConst call
996void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()),
997!dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0, !dbg !11
998 }
999
1000 */
1001 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: First, FromEndIt: Last);
1002 EXPECT_EQ(BInst->getParent(), BBExit);
1003 EXPECT_EQ(CInst->getParent(), BBExit);
1004 EXPECT_EQ(Branch->getParent(), BBEntry);
1005
1006 // DVRB: should be on Branch as before, remain in entry block.
1007 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
1008
1009 // DVRA, should have transferred to BBExit, on B inst.
1010 EXPECT_TRUE(InstContainsDbgVariableRecord(BInst, DVRA));
1011
1012 // DVRConst should be after of the moved instructions, on CInst.
1013 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
1014}
1015
1016// But wait, there's more! What if you splice a range that is empty, but
1017// implicitly contains debug-info? In the dbg.value design for debug-info,
1018// this would be an explicit range, but in DbgVariableRecord debug-info, it
1019// isn't. Check that if we try to do that, with differing head-bit values, that
1020// DbgVariableRecords are transferred.
1021// Test with empty transfers to Dest, with head bit set and not set.
1022
1023TEST_F(DbgSpliceTest, DbgSpliceEmpty0) {
1024 Dest.setHeadBit(false);
1025 First.setHeadBit(false);
1026 Last.setHeadBit(false);
1027 /*
1028 define i16 @f(i16 %a) !dbg !6 {
1029BBEntry entry:
1030DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
1031!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
1032void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
1033!dbg !11 Last br label %exit, !dbg !11
1034
1035BBExit exit:
1036DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
1037!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
1038!dbg !11
1039 }
1040
1041 Splice from BBEntry.getFirstInsertionPt to First -- this implicitly is a
1042 splice of DVRA, but the iterators are pointing at the same instruction. The
1043 only difference is the setting of the head bit. Becomes;
1044
1045 define i16 @f(i16 %a) !dbg !6 {
1046First %b = add i16 %a, 1, !dbg !11
1047DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
1048!DIExpression()), !dbg !11 Last br label %exit, !dbg !11
1049
1050BBExit exit:
1051DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
1052!DIExpression()), !dbg !11 DVRA call void @llvm.dbg.value(metadata i16 %a,
1053metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1,
1054!dbg !11 ret i16 0, !dbg !11
1055 }
1056
1057 */
1058 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: BBEntry->getFirstInsertionPt(), FromEndIt: First);
1059 EXPECT_EQ(BInst->getParent(), BBEntry);
1060 EXPECT_EQ(CInst->getParent(), BBExit);
1061 EXPECT_EQ(Branch->getParent(), BBEntry);
1062
1063 // DVRB: should be on Branch as before, remain in entry block.
1064 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
1065
1066 // DVRA, should have transferred to BBExit, on C inst.
1067 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRA));
1068
1069 // DVRConst should be ahead of the moved DbgVariableRecord, on CInst.
1070 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
1071
1072 // Order of DVRA and DVRConst should be thus:
1073 EXPECT_TRUE(CheckDVROrder(CInst, {DVRConst, DVRA}));
1074}
1075
1076TEST_F(DbgSpliceTest, DbgSpliceEmpty1) {
1077 Dest.setHeadBit(true);
1078 First.setHeadBit(false);
1079 Last.setHeadBit(false);
1080 /*
1081 define i16 @f(i16 %a) !dbg !6 {
1082BBEntry entry:
1083DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
1084!DIExpression()), !dbg !11 First %b = add i16 %a, 1, !dbg !11 DVRB call
1085void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata !DIExpression()),
1086!dbg !11 Last br label %exit, !dbg !11
1087
1088BBExit exit:
1089DVRConst call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata
1090!DIExpression()), !dbg !11 Dest %c = add i16 %b, 1, !dbg !11 ret i16 0,
1091!dbg !11
1092 }
1093
1094 Splice from BBEntry.getFirstInsertionPt to First -- this implicitly is a
1095 splice of DVRA, but the iterators are pointing at the same instruction. The
1096 only difference is the setting of the head bit. Insert at head of Dest,
1097 i.e. before DVRConst. Becomes;
1098
1099 define i16 @f(i16 %a) !dbg !6 {
1100First %b = add i16 %a, 1, !dbg !11
1101DVRB call void @llvm.dbg.value(metadata i16 %b, metadata !9, metadata
1102!DIExpression()), !dbg !11 Last br label %exit, !dbg !11
1103
1104BBExit exit:
1105DVRA call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata
1106!DIExpression()), !dbg !11 DVRConst call void @llvm.dbg.value(metadata i16 0,
1107metadata !9, metadata !DIExpression()), !dbg !11 Dest %c = add i16 %b, 1,
1108!dbg !11 ret i16 0, !dbg !11
1109 }
1110
1111 */
1112 BBExit->splice(ToIt: Dest, FromBB: BBEntry, FromBeginIt: BBEntry->getFirstInsertionPt(), FromEndIt: First);
1113 EXPECT_EQ(BInst->getParent(), BBEntry);
1114 EXPECT_EQ(CInst->getParent(), BBExit);
1115 EXPECT_EQ(Branch->getParent(), BBEntry);
1116
1117 // DVRB: should be on Branch as before, remain in entry block.
1118 EXPECT_TRUE(InstContainsDbgVariableRecord(Branch, DVRB));
1119
1120 // DVRA, should have transferred to BBExit, on C inst.
1121 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRA));
1122
1123 // DVRConst should be ahead of the moved DbgVariableRecord, on CInst.
1124 EXPECT_TRUE(InstContainsDbgVariableRecord(CInst, DVRConst));
1125
1126 // Order of DVRA and DVRConst should be thus:
1127 EXPECT_TRUE(CheckDVROrder(CInst, {DVRA, DVRConst}));
1128}
1129
1130// If we splice new instructions into a block with trailing DbgVariableRecords,
1131// then the trailing DbgVariableRecords should get flushed back out.
1132TEST(BasicBlockDbgInfoTest, DbgSpliceTrailing) {
1133 LLVMContext C;
1134 UseNewDbgInfoFormat = true;
1135
1136 std::unique_ptr<Module> M = parseIR(C, IR: R"(
1137 define i16 @f(i16 %a) !dbg !6 {
1138 entry:
1139 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1140 br label %exit
1141
1142 exit:
1143 %b = add i16 %a, 1, !dbg !11
1144 ret i16 0, !dbg !11
1145 }
1146 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
1147 attributes #0 = { nounwind readnone speculatable willreturn }
1148
1149 !llvm.dbg.cu = !{!0}
1150 !llvm.module.flags = !{!5}
1151
1152 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1153 !1 = !DIFile(filename: "t.ll", directory: "/")
1154 !2 = !{}
1155 !5 = !{i32 2, !"Debug Info Version", i32 3}
1156 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1157 !7 = !DISubroutineType(types: !2)
1158 !8 = !{!9}
1159 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1160 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1161 !11 = !DILocation(line: 1, column: 1, scope: !6)
1162)");
1163
1164 BasicBlock &Entry = M->getFunction(Name: "f")->getEntryBlock();
1165 BasicBlock &Exit = *Entry.getNextNode();
1166 M->convertToNewDbgValues();
1167
1168 // Begin by forcing entry block to have dangling DbgVariableRecord.
1169 Entry.getTerminator()->eraseFromParent();
1170 ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr);
1171 EXPECT_TRUE(Entry.empty());
1172
1173 // Now transfer the entire contents of the exit block into the entry.
1174 Entry.splice(ToIt: Entry.end(), FromBB: &Exit, FromBeginIt: Exit.begin(), FromEndIt: Exit.end());
1175
1176 // The trailing DbgVariableRecord should have been placed at the front of
1177 // what's been spliced in.
1178 Instruction *BInst = &*Entry.begin();
1179 ASSERT_TRUE(BInst->DebugMarker);
1180 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u);
1181
1182 UseNewDbgInfoFormat = false;
1183}
1184
1185// When we remove instructions from the program, adjacent DbgVariableRecords
1186// coalesce together into one DbgMarker. In "old" dbg.value mode you could
1187// re-insert the removed instruction back into the middle of a sequence of
1188// dbg.values. Test that this can be replicated correctly by DbgVariableRecords
1189TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsert) {
1190 LLVMContext C;
1191 UseNewDbgInfoFormat = true;
1192
1193 std::unique_ptr<Module> M = parseIR(C, IR: R"(
1194 define i16 @f(i16 %a) !dbg !6 {
1195 entry:
1196 %qux = sub i16 %a, 0
1197 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1198 %foo = add i16 %a, %a
1199 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
1200 ret i16 1
1201 }
1202 declare void @llvm.dbg.value(metadata, metadata, metadata)
1203
1204 !llvm.dbg.cu = !{!0}
1205 !llvm.module.flags = !{!5}
1206
1207 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1208 !1 = !DIFile(filename: "t.ll", directory: "/")
1209 !2 = !{}
1210 !5 = !{i32 2, !"Debug Info Version", i32 3}
1211 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1212 !7 = !DISubroutineType(types: !2)
1213 !8 = !{!9}
1214 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1215 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1216 !11 = !DILocation(line: 1, column: 1, scope: !6)
1217)");
1218
1219 BasicBlock &Entry = M->getFunction(Name: "f")->getEntryBlock();
1220 M->convertToNewDbgValues();
1221
1222 // Fetch the relevant instructions from the converted function.
1223 Instruction *SubInst = &*Entry.begin();
1224 ASSERT_TRUE(isa<BinaryOperator>(SubInst));
1225 Instruction *AddInst = SubInst->getNextNode();
1226 ASSERT_TRUE(isa<BinaryOperator>(AddInst));
1227 Instruction *RetInst = AddInst->getNextNode();
1228 ASSERT_TRUE(isa<ReturnInst>(RetInst));
1229
1230 // add and sub should both have one DbgVariableRecord on add and ret.
1231 EXPECT_FALSE(SubInst->hasDbgRecords());
1232 EXPECT_TRUE(AddInst->hasDbgRecords());
1233 EXPECT_TRUE(RetInst->hasDbgRecords());
1234 auto R1 = AddInst->getDbgRecordRange();
1235 EXPECT_EQ(std::distance(R1.begin(), R1.end()), 1u);
1236 auto R2 = RetInst->getDbgRecordRange();
1237 EXPECT_EQ(std::distance(R2.begin(), R2.end()), 1u);
1238
1239 // The Supported (TM) code sequence for removing then reinserting insts
1240 // after another instruction:
1241 std::optional<DbgVariableRecord::self_iterator> Pos =
1242 AddInst->getDbgReinsertionPosition();
1243 AddInst->removeFromParent();
1244
1245 // We should have a re-insertion position.
1246 ASSERT_TRUE(Pos);
1247 // Both DbgVariableRecords should now be attached to the ret inst.
1248 auto R3 = RetInst->getDbgRecordRange();
1249 EXPECT_EQ(std::distance(R3.begin(), R3.end()), 2u);
1250
1251 // Re-insert and re-insert.
1252 AddInst->insertAfter(InsertPos: SubInst);
1253 Entry.reinsertInstInDbgRecords(I: AddInst, Pos);
1254 // We should be back into a position of having one DbgVariableRecord on add
1255 // and ret.
1256 EXPECT_FALSE(SubInst->hasDbgRecords());
1257 EXPECT_TRUE(AddInst->hasDbgRecords());
1258 EXPECT_TRUE(RetInst->hasDbgRecords());
1259 auto R4 = AddInst->getDbgRecordRange();
1260 EXPECT_EQ(std::distance(R4.begin(), R4.end()), 1u);
1261 auto R5 = RetInst->getDbgRecordRange();
1262 EXPECT_EQ(std::distance(R5.begin(), R5.end()), 1u);
1263
1264 UseNewDbgInfoFormat = false;
1265}
1266
1267// Test instruction removal and re-insertion, this time with one
1268// DbgVariableRecord that should hop up one instruction.
1269TEST(BasicBlockDbgInfoTest, RemoveInstAndReinsertForOneDbgVariableRecord) {
1270 LLVMContext C;
1271 UseNewDbgInfoFormat = true;
1272
1273 std::unique_ptr<Module> M = parseIR(C, IR: R"(
1274 define i16 @f(i16 %a) !dbg !6 {
1275 entry:
1276 %qux = sub i16 %a, 0
1277 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1278 %foo = add i16 %a, %a
1279 ret i16 1
1280 }
1281 declare void @llvm.dbg.value(metadata, metadata, metadata)
1282
1283 !llvm.dbg.cu = !{!0}
1284 !llvm.module.flags = !{!5}
1285
1286 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1287 !1 = !DIFile(filename: "t.ll", directory: "/")
1288 !2 = !{}
1289 !5 = !{i32 2, !"Debug Info Version", i32 3}
1290 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1291 !7 = !DISubroutineType(types: !2)
1292 !8 = !{!9}
1293 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1294 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1295 !11 = !DILocation(line: 1, column: 1, scope: !6)
1296)");
1297
1298 BasicBlock &Entry = M->getFunction(Name: "f")->getEntryBlock();
1299 M->convertToNewDbgValues();
1300
1301 // Fetch the relevant instructions from the converted function.
1302 Instruction *SubInst = &*Entry.begin();
1303 ASSERT_TRUE(isa<BinaryOperator>(SubInst));
1304 Instruction *AddInst = SubInst->getNextNode();
1305 ASSERT_TRUE(isa<BinaryOperator>(AddInst));
1306 Instruction *RetInst = AddInst->getNextNode();
1307 ASSERT_TRUE(isa<ReturnInst>(RetInst));
1308
1309 // There should be one DbgVariableRecord.
1310 EXPECT_FALSE(SubInst->hasDbgRecords());
1311 EXPECT_TRUE(AddInst->hasDbgRecords());
1312 EXPECT_FALSE(RetInst->hasDbgRecords());
1313 auto R1 = AddInst->getDbgRecordRange();
1314 EXPECT_EQ(std::distance(R1.begin(), R1.end()), 1u);
1315
1316 // The Supported (TM) code sequence for removing then reinserting insts:
1317 std::optional<DbgVariableRecord::self_iterator> Pos =
1318 AddInst->getDbgReinsertionPosition();
1319 AddInst->removeFromParent();
1320
1321 // No re-insertion position as there were no DbgVariableRecords on the ret.
1322 ASSERT_FALSE(Pos);
1323 // The single DbgVariableRecord should now be attached to the ret inst.
1324 EXPECT_TRUE(RetInst->hasDbgRecords());
1325 auto R2 = RetInst->getDbgRecordRange();
1326 EXPECT_EQ(std::distance(R2.begin(), R2.end()), 1u);
1327
1328 // Re-insert and re-insert.
1329 AddInst->insertAfter(InsertPos: SubInst);
1330 Entry.reinsertInstInDbgRecords(I: AddInst, Pos);
1331 // We should be back into a position of having one DbgVariableRecord on the
1332 // AddInst.
1333 EXPECT_FALSE(SubInst->hasDbgRecords());
1334 EXPECT_TRUE(AddInst->hasDbgRecords());
1335 EXPECT_FALSE(RetInst->hasDbgRecords());
1336 auto R3 = AddInst->getDbgRecordRange();
1337 EXPECT_EQ(std::distance(R3.begin(), R3.end()), 1u);
1338
1339 UseNewDbgInfoFormat = false;
1340}
1341
1342// Similar to the above, what if we splice into an empty block with debug-info,
1343// with debug-info at the start of the moving range, that we intend to be
1344// transferred. The dbg.value of %a should remain at the start, but come ahead
1345// of the i16 0 dbg.value.
1346TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty1) {
1347 LLVMContext C;
1348 UseNewDbgInfoFormat = true;
1349
1350 std::unique_ptr<Module> M = parseIR(C, IR: R"(
1351 define i16 @f(i16 %a) !dbg !6 {
1352 entry:
1353 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1354 br label %exit
1355
1356 exit:
1357 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
1358 %b = add i16 %a, 1, !dbg !11
1359 call void @llvm.dbg.value(metadata i16 1, metadata !9, metadata !DIExpression()), !dbg !11
1360 ret i16 0, !dbg !11
1361 }
1362 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
1363 attributes #0 = { nounwind readnone speculatable willreturn }
1364
1365 !llvm.dbg.cu = !{!0}
1366 !llvm.module.flags = !{!5}
1367
1368 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1369 !1 = !DIFile(filename: "t.ll", directory: "/")
1370 !2 = !{}
1371 !5 = !{i32 2, !"Debug Info Version", i32 3}
1372 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1373 !7 = !DISubroutineType(types: !2)
1374 !8 = !{!9}
1375 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1376 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1377 !11 = !DILocation(line: 1, column: 1, scope: !6)
1378)");
1379
1380 Function &F = *M->getFunction(Name: "f");
1381 BasicBlock &Entry = F.getEntryBlock();
1382 BasicBlock &Exit = *Entry.getNextNode();
1383 M->convertToNewDbgValues();
1384
1385 // Begin by forcing entry block to have dangling DbgVariableRecord.
1386 Entry.getTerminator()->eraseFromParent();
1387 ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr);
1388 EXPECT_TRUE(Entry.empty());
1389
1390 // Now transfer the entire contents of the exit block into the entry. This
1391 // includes both dbg.values.
1392 Entry.splice(ToIt: Entry.end(), FromBB: &Exit, FromBeginIt: Exit.begin(), FromEndIt: Exit.end());
1393
1394 // We should now have two dbg.values on the first instruction, and they
1395 // should be in the correct order of %a, then 0.
1396 Instruction *BInst = &*Entry.begin();
1397 ASSERT_TRUE(BInst->hasDbgRecords());
1398 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 2u);
1399 SmallVector<DbgVariableRecord *, 2> DbgVariableRecords;
1400 for (DbgRecord &DVR : BInst->getDbgRecordRange())
1401 DbgVariableRecords.push_back(Elt: cast<DbgVariableRecord>(Val: &DVR));
1402
1403 EXPECT_EQ(DbgVariableRecords[0]->getVariableLocationOp(0), F.getArg(0));
1404 Value *SecondDVRValue = DbgVariableRecords[1]->getVariableLocationOp(OpIdx: 0);
1405 ASSERT_TRUE(isa<ConstantInt>(SecondDVRValue));
1406 EXPECT_EQ(cast<ConstantInt>(SecondDVRValue)->getZExtValue(), 0ull);
1407
1408 // No trailing DbgVariableRecords in the entry block now.
1409 EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr);
1410
1411 UseNewDbgInfoFormat = false;
1412}
1413
1414// Similar test again, but this time: splice the contents of exit into entry,
1415// with the intention of leaving the first dbg.value (i16 0) behind.
1416TEST(BasicBlockDbgInfoTest, DbgSpliceToEmpty2) {
1417 LLVMContext C;
1418 UseNewDbgInfoFormat = true;
1419
1420 std::unique_ptr<Module> M = parseIR(C, IR: R"(
1421 define i16 @f(i16 %a) !dbg !6 {
1422 entry:
1423 call void @llvm.dbg.value(metadata i16 %a, metadata !9, metadata !DIExpression()), !dbg !11
1424 br label %exit
1425
1426 exit:
1427 call void @llvm.dbg.value(metadata i16 0, metadata !9, metadata !DIExpression()), !dbg !11
1428 %b = add i16 %a, 1, !dbg !11
1429 call void @llvm.dbg.value(metadata i16 1, metadata !9, metadata !DIExpression()), !dbg !11
1430 ret i16 0, !dbg !11
1431 }
1432 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
1433 attributes #0 = { nounwind readnone speculatable willreturn }
1434
1435 !llvm.dbg.cu = !{!0}
1436 !llvm.module.flags = !{!5}
1437
1438 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1439 !1 = !DIFile(filename: "t.ll", directory: "/")
1440 !2 = !{}
1441 !5 = !{i32 2, !"Debug Info Version", i32 3}
1442 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1443 !7 = !DISubroutineType(types: !2)
1444 !8 = !{!9}
1445 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1446 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1447 !11 = !DILocation(line: 1, column: 1, scope: !6)
1448)");
1449
1450 Function &F = *M->getFunction(Name: "f");
1451 BasicBlock &Entry = F.getEntryBlock();
1452 BasicBlock &Exit = *Entry.getNextNode();
1453 M->convertToNewDbgValues();
1454
1455 // Begin by forcing entry block to have dangling DbgVariableRecord.
1456 Entry.getTerminator()->eraseFromParent();
1457 ASSERT_NE(Entry.getTrailingDbgRecords(), nullptr);
1458 EXPECT_TRUE(Entry.empty());
1459
1460 // Now transfer into the entry block -- fetching the first instruction with
1461 // begin and then calling getIterator clears the "head" bit, meaning that the
1462 // range to move will not include any leading DbgVariableRecords.
1463 Entry.splice(ToIt: Entry.end(), FromBB: &Exit, FromBeginIt: Exit.begin()->getIterator(), FromEndIt: Exit.end());
1464
1465 // We should now have one dbg.values on the first instruction, %a.
1466 Instruction *BInst = &*Entry.begin();
1467 ASSERT_TRUE(BInst->hasDbgRecords());
1468 EXPECT_EQ(BInst->DebugMarker->StoredDbgRecords.size(), 1u);
1469 SmallVector<DbgVariableRecord *, 2> DbgVariableRecords;
1470 for (DbgRecord &DVR : BInst->getDbgRecordRange())
1471 DbgVariableRecords.push_back(Elt: cast<DbgVariableRecord>(Val: &DVR));
1472
1473 EXPECT_EQ(DbgVariableRecords[0]->getVariableLocationOp(0), F.getArg(0));
1474 // No trailing DbgVariableRecords in the entry block now.
1475 EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr);
1476
1477 // We should have nothing left in the exit block...
1478 EXPECT_TRUE(Exit.empty());
1479 // ... except for some dangling DbgVariableRecords.
1480 EXPECT_NE(Exit.getTrailingDbgRecords(), nullptr);
1481 EXPECT_FALSE(Exit.getTrailingDbgRecords()->empty());
1482 Exit.getTrailingDbgRecords()->eraseFromParent();
1483 Exit.deleteTrailingDbgRecords();
1484
1485 UseNewDbgInfoFormat = false;
1486}
1487
1488// What if we moveBefore end() -- there might be no debug-info there, in which
1489// case we shouldn't crash.
1490TEST(BasicBlockDbgInfoTest, DbgMoveToEnd) {
1491 LLVMContext C;
1492 UseNewDbgInfoFormat = true;
1493
1494 std::unique_ptr<Module> M = parseIR(C, IR: R"(
1495 define i16 @f(i16 %a) !dbg !6 {
1496 entry:
1497 br label %exit
1498
1499 exit:
1500 ret i16 0, !dbg !11
1501 }
1502 declare void @llvm.dbg.value(metadata, metadata, metadata) #0
1503 attributes #0 = { nounwind readnone speculatable willreturn }
1504
1505 !llvm.dbg.cu = !{!0}
1506 !llvm.module.flags = !{!5}
1507
1508 !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
1509 !1 = !DIFile(filename: "t.ll", directory: "/")
1510 !2 = !{}
1511 !5 = !{i32 2, !"Debug Info Version", i32 3}
1512 !6 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
1513 !7 = !DISubroutineType(types: !2)
1514 !8 = !{!9}
1515 !9 = !DILocalVariable(name: "1", scope: !6, file: !1, line: 1, type: !10)
1516 !10 = !DIBasicType(name: "ty16", size: 16, encoding: DW_ATE_unsigned)
1517 !11 = !DILocation(line: 1, column: 1, scope: !6)
1518)");
1519
1520 Function &F = *M->getFunction(Name: "f");
1521 BasicBlock &Entry = F.getEntryBlock();
1522 BasicBlock &Exit = *Entry.getNextNode();
1523 M->convertToNewDbgValues();
1524
1525 // Move the return to the end of the entry block.
1526 Instruction *Br = Entry.getTerminator();
1527 Instruction *Ret = Exit.getTerminator();
1528 EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr);
1529 Ret->moveBefore(BB&: Entry, I: Entry.end());
1530 Br->eraseFromParent();
1531
1532 // There should continue to not be any debug-info anywhere.
1533 EXPECT_EQ(Entry.getTrailingDbgRecords(), nullptr);
1534 EXPECT_EQ(Exit.getTrailingDbgRecords(), nullptr);
1535 EXPECT_FALSE(Ret->hasDbgRecords());
1536
1537 UseNewDbgInfoFormat = false;
1538}
1539
1540} // End anonymous namespace.
1541

source code of llvm/unittests/IR/BasicBlockDbgInfoTest.cpp