1080 lines · cpp
1//===- unittests/CodeGen/DroppedVariableStatsMIRTest.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/CodeGen/DroppedVariableStatsMIR.h"10#include "llvm/AsmParser/Parser.h"11#include "llvm/CodeGen/MIRParser/MIRParser.h"12#include "llvm/CodeGen/MachineModuleInfo.h"13#include "llvm/IR/Function.h"14#include "llvm/IR/LegacyPassManager.h"15#include "llvm/IR/Module.h"16#include "llvm/MC/TargetRegistry.h"17#include "llvm/Pass.h"18#include "llvm/Support/SourceMgr.h"19#include "llvm/Support/TargetSelect.h"20#include "llvm/Target/TargetMachine.h"21#include "gtest/gtest.h"22#include <llvm/ADT/SmallString.h>23#include <llvm/IR/LLVMContext.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>28 29using namespace llvm;30 31namespace {32 33std::unique_ptr<TargetMachine>34createTargetMachine(std::string TargetStr, StringRef CPU, StringRef FS) {35 std::string Error;36 Triple TT(TargetStr);37 const Target *T = TargetRegistry::lookupTarget(TT, Error);38 if (!T)39 return nullptr;40 TargetOptions Options;41 return std::unique_ptr<TargetMachine>(42 T->createTargetMachine(TT, CPU, FS, Options, std::nullopt, std::nullopt));43}44 45std::unique_ptr<Module> parseMIR(const TargetMachine &TM, StringRef MIRCode,46 MachineModuleInfo &MMI, LLVMContext *Context) {47 SMDiagnostic Diagnostic;48 std::unique_ptr<Module> M;49 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);50 auto MIR = createMIRParser(std::move(MBuffer), *Context);51 if (!MIR)52 return nullptr;53 54 std::unique_ptr<Module> Mod = MIR->parseIRModule();55 if (!Mod)56 return nullptr;57 58 Mod->setDataLayout(TM.createDataLayout());59 60 if (MIR->parseMachineFunctions(*Mod, MMI)) {61 M.reset();62 return nullptr;63 }64 return Mod;65}66// This test ensures that if a DBG_VALUE and an instruction that exists in the67// same scope as that DBG_VALUE are both deleted as a result of an optimization68// pass, debug information is considered not dropped.69TEST(DroppedVariableStatsMIR, BothDeleted) {70 InitializeAllTargetInfos();71 InitializeAllTargets();72 InitializeAllTargetMCs();73 PassInstrumentationCallbacks PIC;74 PassInstrumentation PI(&PIC);75 76 LLVMContext C;77 78 const char *MIR =79 R"(80--- |81 ; ModuleID = '/tmp/test.ll'82 source_filename = "/tmp/test.ll"83 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"84 85 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {86 entry:87 #dbg_value(i32 %x, !10, !DIExpression(), !11)88 %add = add nsw i32 %x, 1, !dbg !1289 ret i32 090 }91 92 !llvm.dbg.cu = !{!0}93 !llvm.module.flags = !{!2}94 !llvm.ident = !{!3}95 96 !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: "/")97 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")98 !2 = !{i32 2, !"Debug Info Version", i32 3}99 !3 = !{!"clang"}100 !4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)101 !5 = !DIFile(filename: "/tmp/code.cpp", directory: "")102 !6 = !DISubroutineType(types: !7)103 !7 = !{!8, !8}104 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)105 !9 = !{!10}106 !10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)107 !11 = !DILocation(line: 0, scope: !4)108 !12 = !DILocation(line: 2, column: 11, scope: !4)109 110...111---112name: _Z3fooi113alignment: 4114exposesReturnsTwice: false115legalized: false116regBankSelected: false117selected: false118failedISel: false119tracksRegLiveness: true120hasWinCFI: false121noPhis: false122isSSA: true123noVRegs: false124hasFakeUses: false125callsEHReturn: false126callsUnwindInit: false127hasEHContTarget: false128hasEHScopes: false129hasEHFunclets: false130isOutlined: false131debugInstrRef: false132failsVerification: false133tracksDebugUserValues: false134registers:135 - { id: 0, class: _, preferred-register: '', flags: [ ] }136 - { id: 1, class: _, preferred-register: '', flags: [ ] }137 - { id: 2, class: _, preferred-register: '', flags: [ ] }138 - { id: 3, class: _, preferred-register: '', flags: [ ] }139liveins:140 - { reg: '$w0', virtual-reg: '' }141frameInfo:142 isFrameAddressTaken: false143 isReturnAddressTaken: false144 hasStackMap: false145 hasPatchPoint: false146 stackSize: 0147 offsetAdjustment: 0148 maxAlignment: 1149 adjustsStack: false150 hasCalls: false151 stackProtector: ''152 functionContext: ''153 maxCallFrameSize: 4294967295154 cvBytesOfCalleeSavedRegisters: 0155 hasOpaqueSPAdjustment: false156 hasVAStart: false157 hasMustTailInVarArgFunc: false158 hasTailCall: false159 isCalleeSavedInfoValid: false160 localFrameSize: 0161 savePoint: []162 restorePoint: []163fixedStack: []164stack: []165entry_values: []166callSites: []167debugValueSubstitutions: []168constants: []169machineFunctionInfo: {}170body: |171 bb.1.entry:172 liveins: $w0173 174 %0:_(s32) = COPY $w0175 %1:_(s32) = G_CONSTANT i32 1176 %3:_(s32) = G_CONSTANT i32 0177 DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11178 %2:_(s32) = nsw G_ADD %0, %1, debug-location !12179 $w0 = COPY %3(s32)180 RET_ReallyLR implicit $w0181 )";182 auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");183 if (!TM)184 return;185 MachineModuleInfo MMI(TM.get());186 std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);187 ASSERT_TRUE(M);188 189 DroppedVariableStatsMIR Stats;190 auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));191 Stats.runBeforePass("Test", MF);192 193 // This loop simulates an IR pass that drops debug information.194 for (auto &MBB : *MF) {195 for (auto &MI : MBB) {196 if (MI.isDebugValueLike()) {197 MI.eraseFromParent();198 break;199 }200 }201 for (auto &MI : MBB) {202 auto *DbgLoc = MI.getDebugLoc().get();203 if (DbgLoc) {204 MI.eraseFromParent();205 break;206 }207 }208 break;209 }210 211 Stats.runAfterPass("Test", MF);212 ASSERT_EQ(Stats.getPassDroppedVariables(), false);213}214 215// This test ensures that if a DBG_VALUE is dropped after an optimization pass,216// but an instruction that shares the same scope as the DBG_VALUE still exists,217// debug information is conisdered dropped.218TEST(DroppedVariableStatsMIR, DbgValLost) {219 InitializeAllTargetInfos();220 InitializeAllTargets();221 InitializeAllTargetMCs();222 PassInstrumentationCallbacks PIC;223 PassInstrumentation PI(&PIC);224 225 LLVMContext C;226 227 const char *MIR =228 R"(229--- |230 ; ModuleID = '/tmp/test.ll'231 source_filename = "/tmp/test.ll"232 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"233 234 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {235 entry:236 #dbg_value(i32 %x, !10, !DIExpression(), !11)237 %add = add nsw i32 %x, 1, !dbg !12238 ret i32 0239 }240 241 !llvm.dbg.cu = !{!0}242 !llvm.module.flags = !{!2}243 !llvm.ident = !{!3}244 245 !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: "/")246 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")247 !2 = !{i32 2, !"Debug Info Version", i32 3}248 !3 = !{!"clang"}249 !4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)250 !5 = !DIFile(filename: "/tmp/code.cpp", directory: "")251 !6 = !DISubroutineType(types: !7)252 !7 = !{!8, !8}253 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)254 !9 = !{!10}255 !10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)256 !11 = !DILocation(line: 0, scope: !4)257 !12 = !DILocation(line: 2, column: 11, scope: !4)258 259...260---261name: _Z3fooi262alignment: 4263exposesReturnsTwice: false264legalized: false265regBankSelected: false266selected: false267failedISel: false268tracksRegLiveness: true269hasWinCFI: false270noPhis: false271isSSA: true272noVRegs: false273hasFakeUses: false274callsEHReturn: false275callsUnwindInit: false276hasEHContTarget: false277hasEHScopes: false278hasEHFunclets: false279isOutlined: false280debugInstrRef: false281failsVerification: false282tracksDebugUserValues: false283registers:284 - { id: 0, class: _, preferred-register: '', flags: [ ] }285 - { id: 1, class: _, preferred-register: '', flags: [ ] }286 - { id: 2, class: _, preferred-register: '', flags: [ ] }287 - { id: 3, class: _, preferred-register: '', flags: [ ] }288liveins:289 - { reg: '$w0', virtual-reg: '' }290frameInfo:291 isFrameAddressTaken: false292 isReturnAddressTaken: false293 hasStackMap: false294 hasPatchPoint: false295 stackSize: 0296 offsetAdjustment: 0297 maxAlignment: 1298 adjustsStack: false299 hasCalls: false300 stackProtector: ''301 functionContext: ''302 maxCallFrameSize: 4294967295303 cvBytesOfCalleeSavedRegisters: 0304 hasOpaqueSPAdjustment: false305 hasVAStart: false306 hasMustTailInVarArgFunc: false307 hasTailCall: false308 isCalleeSavedInfoValid: false309 localFrameSize: 0310 savePoint: []311 restorePoint: []312fixedStack: []313stack: []314entry_values: []315callSites: []316debugValueSubstitutions: []317constants: []318machineFunctionInfo: {}319body: |320 bb.1.entry:321 liveins: $w0322 323 %0:_(s32) = COPY $w0324 %1:_(s32) = G_CONSTANT i32 1325 %3:_(s32) = G_CONSTANT i32 0326 DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11327 %2:_(s32) = nsw G_ADD %0, %1, debug-location !12328 $w0 = COPY %3(s32)329 RET_ReallyLR implicit $w0330 )";331 auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");332 if (!TM)333 return;334 MachineModuleInfo MMI(TM.get());335 std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);336 ASSERT_TRUE(M);337 338 DroppedVariableStatsMIR Stats;339 auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));340 Stats.runBeforePass("Test", MF);341 342 // This loop simulates an IR pass that drops debug information.343 for (auto &MBB : *MF) {344 for (auto &MI : MBB) {345 if (MI.isDebugValueLike()) {346 MI.eraseFromParent();347 break;348 }349 }350 break;351 }352 353 Stats.runAfterPass("Test", MF);354 ASSERT_EQ(Stats.getPassDroppedVariables(), true);355}356 357// This test ensures that if a #dbg_value is dropped after an optimization pass,358// but an instruction that has an unrelated scope as the #dbg_value still359// exists, debug information is conisdered not dropped.360TEST(DroppedVariableStatsMIR, UnrelatedScopes) {361 InitializeAllTargetInfos();362 InitializeAllTargets();363 InitializeAllTargetMCs();364 PassInstrumentationCallbacks PIC;365 PassInstrumentation PI(&PIC);366 367 LLVMContext C;368 369 const char *MIR =370 R"(371--- |372 ; ModuleID = '/tmp/test.ll'373 source_filename = "/tmp/test.ll"374 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"375 376 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {377 entry:378 #dbg_value(i32 %x, !10, !DIExpression(), !11)379 %add = add nsw i32 %x, 1, !dbg !12380 ret i32 0381 }382 383 !llvm.dbg.cu = !{!0}384 !llvm.module.flags = !{!2}385 !llvm.ident = !{!3}386 387 !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: "/")388 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")389 !2 = !{i32 2, !"Debug Info Version", i32 3}390 !3 = !{!"clang"}391 !4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)392 !5 = !DIFile(filename: "/tmp/code.cpp", directory: "")393 !6 = !DISubroutineType(types: !7)394 !7 = !{!8, !8}395 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)396 !9 = !{!10}397 !10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)398 !11 = !DILocation(line: 0, scope: !4)399 !12 = !DILocation(line: 2, column: 11, scope: !13)400 !13 = distinct !DISubprogram(name: "bar", linkageName: "_Z3bari", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)401 402...403---404name: _Z3fooi405alignment: 4406exposesReturnsTwice: false407legalized: false408regBankSelected: false409selected: false410failedISel: false411tracksRegLiveness: true412hasWinCFI: false413noPhis: false414isSSA: true415noVRegs: false416hasFakeUses: false417callsEHReturn: false418callsUnwindInit: false419hasEHContTarget: false420hasEHScopes: false421hasEHFunclets: false422isOutlined: false423debugInstrRef: false424failsVerification: false425tracksDebugUserValues: false426registers:427 - { id: 0, class: _, preferred-register: '', flags: [ ] }428 - { id: 1, class: _, preferred-register: '', flags: [ ] }429 - { id: 2, class: _, preferred-register: '', flags: [ ] }430 - { id: 3, class: _, preferred-register: '', flags: [ ] }431liveins:432 - { reg: '$w0', virtual-reg: '' }433frameInfo:434 isFrameAddressTaken: false435 isReturnAddressTaken: false436 hasStackMap: false437 hasPatchPoint: false438 stackSize: 0439 offsetAdjustment: 0440 maxAlignment: 1441 adjustsStack: false442 hasCalls: false443 stackProtector: ''444 functionContext: ''445 maxCallFrameSize: 4294967295446 cvBytesOfCalleeSavedRegisters: 0447 hasOpaqueSPAdjustment: false448 hasVAStart: false449 hasMustTailInVarArgFunc: false450 hasTailCall: false451 isCalleeSavedInfoValid: false452 localFrameSize: 0453 savePoint: []454 restorePoint: []455fixedStack: []456stack: []457entry_values: []458callSites: []459debugValueSubstitutions: []460constants: []461machineFunctionInfo: {}462body: |463 bb.1.entry:464 liveins: $w0465 466 %0:_(s32) = COPY $w0467 %1:_(s32) = G_CONSTANT i32 1468 %3:_(s32) = G_CONSTANT i32 0469 DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11470 %2:_(s32) = nsw G_ADD %0, %1, debug-location !12471 $w0 = COPY %3(s32)472 RET_ReallyLR implicit $w0473 )";474 auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");475 if (!TM)476 return;477 MachineModuleInfo MMI(TM.get());478 std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);479 ASSERT_TRUE(M);480 481 DroppedVariableStatsMIR Stats;482 auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));483 Stats.runBeforePass("Test", MF);484 485 // This loop simulates an IR pass that drops debug information.486 for (auto &MBB : *MF) {487 for (auto &MI : MBB) {488 if (MI.isDebugValueLike()) {489 MI.eraseFromParent();490 break;491 }492 }493 break;494 }495 496 Stats.runAfterPass("Test", MF);497 ASSERT_EQ(Stats.getPassDroppedVariables(), false);498}499 500// This test ensures that if a #dbg_value is dropped after an optimization pass,501// but an instruction that has a scope which is a child of the #dbg_value scope502// still exists, debug information is conisdered dropped.503TEST(DroppedVariableStatsMIR, ChildScopes) {504 InitializeAllTargetInfos();505 InitializeAllTargets();506 InitializeAllTargetMCs();507 PassInstrumentationCallbacks PIC;508 PassInstrumentation PI(&PIC);509 510 LLVMContext C;511 512 const char *MIR =513 R"(514--- |515 ; ModuleID = '/tmp/test.ll'516 source_filename = "/tmp/test.ll"517 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"518 519 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {520 entry:521 #dbg_value(i32 %x, !10, !DIExpression(), !11)522 %add = add nsw i32 %x, 1, !dbg !12523 ret i32 0524 }525 526 !llvm.dbg.cu = !{!0}527 !llvm.module.flags = !{!2}528 !llvm.ident = !{!3}529 530 !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: "/")531 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")532 !2 = !{i32 2, !"Debug Info Version", i32 3}533 !3 = !{!"clang"}534 !4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)535 !5 = !DIFile(filename: "/tmp/code.cpp", directory: "")536 !6 = !DISubroutineType(types: !7)537 !7 = !{!8, !8}538 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)539 !9 = !{!10}540 !10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)541 !11 = !DILocation(line: 0, scope: !4)542 !12 = !DILocation(line: 2, column: 11, scope: !13)543 !13 = distinct !DILexicalBlock(scope: !4, file: !5, line: 10, column: 28)544 545...546---547name: _Z3fooi548alignment: 4549exposesReturnsTwice: false550legalized: false551regBankSelected: false552selected: false553failedISel: false554tracksRegLiveness: true555hasWinCFI: false556noPhis: false557isSSA: true558noVRegs: false559hasFakeUses: false560callsEHReturn: false561callsUnwindInit: false562hasEHContTarget: false563hasEHScopes: false564hasEHFunclets: false565isOutlined: false566debugInstrRef: false567failsVerification: false568tracksDebugUserValues: false569registers:570 - { id: 0, class: _, preferred-register: '', flags: [ ] }571 - { id: 1, class: _, preferred-register: '', flags: [ ] }572 - { id: 2, class: _, preferred-register: '', flags: [ ] }573 - { id: 3, class: _, preferred-register: '', flags: [ ] }574liveins:575 - { reg: '$w0', virtual-reg: '' }576frameInfo:577 isFrameAddressTaken: false578 isReturnAddressTaken: false579 hasStackMap: false580 hasPatchPoint: false581 stackSize: 0582 offsetAdjustment: 0583 maxAlignment: 1584 adjustsStack: false585 hasCalls: false586 stackProtector: ''587 functionContext: ''588 maxCallFrameSize: 4294967295589 cvBytesOfCalleeSavedRegisters: 0590 hasOpaqueSPAdjustment: false591 hasVAStart: false592 hasMustTailInVarArgFunc: false593 hasTailCall: false594 isCalleeSavedInfoValid: false595 localFrameSize: 0596 savePoint: []597 restorePoint: []598fixedStack: []599stack: []600entry_values: []601callSites: []602debugValueSubstitutions: []603constants: []604machineFunctionInfo: {}605body: |606 bb.1.entry:607 liveins: $w0608 609 %0:_(s32) = COPY $w0610 %1:_(s32) = G_CONSTANT i32 1611 %3:_(s32) = G_CONSTANT i32 0612 DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11613 %2:_(s32) = nsw G_ADD %0, %1, debug-location !12614 $w0 = COPY %3(s32)615 RET_ReallyLR implicit $w0616 )";617 auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");618 if (!TM)619 return;620 MachineModuleInfo MMI(TM.get());621 std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);622 ASSERT_TRUE(M);623 624 DroppedVariableStatsMIR Stats;625 auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));626 Stats.runBeforePass("Test", MF);627 628 // This loop simulates an IR pass that drops debug information.629 for (auto &MBB : *MF) {630 for (auto &MI : MBB) {631 if (MI.isDebugValueLike()) {632 MI.eraseFromParent();633 break;634 }635 }636 break;637 }638 639 Stats.runAfterPass("Test", MF);640 ASSERT_EQ(Stats.getPassDroppedVariables(), true);641}642 643// This test ensures that if a DBG_VALUE is dropped after an optimization pass,644// but an instruction that has a scope which is a child of the DBG_VALUE scope645// still exists, and the DBG_VALUE is inlined at another location, debug646// information is conisdered not dropped.647TEST(DroppedVariableStatsMIR, InlinedAt) {648 InitializeAllTargetInfos();649 InitializeAllTargets();650 InitializeAllTargetMCs();651 PassInstrumentationCallbacks PIC;652 PassInstrumentation PI(&PIC);653 654 LLVMContext C;655 656 const char *MIR =657 R"(658--- |659 ; ModuleID = '/tmp/test.ll'660 source_filename = "/tmp/test.ll"661 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"662 663 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {664 entry:665 #dbg_value(i32 %x, !10, !DIExpression(), !11)666 %add = add nsw i32 %x, 1, !dbg !12667 ret i32 0668 }669 670 !llvm.dbg.cu = !{!0}671 !llvm.module.flags = !{!2}672 !llvm.ident = !{!3}673 674 !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: "/")675 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")676 !2 = !{i32 2, !"Debug Info Version", i32 3}677 !3 = !{!"clang"}678 !4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)679 !5 = !DIFile(filename: "/tmp/code.cpp", directory: "")680 !6 = !DISubroutineType(types: !7)681 !7 = !{!8, !8}682 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)683 !9 = !{!10}684 !10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)685 !11 = !DILocation(line: 0, scope: !4, inlinedAt: !14)686 !12 = !DILocation(line: 2, column: 11, scope: !13)687 !13 = distinct !DILexicalBlock(scope: !4, file: !5, line: 10, column: 28)688 !14 = !DILocation(line: 3, column: 2, scope: !4)689 690...691---692name: _Z3fooi693alignment: 4694exposesReturnsTwice: false695legalized: false696regBankSelected: false697selected: false698failedISel: false699tracksRegLiveness: true700hasWinCFI: false701noPhis: false702isSSA: true703noVRegs: false704hasFakeUses: false705callsEHReturn: false706callsUnwindInit: false707hasEHContTarget: false708hasEHScopes: false709hasEHFunclets: false710isOutlined: false711debugInstrRef: false712failsVerification: false713tracksDebugUserValues: false714registers:715 - { id: 0, class: _, preferred-register: '', flags: [ ] }716 - { id: 1, class: _, preferred-register: '', flags: [ ] }717 - { id: 2, class: _, preferred-register: '', flags: [ ] }718 - { id: 3, class: _, preferred-register: '', flags: [ ] }719liveins:720 - { reg: '$w0', virtual-reg: '' }721frameInfo:722 isFrameAddressTaken: false723 isReturnAddressTaken: false724 hasStackMap: false725 hasPatchPoint: false726 stackSize: 0727 offsetAdjustment: 0728 maxAlignment: 1729 adjustsStack: false730 hasCalls: false731 stackProtector: ''732 functionContext: ''733 maxCallFrameSize: 4294967295734 cvBytesOfCalleeSavedRegisters: 0735 hasOpaqueSPAdjustment: false736 hasVAStart: false737 hasMustTailInVarArgFunc: false738 hasTailCall: false739 isCalleeSavedInfoValid: false740 localFrameSize: 0741 savePoint: []742 restorePoint: []743fixedStack: []744stack: []745entry_values: []746callSites: []747debugValueSubstitutions: []748constants: []749machineFunctionInfo: {}750body: |751 bb.1.entry:752 liveins: $w0753 754 %0:_(s32) = COPY $w0755 %1:_(s32) = G_CONSTANT i32 1756 %3:_(s32) = G_CONSTANT i32 0757 DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11758 %2:_(s32) = nsw G_ADD %0, %1, debug-location !12759 $w0 = COPY %3(s32)760 RET_ReallyLR implicit $w0761 )";762 auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");763 if (!TM)764 return;765 MachineModuleInfo MMI(TM.get());766 std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);767 ASSERT_TRUE(M);768 769 DroppedVariableStatsMIR Stats;770 auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));771 Stats.runBeforePass("Test", MF);772 773 // This loop simulates an IR pass that drops debug information.774 for (auto &MBB : *MF) {775 for (auto &MI : MBB) {776 if (MI.isDebugValueLike()) {777 MI.eraseFromParent();778 break;779 }780 }781 break;782 }783 784 Stats.runAfterPass("Test", MF);785 ASSERT_EQ(Stats.getPassDroppedVariables(), false);786}787 788// This test ensures that if a DBG_VALUE is dropped after an optimization pass,789// but an instruction that has a scope which is a child of the DBG_VALUE scope790// still exists, and the DBG_VALUE and the instruction are inlined at another791// location, debug information is conisdered dropped.792TEST(DroppedVariableStatsMIR, InlinedAtShared) {793 InitializeAllTargetInfos();794 InitializeAllTargets();795 InitializeAllTargetMCs();796 PassInstrumentationCallbacks PIC;797 PassInstrumentation PI(&PIC);798 799 LLVMContext C;800 801 const char *MIR =802 R"(803--- |804 ; ModuleID = '/tmp/test.ll'805 source_filename = "/tmp/test.ll"806 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"807 808 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {809 entry:810 #dbg_value(i32 %x, !10, !DIExpression(), !11)811 %add = add nsw i32 %x, 1, !dbg !12812 ret i32 0813 }814 815 !llvm.dbg.cu = !{!0}816 !llvm.module.flags = !{!2}817 !llvm.ident = !{!3}818 819 !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: "/")820 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")821 !2 = !{i32 2, !"Debug Info Version", i32 3}822 !3 = !{!"clang"}823 !4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)824 !5 = !DIFile(filename: "/tmp/code.cpp", directory: "")825 !6 = !DISubroutineType(types: !7)826 !7 = !{!8, !8}827 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)828 !9 = !{!10}829 !10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)830 !11 = !DILocation(line: 0, scope: !4, inlinedAt: !14)831 !12 = !DILocation(line: 2, column: 11, scope: !13, inlinedAt: !14)832 !13 = distinct !DILexicalBlock(scope: !4, file: !5, line: 10, column: 28)833 !14 = !DILocation(line: 3, column: 2, scope: !4)834 835...836---837name: _Z3fooi838alignment: 4839exposesReturnsTwice: false840legalized: false841regBankSelected: false842selected: false843failedISel: false844tracksRegLiveness: true845hasWinCFI: false846noPhis: false847isSSA: true848noVRegs: false849hasFakeUses: false850callsEHReturn: false851callsUnwindInit: false852hasEHContTarget: false853hasEHScopes: false854hasEHFunclets: false855isOutlined: false856debugInstrRef: false857failsVerification: false858tracksDebugUserValues: false859registers:860 - { id: 0, class: _, preferred-register: '', flags: [ ] }861 - { id: 1, class: _, preferred-register: '', flags: [ ] }862 - { id: 2, class: _, preferred-register: '', flags: [ ] }863 - { id: 3, class: _, preferred-register: '', flags: [ ] }864liveins:865 - { reg: '$w0', virtual-reg: '' }866frameInfo:867 isFrameAddressTaken: false868 isReturnAddressTaken: false869 hasStackMap: false870 hasPatchPoint: false871 stackSize: 0872 offsetAdjustment: 0873 maxAlignment: 1874 adjustsStack: false875 hasCalls: false876 stackProtector: ''877 functionContext: ''878 maxCallFrameSize: 4294967295879 cvBytesOfCalleeSavedRegisters: 0880 hasOpaqueSPAdjustment: false881 hasVAStart: false882 hasMustTailInVarArgFunc: false883 hasTailCall: false884 isCalleeSavedInfoValid: false885 localFrameSize: 0886 savePoint: []887 restorePoint: []888fixedStack: []889stack: []890entry_values: []891callSites: []892debugValueSubstitutions: []893constants: []894machineFunctionInfo: {}895body: |896 bb.1.entry:897 liveins: $w0898 899 %0:_(s32) = COPY $w0900 %1:_(s32) = G_CONSTANT i32 1901 %3:_(s32) = G_CONSTANT i32 0902 DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11903 %2:_(s32) = nsw G_ADD %0, %1, debug-location !12904 $w0 = COPY %3(s32)905 RET_ReallyLR implicit $w0906 )";907 auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");908 if (!TM)909 return;910 MachineModuleInfo MMI(TM.get());911 std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);912 ASSERT_TRUE(M);913 914 DroppedVariableStatsMIR Stats;915 auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));916 Stats.runBeforePass("Test", MF);917 918 // This loop simulates an IR pass that drops debug information.919 for (auto &MBB : *MF) {920 for (auto &MI : MBB) {921 if (MI.isDebugValueLike()) {922 MI.eraseFromParent();923 break;924 }925 }926 break;927 }928 929 Stats.runAfterPass("Test", MF);930 ASSERT_EQ(Stats.getPassDroppedVariables(), true);931}932 933// This test ensures that if a DBG_VALUE is dropped after an optimization pass,934// but an instruction that has a scope which is a child of the DBG_VALUE scope935// still exists, and the instruction is inlined at a location that is the936// DBG_VALUE's inlined at location, debug information is conisdered dropped.937TEST(DroppedVariableStatsMIR, InlinedAtChild) {938 InitializeAllTargetInfos();939 InitializeAllTargets();940 InitializeAllTargetMCs();941 PassInstrumentationCallbacks PIC;942 PassInstrumentation PI(&PIC);943 944 LLVMContext C;945 946 const char *MIR =947 R"(948--- |949 ; ModuleID = '/tmp/test.ll'950 source_filename = "/tmp/test.ll"951 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"952 953 define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {954 entry:955 #dbg_value(i32 %x, !10, !DIExpression(), !11)956 %add = add nsw i32 %x, 1, !dbg !12957 ret i32 0958 }959 960 !llvm.dbg.cu = !{!0}961 !llvm.module.flags = !{!2}962 !llvm.ident = !{!3}963 964 !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: "/")965 !1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")966 !2 = !{i32 2, !"Debug Info Version", i32 3}967 !3 = !{!"clang"}968 !4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)969 !5 = !DIFile(filename: "/tmp/code.cpp", directory: "")970 !6 = !DISubroutineType(types: !7)971 !7 = !{!8, !8}972 !8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)973 !9 = !{!10}974 !10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)975 !11 = !DILocation(line: 0, scope: !4, inlinedAt: !14)976 !12 = !DILocation(line: 2, column: 11, scope: !13, inlinedAt: !15)977 !13 = distinct !DILexicalBlock(scope: !4, file: !5, line: 10, column: 28)978 !14 = !DILocation(line: 3, column: 2, scope: !4)979 !15 = !DILocation(line: 4, column: 5, scope: !13, inlinedAt: !14)980 981...982---983name: _Z3fooi984alignment: 4985exposesReturnsTwice: false986legalized: false987regBankSelected: false988selected: false989failedISel: false990tracksRegLiveness: true991hasWinCFI: false992noPhis: false993isSSA: true994noVRegs: false995hasFakeUses: false996callsEHReturn: false997callsUnwindInit: false998hasEHContTarget: false999hasEHScopes: false1000hasEHFunclets: false1001isOutlined: false1002debugInstrRef: false1003failsVerification: false1004tracksDebugUserValues: false1005registers:1006 - { id: 0, class: _, preferred-register: '', flags: [ ] }1007 - { id: 1, class: _, preferred-register: '', flags: [ ] }1008 - { id: 2, class: _, preferred-register: '', flags: [ ] }1009 - { id: 3, class: _, preferred-register: '', flags: [ ] }1010liveins:1011 - { reg: '$w0', virtual-reg: '' }1012frameInfo:1013 isFrameAddressTaken: false1014 isReturnAddressTaken: false1015 hasStackMap: false1016 hasPatchPoint: false1017 stackSize: 01018 offsetAdjustment: 01019 maxAlignment: 11020 adjustsStack: false1021 hasCalls: false1022 stackProtector: ''1023 functionContext: ''1024 maxCallFrameSize: 42949672951025 cvBytesOfCalleeSavedRegisters: 01026 hasOpaqueSPAdjustment: false1027 hasVAStart: false1028 hasMustTailInVarArgFunc: false1029 hasTailCall: false1030 isCalleeSavedInfoValid: false1031 localFrameSize: 01032 savePoint: []1033 restorePoint: []1034fixedStack: []1035stack: []1036entry_values: []1037callSites: []1038debugValueSubstitutions: []1039constants: []1040machineFunctionInfo: {}1041body: |1042 bb.1.entry:1043 liveins: $w01044 1045 %0:_(s32) = COPY $w01046 %1:_(s32) = G_CONSTANT i32 11047 %3:_(s32) = G_CONSTANT i32 01048 DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !111049 %2:_(s32) = nsw G_ADD %0, %1, debug-location !121050 $w0 = COPY %3(s32)1051 RET_ReallyLR implicit $w01052 )";1053 auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");1054 if (!TM)1055 return;1056 MachineModuleInfo MMI(TM.get());1057 std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);1058 ASSERT_TRUE(M);1059 1060 DroppedVariableStatsMIR Stats;1061 auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));1062 Stats.runBeforePass("Test", MF);1063 1064 // This loop simulates an IR pass that drops debug information.1065 for (auto &MBB : *MF) {1066 for (auto &MI : MBB) {1067 if (MI.isDebugValueLike()) {1068 MI.eraseFromParent();1069 break;1070 }1071 }1072 break;1073 }1074 1075 Stats.runAfterPass("Test", MF);1076 ASSERT_EQ(Stats.getPassDroppedVariables(), true);1077}1078 1079} // end anonymous namespace1080