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