
In review of bbde6b, I had originally proposed that we support the legacy text format. As review evolved, it bacame clear this had been a bad idea (too much complexity), but in order to let that patch finally move forward, I approved the change with the variant. This change undoes the variant, and updates all the tests to just use the array form.
1080 lines
33 KiB
C++
1080 lines
33 KiB
C++
//===- unittests/CodeGen/DroppedVariableStatsMIRTest.cpp ------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/DroppedVariableStatsMIR.h"
|
|
#include "llvm/AsmParser/Parser.h"
|
|
#include "llvm/CodeGen/MIRParser/MIRParser.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/LegacyPassManager.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/MC/TargetRegistry.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include "llvm/Support/TargetSelect.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "gtest/gtest.h"
|
|
#include <llvm/ADT/SmallString.h>
|
|
#include <llvm/IR/LLVMContext.h>
|
|
#include <llvm/IR/PassInstrumentation.h>
|
|
#include <llvm/IR/PassManager.h>
|
|
#include <llvm/IR/PassTimingInfo.h>
|
|
#include <llvm/Support/raw_ostream.h>
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
std::unique_ptr<TargetMachine>
|
|
createTargetMachine(std::string TargetStr, StringRef CPU, StringRef FS) {
|
|
std::string Error;
|
|
Triple TT(TargetStr);
|
|
const Target *T = TargetRegistry::lookupTarget(TT, Error);
|
|
if (!T)
|
|
return nullptr;
|
|
TargetOptions Options;
|
|
return std::unique_ptr<TargetMachine>(
|
|
T->createTargetMachine(TT, CPU, FS, Options, std::nullopt, std::nullopt));
|
|
}
|
|
|
|
std::unique_ptr<Module> parseMIR(const TargetMachine &TM, StringRef MIRCode,
|
|
MachineModuleInfo &MMI, LLVMContext *Context) {
|
|
SMDiagnostic Diagnostic;
|
|
std::unique_ptr<Module> M;
|
|
std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
|
|
auto MIR = createMIRParser(std::move(MBuffer), *Context);
|
|
if (!MIR)
|
|
return nullptr;
|
|
|
|
std::unique_ptr<Module> Mod = MIR->parseIRModule();
|
|
if (!Mod)
|
|
return nullptr;
|
|
|
|
Mod->setDataLayout(TM.createDataLayout());
|
|
|
|
if (MIR->parseMachineFunctions(*Mod, MMI)) {
|
|
M.reset();
|
|
return nullptr;
|
|
}
|
|
return Mod;
|
|
}
|
|
// This test ensures that if a DBG_VALUE and an instruction that exists in the
|
|
// same scope as that DBG_VALUE are both deleted as a result of an optimization
|
|
// pass, debug information is considered not dropped.
|
|
TEST(DroppedVariableStatsMIR, BothDeleted) {
|
|
InitializeAllTargetInfos();
|
|
InitializeAllTargets();
|
|
InitializeAllTargetMCs();
|
|
PassInstrumentationCallbacks PIC;
|
|
PassInstrumentation PI(&PIC);
|
|
|
|
LLVMContext C;
|
|
|
|
const char *MIR =
|
|
R"(
|
|
--- |
|
|
; ModuleID = '/tmp/test.ll'
|
|
source_filename = "/tmp/test.ll"
|
|
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
|
|
|
|
define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {
|
|
entry:
|
|
#dbg_value(i32 %x, !10, !DIExpression(), !11)
|
|
%add = add nsw i32 %x, 1, !dbg !12
|
|
ret i32 0
|
|
}
|
|
|
|
!llvm.dbg.cu = !{!0}
|
|
!llvm.module.flags = !{!2}
|
|
!llvm.ident = !{!3}
|
|
|
|
!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: "/")
|
|
!1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
|
|
!2 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!3 = !{!"clang"}
|
|
!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
|
|
!5 = !DIFile(filename: "/tmp/code.cpp", directory: "")
|
|
!6 = !DISubroutineType(types: !7)
|
|
!7 = !{!8, !8}
|
|
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!9 = !{!10}
|
|
!10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)
|
|
!11 = !DILocation(line: 0, scope: !4)
|
|
!12 = !DILocation(line: 2, column: 11, scope: !4)
|
|
|
|
...
|
|
---
|
|
name: _Z3fooi
|
|
alignment: 4
|
|
exposesReturnsTwice: false
|
|
legalized: false
|
|
regBankSelected: false
|
|
selected: false
|
|
failedISel: false
|
|
tracksRegLiveness: true
|
|
hasWinCFI: false
|
|
noPhis: false
|
|
isSSA: true
|
|
noVRegs: false
|
|
hasFakeUses: false
|
|
callsEHReturn: false
|
|
callsUnwindInit: false
|
|
hasEHContTarget: false
|
|
hasEHScopes: false
|
|
hasEHFunclets: false
|
|
isOutlined: false
|
|
debugInstrRef: false
|
|
failsVerification: false
|
|
tracksDebugUserValues: false
|
|
registers:
|
|
- { id: 0, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 1, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 2, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 3, class: _, preferred-register: '', flags: [ ] }
|
|
liveins:
|
|
- { reg: '$w0', virtual-reg: '' }
|
|
frameInfo:
|
|
isFrameAddressTaken: false
|
|
isReturnAddressTaken: false
|
|
hasStackMap: false
|
|
hasPatchPoint: false
|
|
stackSize: 0
|
|
offsetAdjustment: 0
|
|
maxAlignment: 1
|
|
adjustsStack: false
|
|
hasCalls: false
|
|
stackProtector: ''
|
|
functionContext: ''
|
|
maxCallFrameSize: 4294967295
|
|
cvBytesOfCalleeSavedRegisters: 0
|
|
hasOpaqueSPAdjustment: false
|
|
hasVAStart: false
|
|
hasMustTailInVarArgFunc: false
|
|
hasTailCall: false
|
|
isCalleeSavedInfoValid: false
|
|
localFrameSize: 0
|
|
savePoint: []
|
|
restorePoint: []
|
|
fixedStack: []
|
|
stack: []
|
|
entry_values: []
|
|
callSites: []
|
|
debugValueSubstitutions: []
|
|
constants: []
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.1.entry:
|
|
liveins: $w0
|
|
|
|
%0:_(s32) = COPY $w0
|
|
%1:_(s32) = G_CONSTANT i32 1
|
|
%3:_(s32) = G_CONSTANT i32 0
|
|
DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11
|
|
%2:_(s32) = nsw G_ADD %0, %1, debug-location !12
|
|
$w0 = COPY %3(s32)
|
|
RET_ReallyLR implicit $w0
|
|
)";
|
|
auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");
|
|
if (!TM)
|
|
return;
|
|
MachineModuleInfo MMI(TM.get());
|
|
std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);
|
|
ASSERT_TRUE(M);
|
|
|
|
DroppedVariableStatsMIR Stats;
|
|
auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));
|
|
Stats.runBeforePass("Test", MF);
|
|
|
|
// This loop simulates an IR pass that drops debug information.
|
|
for (auto &MBB : *MF) {
|
|
for (auto &MI : MBB) {
|
|
if (MI.isDebugValueLike()) {
|
|
MI.eraseFromParent();
|
|
break;
|
|
}
|
|
}
|
|
for (auto &MI : MBB) {
|
|
auto *DbgLoc = MI.getDebugLoc().get();
|
|
if (DbgLoc) {
|
|
MI.eraseFromParent();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
Stats.runAfterPass("Test", MF);
|
|
ASSERT_EQ(Stats.getPassDroppedVariables(), false);
|
|
}
|
|
|
|
// This test ensures that if a DBG_VALUE is dropped after an optimization pass,
|
|
// but an instruction that shares the same scope as the DBG_VALUE still exists,
|
|
// debug information is conisdered dropped.
|
|
TEST(DroppedVariableStatsMIR, DbgValLost) {
|
|
InitializeAllTargetInfos();
|
|
InitializeAllTargets();
|
|
InitializeAllTargetMCs();
|
|
PassInstrumentationCallbacks PIC;
|
|
PassInstrumentation PI(&PIC);
|
|
|
|
LLVMContext C;
|
|
|
|
const char *MIR =
|
|
R"(
|
|
--- |
|
|
; ModuleID = '/tmp/test.ll'
|
|
source_filename = "/tmp/test.ll"
|
|
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
|
|
|
|
define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {
|
|
entry:
|
|
#dbg_value(i32 %x, !10, !DIExpression(), !11)
|
|
%add = add nsw i32 %x, 1, !dbg !12
|
|
ret i32 0
|
|
}
|
|
|
|
!llvm.dbg.cu = !{!0}
|
|
!llvm.module.flags = !{!2}
|
|
!llvm.ident = !{!3}
|
|
|
|
!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: "/")
|
|
!1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
|
|
!2 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!3 = !{!"clang"}
|
|
!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
|
|
!5 = !DIFile(filename: "/tmp/code.cpp", directory: "")
|
|
!6 = !DISubroutineType(types: !7)
|
|
!7 = !{!8, !8}
|
|
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!9 = !{!10}
|
|
!10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)
|
|
!11 = !DILocation(line: 0, scope: !4)
|
|
!12 = !DILocation(line: 2, column: 11, scope: !4)
|
|
|
|
...
|
|
---
|
|
name: _Z3fooi
|
|
alignment: 4
|
|
exposesReturnsTwice: false
|
|
legalized: false
|
|
regBankSelected: false
|
|
selected: false
|
|
failedISel: false
|
|
tracksRegLiveness: true
|
|
hasWinCFI: false
|
|
noPhis: false
|
|
isSSA: true
|
|
noVRegs: false
|
|
hasFakeUses: false
|
|
callsEHReturn: false
|
|
callsUnwindInit: false
|
|
hasEHContTarget: false
|
|
hasEHScopes: false
|
|
hasEHFunclets: false
|
|
isOutlined: false
|
|
debugInstrRef: false
|
|
failsVerification: false
|
|
tracksDebugUserValues: false
|
|
registers:
|
|
- { id: 0, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 1, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 2, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 3, class: _, preferred-register: '', flags: [ ] }
|
|
liveins:
|
|
- { reg: '$w0', virtual-reg: '' }
|
|
frameInfo:
|
|
isFrameAddressTaken: false
|
|
isReturnAddressTaken: false
|
|
hasStackMap: false
|
|
hasPatchPoint: false
|
|
stackSize: 0
|
|
offsetAdjustment: 0
|
|
maxAlignment: 1
|
|
adjustsStack: false
|
|
hasCalls: false
|
|
stackProtector: ''
|
|
functionContext: ''
|
|
maxCallFrameSize: 4294967295
|
|
cvBytesOfCalleeSavedRegisters: 0
|
|
hasOpaqueSPAdjustment: false
|
|
hasVAStart: false
|
|
hasMustTailInVarArgFunc: false
|
|
hasTailCall: false
|
|
isCalleeSavedInfoValid: false
|
|
localFrameSize: 0
|
|
savePoint: []
|
|
restorePoint: []
|
|
fixedStack: []
|
|
stack: []
|
|
entry_values: []
|
|
callSites: []
|
|
debugValueSubstitutions: []
|
|
constants: []
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.1.entry:
|
|
liveins: $w0
|
|
|
|
%0:_(s32) = COPY $w0
|
|
%1:_(s32) = G_CONSTANT i32 1
|
|
%3:_(s32) = G_CONSTANT i32 0
|
|
DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11
|
|
%2:_(s32) = nsw G_ADD %0, %1, debug-location !12
|
|
$w0 = COPY %3(s32)
|
|
RET_ReallyLR implicit $w0
|
|
)";
|
|
auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");
|
|
if (!TM)
|
|
return;
|
|
MachineModuleInfo MMI(TM.get());
|
|
std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);
|
|
ASSERT_TRUE(M);
|
|
|
|
DroppedVariableStatsMIR Stats;
|
|
auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));
|
|
Stats.runBeforePass("Test", MF);
|
|
|
|
// This loop simulates an IR pass that drops debug information.
|
|
for (auto &MBB : *MF) {
|
|
for (auto &MI : MBB) {
|
|
if (MI.isDebugValueLike()) {
|
|
MI.eraseFromParent();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
Stats.runAfterPass("Test", MF);
|
|
ASSERT_EQ(Stats.getPassDroppedVariables(), true);
|
|
}
|
|
|
|
// This test ensures that if a #dbg_value is dropped after an optimization pass,
|
|
// but an instruction that has an unrelated scope as the #dbg_value still
|
|
// exists, debug information is conisdered not dropped.
|
|
TEST(DroppedVariableStatsMIR, UnrelatedScopes) {
|
|
InitializeAllTargetInfos();
|
|
InitializeAllTargets();
|
|
InitializeAllTargetMCs();
|
|
PassInstrumentationCallbacks PIC;
|
|
PassInstrumentation PI(&PIC);
|
|
|
|
LLVMContext C;
|
|
|
|
const char *MIR =
|
|
R"(
|
|
--- |
|
|
; ModuleID = '/tmp/test.ll'
|
|
source_filename = "/tmp/test.ll"
|
|
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
|
|
|
|
define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {
|
|
entry:
|
|
#dbg_value(i32 %x, !10, !DIExpression(), !11)
|
|
%add = add nsw i32 %x, 1, !dbg !12
|
|
ret i32 0
|
|
}
|
|
|
|
!llvm.dbg.cu = !{!0}
|
|
!llvm.module.flags = !{!2}
|
|
!llvm.ident = !{!3}
|
|
|
|
!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: "/")
|
|
!1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
|
|
!2 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!3 = !{!"clang"}
|
|
!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
|
|
!5 = !DIFile(filename: "/tmp/code.cpp", directory: "")
|
|
!6 = !DISubroutineType(types: !7)
|
|
!7 = !{!8, !8}
|
|
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!9 = !{!10}
|
|
!10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)
|
|
!11 = !DILocation(line: 0, scope: !4)
|
|
!12 = !DILocation(line: 2, column: 11, scope: !13)
|
|
!13 = distinct !DISubprogram(name: "bar", linkageName: "_Z3bari", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
|
|
|
|
...
|
|
---
|
|
name: _Z3fooi
|
|
alignment: 4
|
|
exposesReturnsTwice: false
|
|
legalized: false
|
|
regBankSelected: false
|
|
selected: false
|
|
failedISel: false
|
|
tracksRegLiveness: true
|
|
hasWinCFI: false
|
|
noPhis: false
|
|
isSSA: true
|
|
noVRegs: false
|
|
hasFakeUses: false
|
|
callsEHReturn: false
|
|
callsUnwindInit: false
|
|
hasEHContTarget: false
|
|
hasEHScopes: false
|
|
hasEHFunclets: false
|
|
isOutlined: false
|
|
debugInstrRef: false
|
|
failsVerification: false
|
|
tracksDebugUserValues: false
|
|
registers:
|
|
- { id: 0, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 1, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 2, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 3, class: _, preferred-register: '', flags: [ ] }
|
|
liveins:
|
|
- { reg: '$w0', virtual-reg: '' }
|
|
frameInfo:
|
|
isFrameAddressTaken: false
|
|
isReturnAddressTaken: false
|
|
hasStackMap: false
|
|
hasPatchPoint: false
|
|
stackSize: 0
|
|
offsetAdjustment: 0
|
|
maxAlignment: 1
|
|
adjustsStack: false
|
|
hasCalls: false
|
|
stackProtector: ''
|
|
functionContext: ''
|
|
maxCallFrameSize: 4294967295
|
|
cvBytesOfCalleeSavedRegisters: 0
|
|
hasOpaqueSPAdjustment: false
|
|
hasVAStart: false
|
|
hasMustTailInVarArgFunc: false
|
|
hasTailCall: false
|
|
isCalleeSavedInfoValid: false
|
|
localFrameSize: 0
|
|
savePoint: []
|
|
restorePoint: []
|
|
fixedStack: []
|
|
stack: []
|
|
entry_values: []
|
|
callSites: []
|
|
debugValueSubstitutions: []
|
|
constants: []
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.1.entry:
|
|
liveins: $w0
|
|
|
|
%0:_(s32) = COPY $w0
|
|
%1:_(s32) = G_CONSTANT i32 1
|
|
%3:_(s32) = G_CONSTANT i32 0
|
|
DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11
|
|
%2:_(s32) = nsw G_ADD %0, %1, debug-location !12
|
|
$w0 = COPY %3(s32)
|
|
RET_ReallyLR implicit $w0
|
|
)";
|
|
auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");
|
|
if (!TM)
|
|
return;
|
|
MachineModuleInfo MMI(TM.get());
|
|
std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);
|
|
ASSERT_TRUE(M);
|
|
|
|
DroppedVariableStatsMIR Stats;
|
|
auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));
|
|
Stats.runBeforePass("Test", MF);
|
|
|
|
// This loop simulates an IR pass that drops debug information.
|
|
for (auto &MBB : *MF) {
|
|
for (auto &MI : MBB) {
|
|
if (MI.isDebugValueLike()) {
|
|
MI.eraseFromParent();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
Stats.runAfterPass("Test", MF);
|
|
ASSERT_EQ(Stats.getPassDroppedVariables(), false);
|
|
}
|
|
|
|
// This test ensures that if a #dbg_value is dropped after an optimization pass,
|
|
// but an instruction that has a scope which is a child of the #dbg_value scope
|
|
// still exists, debug information is conisdered dropped.
|
|
TEST(DroppedVariableStatsMIR, ChildScopes) {
|
|
InitializeAllTargetInfos();
|
|
InitializeAllTargets();
|
|
InitializeAllTargetMCs();
|
|
PassInstrumentationCallbacks PIC;
|
|
PassInstrumentation PI(&PIC);
|
|
|
|
LLVMContext C;
|
|
|
|
const char *MIR =
|
|
R"(
|
|
--- |
|
|
; ModuleID = '/tmp/test.ll'
|
|
source_filename = "/tmp/test.ll"
|
|
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
|
|
|
|
define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {
|
|
entry:
|
|
#dbg_value(i32 %x, !10, !DIExpression(), !11)
|
|
%add = add nsw i32 %x, 1, !dbg !12
|
|
ret i32 0
|
|
}
|
|
|
|
!llvm.dbg.cu = !{!0}
|
|
!llvm.module.flags = !{!2}
|
|
!llvm.ident = !{!3}
|
|
|
|
!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: "/")
|
|
!1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
|
|
!2 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!3 = !{!"clang"}
|
|
!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
|
|
!5 = !DIFile(filename: "/tmp/code.cpp", directory: "")
|
|
!6 = !DISubroutineType(types: !7)
|
|
!7 = !{!8, !8}
|
|
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!9 = !{!10}
|
|
!10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)
|
|
!11 = !DILocation(line: 0, scope: !4)
|
|
!12 = !DILocation(line: 2, column: 11, scope: !13)
|
|
!13 = distinct !DILexicalBlock(scope: !4, file: !5, line: 10, column: 28)
|
|
|
|
...
|
|
---
|
|
name: _Z3fooi
|
|
alignment: 4
|
|
exposesReturnsTwice: false
|
|
legalized: false
|
|
regBankSelected: false
|
|
selected: false
|
|
failedISel: false
|
|
tracksRegLiveness: true
|
|
hasWinCFI: false
|
|
noPhis: false
|
|
isSSA: true
|
|
noVRegs: false
|
|
hasFakeUses: false
|
|
callsEHReturn: false
|
|
callsUnwindInit: false
|
|
hasEHContTarget: false
|
|
hasEHScopes: false
|
|
hasEHFunclets: false
|
|
isOutlined: false
|
|
debugInstrRef: false
|
|
failsVerification: false
|
|
tracksDebugUserValues: false
|
|
registers:
|
|
- { id: 0, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 1, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 2, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 3, class: _, preferred-register: '', flags: [ ] }
|
|
liveins:
|
|
- { reg: '$w0', virtual-reg: '' }
|
|
frameInfo:
|
|
isFrameAddressTaken: false
|
|
isReturnAddressTaken: false
|
|
hasStackMap: false
|
|
hasPatchPoint: false
|
|
stackSize: 0
|
|
offsetAdjustment: 0
|
|
maxAlignment: 1
|
|
adjustsStack: false
|
|
hasCalls: false
|
|
stackProtector: ''
|
|
functionContext: ''
|
|
maxCallFrameSize: 4294967295
|
|
cvBytesOfCalleeSavedRegisters: 0
|
|
hasOpaqueSPAdjustment: false
|
|
hasVAStart: false
|
|
hasMustTailInVarArgFunc: false
|
|
hasTailCall: false
|
|
isCalleeSavedInfoValid: false
|
|
localFrameSize: 0
|
|
savePoint: []
|
|
restorePoint: []
|
|
fixedStack: []
|
|
stack: []
|
|
entry_values: []
|
|
callSites: []
|
|
debugValueSubstitutions: []
|
|
constants: []
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.1.entry:
|
|
liveins: $w0
|
|
|
|
%0:_(s32) = COPY $w0
|
|
%1:_(s32) = G_CONSTANT i32 1
|
|
%3:_(s32) = G_CONSTANT i32 0
|
|
DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11
|
|
%2:_(s32) = nsw G_ADD %0, %1, debug-location !12
|
|
$w0 = COPY %3(s32)
|
|
RET_ReallyLR implicit $w0
|
|
)";
|
|
auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");
|
|
if (!TM)
|
|
return;
|
|
MachineModuleInfo MMI(TM.get());
|
|
std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);
|
|
ASSERT_TRUE(M);
|
|
|
|
DroppedVariableStatsMIR Stats;
|
|
auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));
|
|
Stats.runBeforePass("Test", MF);
|
|
|
|
// This loop simulates an IR pass that drops debug information.
|
|
for (auto &MBB : *MF) {
|
|
for (auto &MI : MBB) {
|
|
if (MI.isDebugValueLike()) {
|
|
MI.eraseFromParent();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
Stats.runAfterPass("Test", MF);
|
|
ASSERT_EQ(Stats.getPassDroppedVariables(), true);
|
|
}
|
|
|
|
// This test ensures that if a DBG_VALUE is dropped after an optimization pass,
|
|
// but an instruction that has a scope which is a child of the DBG_VALUE scope
|
|
// still exists, and the DBG_VALUE is inlined at another location, debug
|
|
// information is conisdered not dropped.
|
|
TEST(DroppedVariableStatsMIR, InlinedAt) {
|
|
InitializeAllTargetInfos();
|
|
InitializeAllTargets();
|
|
InitializeAllTargetMCs();
|
|
PassInstrumentationCallbacks PIC;
|
|
PassInstrumentation PI(&PIC);
|
|
|
|
LLVMContext C;
|
|
|
|
const char *MIR =
|
|
R"(
|
|
--- |
|
|
; ModuleID = '/tmp/test.ll'
|
|
source_filename = "/tmp/test.ll"
|
|
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
|
|
|
|
define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {
|
|
entry:
|
|
#dbg_value(i32 %x, !10, !DIExpression(), !11)
|
|
%add = add nsw i32 %x, 1, !dbg !12
|
|
ret i32 0
|
|
}
|
|
|
|
!llvm.dbg.cu = !{!0}
|
|
!llvm.module.flags = !{!2}
|
|
!llvm.ident = !{!3}
|
|
|
|
!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: "/")
|
|
!1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
|
|
!2 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!3 = !{!"clang"}
|
|
!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
|
|
!5 = !DIFile(filename: "/tmp/code.cpp", directory: "")
|
|
!6 = !DISubroutineType(types: !7)
|
|
!7 = !{!8, !8}
|
|
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!9 = !{!10}
|
|
!10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)
|
|
!11 = !DILocation(line: 0, scope: !4, inlinedAt: !14)
|
|
!12 = !DILocation(line: 2, column: 11, scope: !13)
|
|
!13 = distinct !DILexicalBlock(scope: !4, file: !5, line: 10, column: 28)
|
|
!14 = !DILocation(line: 3, column: 2, scope: !4)
|
|
|
|
...
|
|
---
|
|
name: _Z3fooi
|
|
alignment: 4
|
|
exposesReturnsTwice: false
|
|
legalized: false
|
|
regBankSelected: false
|
|
selected: false
|
|
failedISel: false
|
|
tracksRegLiveness: true
|
|
hasWinCFI: false
|
|
noPhis: false
|
|
isSSA: true
|
|
noVRegs: false
|
|
hasFakeUses: false
|
|
callsEHReturn: false
|
|
callsUnwindInit: false
|
|
hasEHContTarget: false
|
|
hasEHScopes: false
|
|
hasEHFunclets: false
|
|
isOutlined: false
|
|
debugInstrRef: false
|
|
failsVerification: false
|
|
tracksDebugUserValues: false
|
|
registers:
|
|
- { id: 0, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 1, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 2, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 3, class: _, preferred-register: '', flags: [ ] }
|
|
liveins:
|
|
- { reg: '$w0', virtual-reg: '' }
|
|
frameInfo:
|
|
isFrameAddressTaken: false
|
|
isReturnAddressTaken: false
|
|
hasStackMap: false
|
|
hasPatchPoint: false
|
|
stackSize: 0
|
|
offsetAdjustment: 0
|
|
maxAlignment: 1
|
|
adjustsStack: false
|
|
hasCalls: false
|
|
stackProtector: ''
|
|
functionContext: ''
|
|
maxCallFrameSize: 4294967295
|
|
cvBytesOfCalleeSavedRegisters: 0
|
|
hasOpaqueSPAdjustment: false
|
|
hasVAStart: false
|
|
hasMustTailInVarArgFunc: false
|
|
hasTailCall: false
|
|
isCalleeSavedInfoValid: false
|
|
localFrameSize: 0
|
|
savePoint: []
|
|
restorePoint: []
|
|
fixedStack: []
|
|
stack: []
|
|
entry_values: []
|
|
callSites: []
|
|
debugValueSubstitutions: []
|
|
constants: []
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.1.entry:
|
|
liveins: $w0
|
|
|
|
%0:_(s32) = COPY $w0
|
|
%1:_(s32) = G_CONSTANT i32 1
|
|
%3:_(s32) = G_CONSTANT i32 0
|
|
DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11
|
|
%2:_(s32) = nsw G_ADD %0, %1, debug-location !12
|
|
$w0 = COPY %3(s32)
|
|
RET_ReallyLR implicit $w0
|
|
)";
|
|
auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");
|
|
if (!TM)
|
|
return;
|
|
MachineModuleInfo MMI(TM.get());
|
|
std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);
|
|
ASSERT_TRUE(M);
|
|
|
|
DroppedVariableStatsMIR Stats;
|
|
auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));
|
|
Stats.runBeforePass("Test", MF);
|
|
|
|
// This loop simulates an IR pass that drops debug information.
|
|
for (auto &MBB : *MF) {
|
|
for (auto &MI : MBB) {
|
|
if (MI.isDebugValueLike()) {
|
|
MI.eraseFromParent();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
Stats.runAfterPass("Test", MF);
|
|
ASSERT_EQ(Stats.getPassDroppedVariables(), false);
|
|
}
|
|
|
|
// This test ensures that if a DBG_VALUE is dropped after an optimization pass,
|
|
// but an instruction that has a scope which is a child of the DBG_VALUE scope
|
|
// still exists, and the DBG_VALUE and the instruction are inlined at another
|
|
// location, debug information is conisdered dropped.
|
|
TEST(DroppedVariableStatsMIR, InlinedAtShared) {
|
|
InitializeAllTargetInfos();
|
|
InitializeAllTargets();
|
|
InitializeAllTargetMCs();
|
|
PassInstrumentationCallbacks PIC;
|
|
PassInstrumentation PI(&PIC);
|
|
|
|
LLVMContext C;
|
|
|
|
const char *MIR =
|
|
R"(
|
|
--- |
|
|
; ModuleID = '/tmp/test.ll'
|
|
source_filename = "/tmp/test.ll"
|
|
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
|
|
|
|
define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {
|
|
entry:
|
|
#dbg_value(i32 %x, !10, !DIExpression(), !11)
|
|
%add = add nsw i32 %x, 1, !dbg !12
|
|
ret i32 0
|
|
}
|
|
|
|
!llvm.dbg.cu = !{!0}
|
|
!llvm.module.flags = !{!2}
|
|
!llvm.ident = !{!3}
|
|
|
|
!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: "/")
|
|
!1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
|
|
!2 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!3 = !{!"clang"}
|
|
!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
|
|
!5 = !DIFile(filename: "/tmp/code.cpp", directory: "")
|
|
!6 = !DISubroutineType(types: !7)
|
|
!7 = !{!8, !8}
|
|
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!9 = !{!10}
|
|
!10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)
|
|
!11 = !DILocation(line: 0, scope: !4, inlinedAt: !14)
|
|
!12 = !DILocation(line: 2, column: 11, scope: !13, inlinedAt: !14)
|
|
!13 = distinct !DILexicalBlock(scope: !4, file: !5, line: 10, column: 28)
|
|
!14 = !DILocation(line: 3, column: 2, scope: !4)
|
|
|
|
...
|
|
---
|
|
name: _Z3fooi
|
|
alignment: 4
|
|
exposesReturnsTwice: false
|
|
legalized: false
|
|
regBankSelected: false
|
|
selected: false
|
|
failedISel: false
|
|
tracksRegLiveness: true
|
|
hasWinCFI: false
|
|
noPhis: false
|
|
isSSA: true
|
|
noVRegs: false
|
|
hasFakeUses: false
|
|
callsEHReturn: false
|
|
callsUnwindInit: false
|
|
hasEHContTarget: false
|
|
hasEHScopes: false
|
|
hasEHFunclets: false
|
|
isOutlined: false
|
|
debugInstrRef: false
|
|
failsVerification: false
|
|
tracksDebugUserValues: false
|
|
registers:
|
|
- { id: 0, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 1, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 2, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 3, class: _, preferred-register: '', flags: [ ] }
|
|
liveins:
|
|
- { reg: '$w0', virtual-reg: '' }
|
|
frameInfo:
|
|
isFrameAddressTaken: false
|
|
isReturnAddressTaken: false
|
|
hasStackMap: false
|
|
hasPatchPoint: false
|
|
stackSize: 0
|
|
offsetAdjustment: 0
|
|
maxAlignment: 1
|
|
adjustsStack: false
|
|
hasCalls: false
|
|
stackProtector: ''
|
|
functionContext: ''
|
|
maxCallFrameSize: 4294967295
|
|
cvBytesOfCalleeSavedRegisters: 0
|
|
hasOpaqueSPAdjustment: false
|
|
hasVAStart: false
|
|
hasMustTailInVarArgFunc: false
|
|
hasTailCall: false
|
|
isCalleeSavedInfoValid: false
|
|
localFrameSize: 0
|
|
savePoint: []
|
|
restorePoint: []
|
|
fixedStack: []
|
|
stack: []
|
|
entry_values: []
|
|
callSites: []
|
|
debugValueSubstitutions: []
|
|
constants: []
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.1.entry:
|
|
liveins: $w0
|
|
|
|
%0:_(s32) = COPY $w0
|
|
%1:_(s32) = G_CONSTANT i32 1
|
|
%3:_(s32) = G_CONSTANT i32 0
|
|
DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11
|
|
%2:_(s32) = nsw G_ADD %0, %1, debug-location !12
|
|
$w0 = COPY %3(s32)
|
|
RET_ReallyLR implicit $w0
|
|
)";
|
|
auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");
|
|
if (!TM)
|
|
return;
|
|
MachineModuleInfo MMI(TM.get());
|
|
std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);
|
|
ASSERT_TRUE(M);
|
|
|
|
DroppedVariableStatsMIR Stats;
|
|
auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));
|
|
Stats.runBeforePass("Test", MF);
|
|
|
|
// This loop simulates an IR pass that drops debug information.
|
|
for (auto &MBB : *MF) {
|
|
for (auto &MI : MBB) {
|
|
if (MI.isDebugValueLike()) {
|
|
MI.eraseFromParent();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
Stats.runAfterPass("Test", MF);
|
|
ASSERT_EQ(Stats.getPassDroppedVariables(), true);
|
|
}
|
|
|
|
// This test ensures that if a DBG_VALUE is dropped after an optimization pass,
|
|
// but an instruction that has a scope which is a child of the DBG_VALUE scope
|
|
// still exists, and the instruction is inlined at a location that is the
|
|
// DBG_VALUE's inlined at location, debug information is conisdered dropped.
|
|
TEST(DroppedVariableStatsMIR, InlinedAtChild) {
|
|
InitializeAllTargetInfos();
|
|
InitializeAllTargets();
|
|
InitializeAllTargetMCs();
|
|
PassInstrumentationCallbacks PIC;
|
|
PassInstrumentation PI(&PIC);
|
|
|
|
LLVMContext C;
|
|
|
|
const char *MIR =
|
|
R"(
|
|
--- |
|
|
; ModuleID = '/tmp/test.ll'
|
|
source_filename = "/tmp/test.ll"
|
|
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
|
|
|
|
define noundef range(i32 -2147483647, -2147483648) i32 @_Z3fooi(i32 noundef %x) local_unnamed_addr !dbg !4 {
|
|
entry:
|
|
#dbg_value(i32 %x, !10, !DIExpression(), !11)
|
|
%add = add nsw i32 %x, 1, !dbg !12
|
|
ret i32 0
|
|
}
|
|
|
|
!llvm.dbg.cu = !{!0}
|
|
!llvm.module.flags = !{!2}
|
|
!llvm.ident = !{!3}
|
|
|
|
!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: "/")
|
|
!1 = !DIFile(filename: "/tmp/code.cpp", directory: "/")
|
|
!2 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!3 = !{!"clang"}
|
|
!4 = distinct !DISubprogram(name: "foo", linkageName: "_Z3fooi", scope: !5, file: !5, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9)
|
|
!5 = !DIFile(filename: "/tmp/code.cpp", directory: "")
|
|
!6 = !DISubroutineType(types: !7)
|
|
!7 = !{!8, !8}
|
|
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!9 = !{!10}
|
|
!10 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !5, line: 1, type: !8)
|
|
!11 = !DILocation(line: 0, scope: !4, inlinedAt: !14)
|
|
!12 = !DILocation(line: 2, column: 11, scope: !13, inlinedAt: !15)
|
|
!13 = distinct !DILexicalBlock(scope: !4, file: !5, line: 10, column: 28)
|
|
!14 = !DILocation(line: 3, column: 2, scope: !4)
|
|
!15 = !DILocation(line: 4, column: 5, scope: !13, inlinedAt: !14)
|
|
|
|
...
|
|
---
|
|
name: _Z3fooi
|
|
alignment: 4
|
|
exposesReturnsTwice: false
|
|
legalized: false
|
|
regBankSelected: false
|
|
selected: false
|
|
failedISel: false
|
|
tracksRegLiveness: true
|
|
hasWinCFI: false
|
|
noPhis: false
|
|
isSSA: true
|
|
noVRegs: false
|
|
hasFakeUses: false
|
|
callsEHReturn: false
|
|
callsUnwindInit: false
|
|
hasEHContTarget: false
|
|
hasEHScopes: false
|
|
hasEHFunclets: false
|
|
isOutlined: false
|
|
debugInstrRef: false
|
|
failsVerification: false
|
|
tracksDebugUserValues: false
|
|
registers:
|
|
- { id: 0, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 1, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 2, class: _, preferred-register: '', flags: [ ] }
|
|
- { id: 3, class: _, preferred-register: '', flags: [ ] }
|
|
liveins:
|
|
- { reg: '$w0', virtual-reg: '' }
|
|
frameInfo:
|
|
isFrameAddressTaken: false
|
|
isReturnAddressTaken: false
|
|
hasStackMap: false
|
|
hasPatchPoint: false
|
|
stackSize: 0
|
|
offsetAdjustment: 0
|
|
maxAlignment: 1
|
|
adjustsStack: false
|
|
hasCalls: false
|
|
stackProtector: ''
|
|
functionContext: ''
|
|
maxCallFrameSize: 4294967295
|
|
cvBytesOfCalleeSavedRegisters: 0
|
|
hasOpaqueSPAdjustment: false
|
|
hasVAStart: false
|
|
hasMustTailInVarArgFunc: false
|
|
hasTailCall: false
|
|
isCalleeSavedInfoValid: false
|
|
localFrameSize: 0
|
|
savePoint: []
|
|
restorePoint: []
|
|
fixedStack: []
|
|
stack: []
|
|
entry_values: []
|
|
callSites: []
|
|
debugValueSubstitutions: []
|
|
constants: []
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.1.entry:
|
|
liveins: $w0
|
|
|
|
%0:_(s32) = COPY $w0
|
|
%1:_(s32) = G_CONSTANT i32 1
|
|
%3:_(s32) = G_CONSTANT i32 0
|
|
DBG_VALUE %0(s32), $noreg, !10, !DIExpression(), debug-location !11
|
|
%2:_(s32) = nsw G_ADD %0, %1, debug-location !12
|
|
$w0 = COPY %3(s32)
|
|
RET_ReallyLR implicit $w0
|
|
)";
|
|
auto TM = createTargetMachine(Triple::normalize("aarch64--"), "", "");
|
|
if (!TM)
|
|
return;
|
|
MachineModuleInfo MMI(TM.get());
|
|
std::unique_ptr<Module> M = parseMIR(*TM, MIR, MMI, &C);
|
|
ASSERT_TRUE(M);
|
|
|
|
DroppedVariableStatsMIR Stats;
|
|
auto *MF = MMI.getMachineFunction(*M->getFunction("_Z3fooi"));
|
|
Stats.runBeforePass("Test", MF);
|
|
|
|
// This loop simulates an IR pass that drops debug information.
|
|
for (auto &MBB : *MF) {
|
|
for (auto &MI : MBB) {
|
|
if (MI.isDebugValueLike()) {
|
|
MI.eraseFromParent();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
Stats.runAfterPass("Test", MF);
|
|
ASSERT_EQ(Stats.getPassDroppedVariables(), true);
|
|
}
|
|
|
|
} // end anonymous namespace
|