Fix test failures introduced by PR #113697 (#116941)
[llvm-project.git] / llvm / unittests / IR / DroppedVariableStatsTest.cpp
blob61f3a87bb355e0cf7c123fdfb08a2e5b90fb2caa
1 //===- unittests/IR/DroppedVariableStatsTest.cpp - TimePassesHandler tests
2 //----------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/InstIterator.h"
13 #include "llvm/IR/LegacyPassManager.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/Pass.h"
16 #include "llvm/PassRegistry.h"
17 #include "llvm/Passes/StandardInstrumentations.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "gtest/gtest.h"
20 #include <gtest/gtest.h>
21 #include <llvm/ADT/SmallString.h>
22 #include <llvm/IR/LLVMContext.h>
23 #include <llvm/IR/Module.h>
24 #include <llvm/IR/PassInstrumentation.h>
25 #include <llvm/IR/PassManager.h>
26 #include <llvm/IR/PassTimingInfo.h>
27 #include <llvm/Support/raw_ostream.h>
29 using namespace llvm;
30 namespace llvm {
31 void initializePassTest1Pass(PassRegistry &);
33 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
34 SMDiagnostic Err;
35 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
36 if (!Mod)
37 Err.print("AbstractCallSiteTests", errs());
38 return Mod;
40 } // namespace llvm
42 namespace {
44 // This test ensures that if a #dbg_value and an instruction that exists in the
45 // same scope as that #dbg_value are both deleted as a result of an optimization
46 // pass, debug information is considered not dropped.
47 TEST(DroppedVariableStats, BothDeleted) {
48 PassInstrumentationCallbacks PIC;
49 PassInstrumentation PI(&PIC);
51 LLVMContext C;
53 const char *IR =
54 R"(
55 ; Function Attrs: mustprogress nounwind ssp uwtable(sync)
56 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
57 entry:
58 #dbg_value(i32 %x, !15, !DIExpression(), !16)
59 %add = add nsw i32 %x, 1, !dbg !17
60 ret i32 0
62 !llvm.dbg.cu = !{!0}
63 !llvm.module.flags = !{!3}
64 !llvm.ident = !{!8}
65 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
66 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
67 !3 = !{i32 2, !"Debug Info Version", i32 3}
68 !8 = !{!"clang"}
69 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
70 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
71 !11 = !DISubroutineType(types: !12)
72 !12 = !{!13, !13}
73 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
74 !14 = !{!15}
75 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
76 !16 = !DILocation(line: 0, scope: !9)
77 !17 = !DILocation(line: 2, column: 11, scope: !9))";
79 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
80 ASSERT_TRUE(M);
82 DroppedVariableStats Stats(true);
83 Stats.runBeforePass("Test",
84 llvm::Any(const_cast<const llvm::Module *>(M.get())));
86 // This loop simulates an IR pass that drops debug information.
87 for (auto &F : *M) {
88 for (auto &I : instructions(&F)) {
89 I.dropDbgRecords();
90 I.eraseFromParent();
91 break;
93 break;
95 PreservedAnalyses PA;
96 Stats.runAfterPass("Test",
97 llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
98 ASSERT_EQ(Stats.getPassDroppedVariables(), false);
101 // This test ensures that if a #dbg_value is dropped after an optimization pass,
102 // but an instruction that shares the same scope as the #dbg_value still exists,
103 // debug information is conisdered dropped.
104 TEST(DroppedVariableStats, DbgValLost) {
105 PassInstrumentationCallbacks PIC;
106 PassInstrumentation PI(&PIC);
108 LLVMContext C;
110 const char *IR =
112 ; Function Attrs: mustprogress nounwind ssp uwtable(sync)
113 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
114 entry:
115 #dbg_value(i32 %x, !15, !DIExpression(), !16)
116 %add = add nsw i32 %x, 1, !dbg !17
117 ret i32 0
119 !llvm.dbg.cu = !{!0}
120 !llvm.module.flags = !{!3}
121 !llvm.ident = !{!8}
122 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
123 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
124 !3 = !{i32 2, !"Debug Info Version", i32 3}
125 !8 = !{!"clang"}
126 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
127 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
128 !11 = !DISubroutineType(types: !12)
129 !12 = !{!13, !13}
130 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
131 !14 = !{!15}
132 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
133 !16 = !DILocation(line: 0, scope: !9)
134 !17 = !DILocation(line: 2, column: 11, scope: !9))";
136 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
137 ASSERT_TRUE(M);
139 DroppedVariableStats Stats(true);
140 Stats.runBeforePass("Test",
141 llvm::Any(const_cast<const llvm::Module *>(M.get())));
143 // This loop simulates an IR pass that drops debug information.
144 for (auto &F : *M) {
145 for (auto &I : instructions(&F)) {
146 I.dropDbgRecords();
147 break;
149 break;
151 PreservedAnalyses PA;
152 Stats.runAfterPass("Test",
153 llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
154 ASSERT_EQ(Stats.getPassDroppedVariables(), true);
157 // This test ensures that if a #dbg_value is dropped after an optimization pass,
158 // but an instruction that has an unrelated scope as the #dbg_value still
159 // exists, debug information is conisdered not dropped.
160 TEST(DroppedVariableStats, UnrelatedScopes) {
161 PassInstrumentationCallbacks PIC;
162 PassInstrumentation PI(&PIC);
164 LLVMContext C;
166 const char *IR =
168 ; Function Attrs: mustprogress nounwind ssp uwtable(sync)
169 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
170 entry:
171 #dbg_value(i32 %x, !15, !DIExpression(), !16)
172 %add = add nsw i32 %x, 1, !dbg !17
173 ret i32 0
175 !llvm.dbg.cu = !{!0}
176 !llvm.module.flags = !{!3}
177 !llvm.ident = !{!8}
178 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
179 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
180 !3 = !{i32 2, !"Debug Info Version", i32 3}
181 !8 = !{!"clang"}
182 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
183 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
184 !11 = !DISubroutineType(types: !12)
185 !12 = !{!13, !13}
186 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
187 !14 = !{!15}
188 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
189 !16 = !DILocation(line: 0, scope: !9)
190 !17 = !DILocation(line: 2, column: 11, scope: !18)
191 !18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3bari", scope: !10, file: !10, line: 11, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14))";
193 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
194 ASSERT_TRUE(M);
196 DroppedVariableStats Stats(true);
197 Stats.runBeforePass("Test",
198 llvm::Any(const_cast<const llvm::Module *>(M.get())));
200 // This loop simulates an IR pass that drops debug information.
201 for (auto &F : *M) {
202 for (auto &I : instructions(&F)) {
203 I.dropDbgRecords();
204 break;
206 break;
208 PreservedAnalyses PA;
209 Stats.runAfterPass("Test",
210 llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
211 ASSERT_EQ(Stats.getPassDroppedVariables(), false);
214 // This test ensures that if a #dbg_value is dropped after an optimization pass,
215 // but an instruction that has a scope which is a child of the #dbg_value scope
216 // still exists, debug information is conisdered dropped.
217 TEST(DroppedVariableStats, ChildScopes) {
218 PassInstrumentationCallbacks PIC;
219 PassInstrumentation PI(&PIC);
221 LLVMContext C;
223 const char *IR =
225 ; Function Attrs: mustprogress nounwind ssp uwtable(sync)
226 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
227 entry:
228 #dbg_value(i32 %x, !15, !DIExpression(), !16)
229 %add = add nsw i32 %x, 1, !dbg !17
230 ret i32 0
232 !llvm.dbg.cu = !{!0}
233 !llvm.module.flags = !{!3}
234 !llvm.ident = !{!8}
235 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
236 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
237 !3 = !{i32 2, !"Debug Info Version", i32 3}
238 !8 = !{!"clang"}
239 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
240 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
241 !11 = !DISubroutineType(types: !12)
242 !12 = !{!13, !13}
243 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
244 !14 = !{!15}
245 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
246 !16 = !DILocation(line: 0, scope: !9)
247 !17 = !DILocation(line: 2, column: 11, scope: !18)
248 !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28))";
250 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
251 ASSERT_TRUE(M);
253 DroppedVariableStats Stats(true);
254 Stats.runBeforePass("Test",
255 llvm::Any(const_cast<const llvm::Module *>(M.get())));
257 // This loop simulates an IR pass that drops debug information.
258 for (auto &F : *M) {
259 for (auto &I : instructions(&F)) {
260 I.dropDbgRecords();
261 break;
263 break;
265 PreservedAnalyses PA;
266 Stats.runAfterPass("Test",
267 llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
268 ASSERT_EQ(Stats.getPassDroppedVariables(), true);
271 // This test ensures that if a #dbg_value is dropped after an optimization pass,
272 // but an instruction that has a scope which is a child of the #dbg_value scope
273 // still exists, and the #dbg_value is inlined at another location, debug
274 // information is conisdered not dropped.
275 TEST(DroppedVariableStats, InlinedAt) {
276 PassInstrumentationCallbacks PIC;
277 PassInstrumentation PI(&PIC);
279 LLVMContext C;
281 const char *IR =
282 R"(; Function Attrs: mustprogress nounwind ssp uwtable(sync)
283 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
284 entry:
285 #dbg_value(i32 %x, !15, !DIExpression(), !16)
286 %add = add nsw i32 %x, 1, !dbg !17
287 ret i32 0
289 !llvm.dbg.cu = !{!0}
290 !llvm.module.flags = !{!3}
291 !llvm.ident = !{!8}
292 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
293 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
294 !3 = !{i32 2, !"Debug Info Version", i32 3}
295 !8 = !{!"clang"}
296 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
297 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
298 !11 = !DISubroutineType(types: !12)
299 !12 = !{!13, !13}
300 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
301 !14 = !{!15}
302 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
303 !16 = !DILocation(line: 0, scope: !9, inlinedAt: !19)
304 !17 = !DILocation(line: 2, column: 11, scope: !18)
305 !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28)
306 !19 = !DILocation(line: 3, column: 2, scope: !9))";
308 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
309 ASSERT_TRUE(M);
311 DroppedVariableStats Stats(true);
312 Stats.runBeforePass("Test",
313 llvm::Any(const_cast<const llvm::Module *>(M.get())));
315 // This loop simulates an IR pass that drops debug information.
316 for (auto &F : *M) {
317 for (auto &I : instructions(&F)) {
318 I.dropDbgRecords();
319 break;
321 break;
323 PreservedAnalyses PA;
324 Stats.runAfterPass("Test",
325 llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
326 ASSERT_EQ(Stats.getPassDroppedVariables(), false);
329 // This test ensures that if a #dbg_value is dropped after an optimization pass,
330 // but an instruction that has a scope which is a child of the #dbg_value scope
331 // still exists, and the #dbg_value and the instruction are inlined at another
332 // location, debug information is conisdered dropped.
333 TEST(DroppedVariableStats, InlinedAtShared) {
334 PassInstrumentationCallbacks PIC;
335 PassInstrumentation PI(&PIC);
337 LLVMContext C;
339 const char *IR =
340 R"(; Function Attrs: mustprogress nounwind ssp uwtable(sync)
341 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
342 entry:
343 #dbg_value(i32 %x, !15, !DIExpression(), !16)
344 %add = add nsw i32 %x, 1, !dbg !17
345 ret i32 0
347 !llvm.dbg.cu = !{!0}
348 !llvm.module.flags = !{!3}
349 !llvm.ident = !{!8}
350 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
351 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
352 !3 = !{i32 2, !"Debug Info Version", i32 3}
353 !8 = !{!"clang"}
354 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
355 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
356 !11 = !DISubroutineType(types: !12)
357 !12 = !{!13, !13}
358 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
359 !14 = !{!15}
360 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
361 !16 = !DILocation(line: 0, scope: !9, inlinedAt: !19)
362 !17 = !DILocation(line: 2, column: 11, scope: !18, inlinedAt: !19)
363 !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28)
364 !19 = !DILocation(line: 3, column: 2, scope: !9))";
366 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
367 ASSERT_TRUE(M);
369 DroppedVariableStats Stats(true);
370 Stats.runBeforePass("Test",
371 llvm::Any(const_cast<const llvm::Module *>(M.get())));
373 // This loop simulates an IR pass that drops debug information.
374 for (auto &F : *M) {
375 for (auto &I : instructions(&F)) {
376 I.dropDbgRecords();
377 break;
379 break;
381 PreservedAnalyses PA;
382 Stats.runAfterPass("Test",
383 llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
384 ASSERT_EQ(Stats.getPassDroppedVariables(), true);
387 // This test ensures that if a #dbg_value is dropped after an optimization pass,
388 // but an instruction that has a scope which is a child of the #dbg_value scope
389 // still exists, and the instruction is inlined at a location that is the
390 // #dbg_value's inlined at location, debug information is conisdered dropped.
391 TEST(DroppedVariableStats, InlinedAtChild) {
392 PassInstrumentationCallbacks PIC;
393 PassInstrumentation PI(&PIC);
395 LLVMContext C;
397 const char *IR =
398 R"(; Function Attrs: mustprogress nounwind ssp uwtable(sync)
399 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
400 entry:
401 #dbg_value(i32 %x, !15, !DIExpression(), !16)
402 %add = add nsw i32 %x, 1, !dbg !17
403 ret i32 0
405 !llvm.dbg.cu = !{!0}
406 !llvm.module.flags = !{!3}
407 !llvm.ident = !{!8}
408 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: Apple, sysroot: "/")
409 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
410 !3 = !{i32 2, !"Debug Info Version", i32 3}
411 !8 = !{!"clang"}
412 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
413 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
414 !11 = !DISubroutineType(types: !12)
415 !12 = !{!13, !13}
416 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
417 !14 = !{!15}
418 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
419 !16 = !DILocation(line: 0, scope: !9, inlinedAt: !19)
420 !17 = !DILocation(line: 2, column: 11, scope: !18, inlinedAt: !20)
421 !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28)
422 !19 = !DILocation(line: 3, column: 2, scope: !9);
423 !20 = !DILocation(line: 4, column: 5, scope: !18, inlinedAt: !19))";
425 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
426 ASSERT_TRUE(M);
428 DroppedVariableStats Stats(true);
429 Stats.runBeforePass("Test",
430 llvm::Any(const_cast<const llvm::Module *>(M.get())));
432 // This loop simulates an IR pass that drops debug information.
433 for (auto &F : *M) {
434 for (auto &I : instructions(&F)) {
435 I.dropDbgRecords();
436 break;
438 break;
440 PreservedAnalyses PA;
441 Stats.runAfterPass("Test",
442 llvm::Any(const_cast<const llvm::Module *>(M.get())), PA);
443 ASSERT_EQ(Stats.getPassDroppedVariables(), true);
446 } // end anonymous namespace