[TableGen][GISel] Add const to some member functions & reformat (NFC) (#120899)
[llvm-project.git] / llvm / unittests / IR / DroppedVariableStatsIRTest.cpp
blob34803a9771850a0a2dee8b5a3251aba6334737b8
1 //===- unittests/IR/DroppedVariableStatsIRTest.cpp ------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "llvm/AsmParser/Parser.h"
10 #include "llvm/IR/Function.h"
11 #include "llvm/IR/InstIterator.h"
12 #include "llvm/IR/LegacyPassManager.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/Pass.h"
15 #include "llvm/PassRegistry.h"
16 #include "llvm/Passes/StandardInstrumentations.h"
17 #include "llvm/Support/SourceMgr.h"
18 #include "gtest/gtest.h"
19 #include <gtest/gtest.h>
20 #include <llvm/ADT/SmallString.h>
21 #include <llvm/IR/LLVMContext.h>
22 #include <llvm/IR/Module.h>
23 #include <llvm/IR/PassInstrumentation.h>
24 #include <llvm/IR/PassManager.h>
25 #include <llvm/IR/PassTimingInfo.h>
26 #include <llvm/Support/raw_ostream.h>
28 using namespace llvm;
29 namespace llvm {
30 void initializePassTest1Pass(PassRegistry &);
32 static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
33 SMDiagnostic Err;
34 std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
35 if (!Mod)
36 Err.print("AbstractCallSiteTests", errs());
37 return Mod;
39 } // namespace llvm
41 namespace {
43 // This test ensures that if a #dbg_value and an instruction that exists in the
44 // same scope as that #dbg_value are both deleted as a result of an optimization
45 // pass, debug information is considered not dropped.
46 TEST(DroppedVariableStatsIR, BothDeleted) {
47 PassInstrumentationCallbacks PIC;
48 PassInstrumentation PI(&PIC);
50 LLVMContext C;
52 const char *IR =
53 R"(
54 ; Function Attrs: mustprogress nounwind ssp uwtable(sync)
55 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
56 entry:
57 #dbg_value(i32 %x, !15, !DIExpression(), !16)
58 %add = add nsw i32 %x, 1, !dbg !17
59 ret i32 0
61 !llvm.dbg.cu = !{!0}
62 !llvm.module.flags = !{!3}
63 !llvm.ident = !{!8}
64 !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: "/")
65 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
66 !3 = !{i32 2, !"Debug Info Version", i32 3}
67 !8 = !{!"clang"}
68 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
69 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
70 !11 = !DISubroutineType(types: !12)
71 !12 = !{!13, !13}
72 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
73 !14 = !{!15}
74 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
75 !16 = !DILocation(line: 0, scope: !9)
76 !17 = !DILocation(line: 2, column: 11, scope: !9))";
78 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
79 ASSERT_TRUE(M);
81 DroppedVariableStatsIR Stats(true);
82 Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
84 // This loop simulates an IR pass that drops debug information.
85 for (auto &F : *M) {
86 for (auto &I : instructions(&F)) {
87 I.dropDbgRecords();
88 I.eraseFromParent();
89 break;
91 break;
93 Stats.runAfterPass("Test",
94 llvm::Any(const_cast<const llvm::Module *>(M.get())));
95 ASSERT_EQ(Stats.getPassDroppedVariables(), false);
98 // This test ensures that if a #dbg_value is dropped after an optimization pass,
99 // but an instruction that shares the same scope as the #dbg_value still exists,
100 // debug information is conisdered dropped.
101 TEST(DroppedVariableStatsIR, DbgValLost) {
102 PassInstrumentationCallbacks PIC;
103 PassInstrumentation PI(&PIC);
105 LLVMContext C;
107 const char *IR =
109 ; Function Attrs: mustprogress nounwind ssp uwtable(sync)
110 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
111 entry:
112 #dbg_value(i32 %x, !15, !DIExpression(), !16)
113 %add = add nsw i32 %x, 1, !dbg !17
114 ret i32 0
116 !llvm.dbg.cu = !{!0}
117 !llvm.module.flags = !{!3}
118 !llvm.ident = !{!8}
119 !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: "/")
120 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
121 !3 = !{i32 2, !"Debug Info Version", i32 3}
122 !8 = !{!"clang"}
123 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
124 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
125 !11 = !DISubroutineType(types: !12)
126 !12 = !{!13, !13}
127 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
128 !14 = !{!15}
129 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
130 !16 = !DILocation(line: 0, scope: !9)
131 !17 = !DILocation(line: 2, column: 11, scope: !9))";
133 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
134 ASSERT_TRUE(M);
136 DroppedVariableStatsIR Stats(true);
137 Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
139 // This loop simulates an IR pass that drops debug information.
140 for (auto &F : *M) {
141 for (auto &I : instructions(&F)) {
142 I.dropDbgRecords();
143 break;
145 break;
147 Stats.runAfterPass("Test",
148 llvm::Any(const_cast<const llvm::Module *>(M.get())));
149 ASSERT_EQ(Stats.getPassDroppedVariables(), true);
152 // This test ensures that if a #dbg_value is dropped after an optimization pass,
153 // but an instruction that has an unrelated scope as the #dbg_value still
154 // exists, debug information is conisdered not dropped.
155 TEST(DroppedVariableStatsIR, UnrelatedScopes) {
156 PassInstrumentationCallbacks PIC;
157 PassInstrumentation PI(&PIC);
159 LLVMContext C;
161 const char *IR =
163 ; Function Attrs: mustprogress nounwind ssp uwtable(sync)
164 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
165 entry:
166 #dbg_value(i32 %x, !15, !DIExpression(), !16)
167 %add = add nsw i32 %x, 1, !dbg !17
168 ret i32 0
170 !llvm.dbg.cu = !{!0}
171 !llvm.module.flags = !{!3}
172 !llvm.ident = !{!8}
173 !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: "/")
174 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
175 !3 = !{i32 2, !"Debug Info Version", i32 3}
176 !8 = !{!"clang"}
177 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
178 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
179 !11 = !DISubroutineType(types: !12)
180 !12 = !{!13, !13}
181 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
182 !14 = !{!15}
183 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
184 !16 = !DILocation(line: 0, scope: !9)
185 !17 = !DILocation(line: 2, column: 11, scope: !18)
186 !18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3bari", scope: !10, file: !10, line: 11, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14))";
188 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
189 ASSERT_TRUE(M);
191 DroppedVariableStatsIR Stats(true);
192 Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
194 // This loop simulates an IR pass that drops debug information.
195 for (auto &F : *M) {
196 for (auto &I : instructions(&F)) {
197 I.dropDbgRecords();
198 break;
200 break;
202 Stats.runAfterPass("Test",
203 llvm::Any(const_cast<const llvm::Module *>(M.get())));
204 ASSERT_EQ(Stats.getPassDroppedVariables(), false);
207 // This test ensures that if a #dbg_value is dropped after an optimization pass,
208 // but an instruction that has a scope which is a child of the #dbg_value scope
209 // still exists, debug information is conisdered dropped.
210 TEST(DroppedVariableStatsIR, ChildScopes) {
211 PassInstrumentationCallbacks PIC;
212 PassInstrumentation PI(&PIC);
214 LLVMContext C;
216 const char *IR =
218 ; Function Attrs: mustprogress nounwind ssp uwtable(sync)
219 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
220 entry:
221 #dbg_value(i32 %x, !15, !DIExpression(), !16)
222 %add = add nsw i32 %x, 1, !dbg !17
223 ret i32 0
225 !llvm.dbg.cu = !{!0}
226 !llvm.module.flags = !{!3}
227 !llvm.ident = !{!8}
228 !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: "/")
229 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
230 !3 = !{i32 2, !"Debug Info Version", i32 3}
231 !8 = !{!"clang"}
232 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
233 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
234 !11 = !DISubroutineType(types: !12)
235 !12 = !{!13, !13}
236 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
237 !14 = !{!15}
238 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
239 !16 = !DILocation(line: 0, scope: !9)
240 !17 = !DILocation(line: 2, column: 11, scope: !18)
241 !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28))";
243 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
244 ASSERT_TRUE(M);
246 DroppedVariableStatsIR Stats(true);
247 Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
249 // This loop simulates an IR pass that drops debug information.
250 for (auto &F : *M) {
251 for (auto &I : instructions(&F)) {
252 I.dropDbgRecords();
253 break;
255 break;
257 Stats.runAfterPass("Test",
258 llvm::Any(const_cast<const llvm::Module *>(M.get())));
259 ASSERT_EQ(Stats.getPassDroppedVariables(), true);
262 // This test ensures that if a #dbg_value is dropped after an optimization pass,
263 // but an instruction that has a scope which is a child of the #dbg_value scope
264 // still exists, and the #dbg_value is inlined at another location, debug
265 // information is conisdered not dropped.
266 TEST(DroppedVariableStatsIR, InlinedAt) {
267 PassInstrumentationCallbacks PIC;
268 PassInstrumentation PI(&PIC);
270 LLVMContext C;
272 const char *IR =
273 R"(; Function Attrs: mustprogress nounwind ssp uwtable(sync)
274 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
275 entry:
276 #dbg_value(i32 %x, !15, !DIExpression(), !16)
277 %add = add nsw i32 %x, 1, !dbg !17
278 ret i32 0
280 !llvm.dbg.cu = !{!0}
281 !llvm.module.flags = !{!3}
282 !llvm.ident = !{!8}
283 !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: "/")
284 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
285 !3 = !{i32 2, !"Debug Info Version", i32 3}
286 !8 = !{!"clang"}
287 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
288 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
289 !11 = !DISubroutineType(types: !12)
290 !12 = !{!13, !13}
291 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
292 !14 = !{!15}
293 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
294 !16 = !DILocation(line: 0, scope: !9, inlinedAt: !19)
295 !17 = !DILocation(line: 2, column: 11, scope: !18)
296 !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28)
297 !19 = !DILocation(line: 3, column: 2, scope: !9))";
299 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
300 ASSERT_TRUE(M);
302 DroppedVariableStatsIR Stats(true);
303 Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
305 // This loop simulates an IR pass that drops debug information.
306 for (auto &F : *M) {
307 for (auto &I : instructions(&F)) {
308 I.dropDbgRecords();
309 break;
311 break;
313 Stats.runAfterPass("Test",
314 llvm::Any(const_cast<const llvm::Module *>(M.get())));
315 ASSERT_EQ(Stats.getPassDroppedVariables(), false);
318 // This test ensures that if a #dbg_value is dropped after an optimization pass,
319 // but an instruction that has a scope which is a child of the #dbg_value scope
320 // still exists, and the #dbg_value and the instruction are inlined at another
321 // location, debug information is conisdered dropped.
322 TEST(DroppedVariableStatsIR, InlinedAtShared) {
323 PassInstrumentationCallbacks PIC;
324 PassInstrumentation PI(&PIC);
326 LLVMContext C;
328 const char *IR =
329 R"(; Function Attrs: mustprogress nounwind ssp uwtable(sync)
330 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
331 entry:
332 #dbg_value(i32 %x, !15, !DIExpression(), !16)
333 %add = add nsw i32 %x, 1, !dbg !17
334 ret i32 0
336 !llvm.dbg.cu = !{!0}
337 !llvm.module.flags = !{!3}
338 !llvm.ident = !{!8}
339 !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: "/")
340 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
341 !3 = !{i32 2, !"Debug Info Version", i32 3}
342 !8 = !{!"clang"}
343 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
344 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
345 !11 = !DISubroutineType(types: !12)
346 !12 = !{!13, !13}
347 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
348 !14 = !{!15}
349 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
350 !16 = !DILocation(line: 0, scope: !9, inlinedAt: !19)
351 !17 = !DILocation(line: 2, column: 11, scope: !18, inlinedAt: !19)
352 !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28)
353 !19 = !DILocation(line: 3, column: 2, scope: !9))";
355 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
356 ASSERT_TRUE(M);
358 DroppedVariableStatsIR Stats(true);
359 Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
361 // This loop simulates an IR pass that drops debug information.
362 for (auto &F : *M) {
363 for (auto &I : instructions(&F)) {
364 I.dropDbgRecords();
365 break;
367 break;
369 Stats.runAfterPass("Test",
370 llvm::Any(const_cast<const llvm::Module *>(M.get())));
371 ASSERT_EQ(Stats.getPassDroppedVariables(), true);
374 // This test ensures that if a #dbg_value is dropped after an optimization pass,
375 // but an instruction that has a scope which is a child of the #dbg_value scope
376 // still exists, and the instruction is inlined at a location that is the
377 // #dbg_value's inlined at location, debug information is conisdered dropped.
378 TEST(DroppedVariableStatsIR, InlinedAtChild) {
379 PassInstrumentationCallbacks PIC;
380 PassInstrumentation PI(&PIC);
382 LLVMContext C;
384 const char *IR =
385 R"(; Function Attrs: mustprogress nounwind ssp uwtable(sync)
386 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr #0 !dbg !9 {
387 entry:
388 #dbg_value(i32 %x, !15, !DIExpression(), !16)
389 %add = add nsw i32 %x, 1, !dbg !17
390 ret i32 0
392 !llvm.dbg.cu = !{!0}
393 !llvm.module.flags = !{!3}
394 !llvm.ident = !{!8}
395 !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: "/")
396 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
397 !3 = !{i32 2, !"Debug Info Version", i32 3}
398 !8 = !{!"clang"}
399 !9 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !10, file: !10, line: 1, type: !11, scopeLine: 1, unit: !0, retainedNodes: !14)
400 !10 = !DIFile(filename: "/tmp/code.cpp", directory: "")
401 !11 = !DISubroutineType(types: !12)
402 !12 = !{!13, !13}
403 !13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
404 !14 = !{!15}
405 !15 = !DILocalVariable(name: "x", arg: 1, scope: !9, file: !10, line: 1, type: !13)
406 !16 = !DILocation(line: 0, scope: !9, inlinedAt: !19)
407 !17 = !DILocation(line: 2, column: 11, scope: !18, inlinedAt: !20)
408 !18 = distinct !DILexicalBlock(scope: !9, file: !10, line: 10, column: 28)
409 !19 = !DILocation(line: 3, column: 2, scope: !9);
410 !20 = !DILocation(line: 4, column: 5, scope: !18, inlinedAt: !19))";
412 std::unique_ptr<llvm::Module> M = parseIR(C, IR);
413 ASSERT_TRUE(M);
415 DroppedVariableStatsIR Stats(true);
416 Stats.runBeforePass(llvm::Any(const_cast<const llvm::Module *>(M.get())));
418 // This loop simulates an IR pass that drops debug information.
419 for (auto &F : *M) {
420 for (auto &I : instructions(&F)) {
421 I.dropDbgRecords();
422 break;
424 break;
426 Stats.runAfterPass("Test",
427 llvm::Any(const_cast<const llvm::Module *>(M.get())));
428 ASSERT_EQ(Stats.getPassDroppedVariables(), true);
431 } // end anonymous namespace