[llvm] 223c764 - Add a pass to collect dropped var stats for MIR (#120501)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Dec 19 00:41:52 PST 2024
Author: Shubham Sandeep Rastogi
Date: 2024-12-19T00:41:48-08:00
New Revision: 223c7648468cd4f649a578d3f9cbc27a63523192
URL: https://github.com/llvm/llvm-project/commit/223c7648468cd4f649a578d3f9cbc27a63523192
DIFF: https://github.com/llvm/llvm-project/commit/223c7648468cd4f649a578d3f9cbc27a63523192.diff
LOG: Add a pass to collect dropped var stats for MIR (#120501)
Reland "Add a pass to collect dropped var stats for MIR" (#117044)
I am trying to reland https://github.com/llvm/llvm-project/pull/115566
I also moved the DroppedVariableStats code to the Analysis lib
This is part of a stack of patches with
https://github.com/llvm/llvm-project/pull/120502 being the first one in
the stack
Added:
llvm/unittests/MIR/DroppedVariableStatsMIRTest.cpp
Modified:
llvm/include/llvm/Analysis/DroppedVariableStats.h
llvm/include/llvm/CodeGen/MachineFunctionPass.h
llvm/lib/Analysis/CMakeLists.txt
llvm/lib/Analysis/DroppedVariableStats.cpp
llvm/lib/CodeGen/MachineFunctionPass.cpp
llvm/unittests/MIR/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/DroppedVariableStats.h b/llvm/include/llvm/Analysis/DroppedVariableStats.h
index 4555157c942b51..e340caf93326bf 100644
--- a/llvm/include/llvm/Analysis/DroppedVariableStats.h
+++ b/llvm/include/llvm/Analysis/DroppedVariableStats.h
@@ -7,7 +7,7 @@
///===---------------------------------------------------------------------===//
/// \file
/// Dropped Variable Statistics for Debug Information. Reports any number
-/// of #dbg_value that get dropped due to an optimization pass.
+/// of #dbg_values or DBG_VALUEs that get dropped due to an optimization pass.
///
///===---------------------------------------------------------------------===//
@@ -219,6 +219,52 @@ class DroppedVariableStatsIR : public DroppedVariableStats {
}
};
+/// A class to collect and print dropped debug information due to MIR
+/// optimization passes. After every MIR pass is run, it will print how many
+/// #DBG_VALUEs were dropped due to that pass.
+class DroppedVariableStatsMIR : public DroppedVariableStats {
+public:
+ DroppedVariableStatsMIR() : llvm::DroppedVariableStats(false) {}
+
+ void runBeforePass(StringRef PassID, MachineFunction *MF) {
+ if (PassID == "Debug Variable Analysis")
+ return;
+ setup();
+ return runOnMachineFunction(MF, true);
+ }
+
+ void runAfterPass(StringRef PassID, MachineFunction *MF) {
+ if (PassID == "Debug Variable Analysis")
+ return;
+ runOnMachineFunction(MF, false);
+ calculateDroppedVarStatsOnMachineFunction(MF, PassID, MF->getName().str());
+ cleanup();
+ }
+
+private:
+ const MachineFunction *MFunc;
+ /// Populate DebugVariablesBefore, DebugVariablesAfter, InlinedAts before or
+ /// after a pass has run to facilitate dropped variable calculation for an
+ /// llvm::MachineFunction.
+ void runOnMachineFunction(const MachineFunction *MF, bool Before);
+ /// Iterate over all Instructions in a MachineFunction and report any dropped
+ /// debug information.
+ void calculateDroppedVarStatsOnMachineFunction(const MachineFunction *MF,
+ StringRef PassID,
+ StringRef FuncOrModName);
+ /// Override base class method to run on an llvm::MachineFunction
+ /// specifically.
+ virtual void
+ visitEveryInstruction(unsigned &DroppedCount,
+ DenseMap<VarID, DILocation *> &InlinedAtsMap,
+ VarID Var) override;
+ /// Override base class method to run on DBG_VALUEs specifically.
+ virtual void visitEveryDebugRecord(
+ DenseSet<VarID> &VarIDSet,
+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
+ StringRef FuncName, bool Before) override;
+};
+
} // namespace llvm
#endif
diff --git a/llvm/include/llvm/CodeGen/MachineFunctionPass.h b/llvm/include/llvm/CodeGen/MachineFunctionPass.h
index caaf22c2139e31..0d49e4997bc9ac 100644
--- a/llvm/include/llvm/CodeGen/MachineFunctionPass.h
+++ b/llvm/include/llvm/CodeGen/MachineFunctionPass.h
@@ -18,6 +18,7 @@
#ifndef LLVM_CODEGEN_MACHINEFUNCTIONPASS_H
#define LLVM_CODEGEN_MACHINEFUNCTIONPASS_H
+#include "llvm/Analysis/DroppedVariableStats.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Pass.h"
@@ -67,6 +68,7 @@ class MachineFunctionPass : public FunctionPass {
MachineFunctionProperties RequiredProperties;
MachineFunctionProperties SetProperties;
MachineFunctionProperties ClearedProperties;
+ DroppedVariableStatsMIR DroppedVarStatsMF;
/// createPrinterPass - Get a machine function printer pass.
Pass *createPrinterPass(raw_ostream &O,
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index 5cf3777253fbe4..245276d370e0b0 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -50,6 +50,7 @@ add_llvm_component_library(LLVMAnalysis
CycleAnalysis.cpp
DDG.cpp
DDGPrinter.cpp
+ DroppedVariableStats.cpp
ConstraintSystem.cpp
Delinearization.cpp
DemandedBits.cpp
diff --git a/llvm/lib/Analysis/DroppedVariableStats.cpp b/llvm/lib/Analysis/DroppedVariableStats.cpp
index 7162cece4f3d9b..f900baaabae257 100644
--- a/llvm/lib/Analysis/DroppedVariableStats.cpp
+++ b/llvm/lib/Analysis/DroppedVariableStats.cpp
@@ -7,7 +7,7 @@
///===---------------------------------------------------------------------===//
/// \file
/// Dropped Variable Statistics for Debug Information. Reports any number
-/// of #dbg_value that get dropped due to an optimization pass.
+/// of #dbg_values or DBG_VALUEs that get dropped due to an optimization pass.
///
///===---------------------------------------------------------------------===//
@@ -192,3 +192,64 @@ void DroppedVariableStatsIR::visitEveryDebugRecord(
}
}
}
+
+void DroppedVariableStatsMIR::runOnMachineFunction(const MachineFunction *MF,
+ bool Before) {
+ auto &DebugVariables = DebugVariablesStack.back()[&MF->getFunction()];
+ auto FuncName = MF->getName();
+ MFunc = MF;
+ run(DebugVariables, FuncName, Before);
+}
+
+void DroppedVariableStatsMIR::calculateDroppedVarStatsOnMachineFunction(
+ const MachineFunction *MF, StringRef PassID, StringRef FuncOrModName) {
+ MFunc = MF;
+ StringRef FuncName = MF->getName();
+ const Function *Func = &MF->getFunction();
+ DebugVariables &DbgVariables = DebugVariablesStack.back()[Func];
+ calculateDroppedStatsAndPrint(DbgVariables, FuncName, PassID, FuncOrModName,
+ "MachineFunction", Func);
+}
+
+void DroppedVariableStatsMIR::visitEveryInstruction(
+ unsigned &DroppedCount, DenseMap<VarID, DILocation *> &InlinedAtsMap,
+ VarID Var) {
+ unsigned PrevDroppedCount = DroppedCount;
+ const DIScope *DbgValScope = std::get<0>(Var);
+ for (const auto &MBB : *MFunc) {
+ for (const auto &MI : MBB) {
+ if (!MI.isDebugInstr()) {
+ auto *DbgLoc = MI.getDebugLoc().get();
+ if (!DbgLoc)
+ continue;
+
+ auto *Scope = DbgLoc->getScope();
+ if (updateDroppedCount(DbgLoc, Scope, DbgValScope, InlinedAtsMap, Var,
+ DroppedCount))
+ break;
+ }
+ }
+ if (PrevDroppedCount != DroppedCount) {
+ PrevDroppedCount = DroppedCount;
+ break;
+ }
+ }
+}
+
+void DroppedVariableStatsMIR::visitEveryDebugRecord(
+ DenseSet<VarID> &VarIDSet,
+ DenseMap<StringRef, DenseMap<VarID, DILocation *>> &InlinedAtsMap,
+ StringRef FuncName, bool Before) {
+ for (const auto &MBB : *MFunc) {
+ for (const auto &MI : MBB) {
+ if (MI.isDebugValueLike()) {
+ auto *DbgVar = MI.getDebugVariable();
+ if (!DbgVar)
+ continue;
+ auto DbgLoc = MI.getDebugLoc();
+ populateVarIDSetAndInlinedMap(DbgVar, DbgLoc, VarIDSet, InlinedAtsMap,
+ FuncName, Before);
+ }
+ }
+ }
+}
diff --git a/llvm/lib/CodeGen/MachineFunctionPass.cpp b/llvm/lib/CodeGen/MachineFunctionPass.cpp
index 62ac3e32d24d9d..e803811643f874 100644
--- a/llvm/lib/CodeGen/MachineFunctionPass.cpp
+++ b/llvm/lib/CodeGen/MachineFunctionPass.cpp
@@ -32,6 +32,11 @@
using namespace llvm;
using namespace ore;
+static cl::opt<bool> DroppedVarStatsMIR(
+ "dropped-variable-stats-mir", cl::Hidden,
+ cl::desc("Dump dropped debug variables stats for MIR passes"),
+ cl::init(false));
+
Pass *MachineFunctionPass::createPrinterPass(raw_ostream &O,
const std::string &Banner) const {
return createMachineFunctionPrinterPass(O, Banner);
@@ -91,7 +96,15 @@ bool MachineFunctionPass::runOnFunction(Function &F) {
MFProps.reset(ClearedProperties);
- bool RV = runOnMachineFunction(MF);
+ bool RV;
+ if (DroppedVarStatsMIR) {
+ auto PassName = getPassName();
+ DroppedVarStatsMF.runBeforePass(PassName, &MF);
+ RV = runOnMachineFunction(MF);
+ DroppedVarStatsMF.runAfterPass(PassName, &MF);
+ } else {
+ RV = runOnMachineFunction(MF);
+ }
if (ShouldEmitSizeRemarks) {
// We wanted size remarks. Check if there was a change to the number of
diff --git a/llvm/unittests/MIR/CMakeLists.txt b/llvm/unittests/MIR/CMakeLists.txt
index 206094266ba148..48d7b9f03c7d11 100644
--- a/llvm/unittests/MIR/CMakeLists.txt
+++ b/llvm/unittests/MIR/CMakeLists.txt
@@ -14,6 +14,7 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_unittest(MIRTests
+ DroppedVariableStatsMIRTest.cpp
MachineMetadata.cpp
MachineStableHashTest.cpp
)
diff --git a/llvm/unittests/MIR/DroppedVariableStatsMIRTest.cpp b/llvm/unittests/MIR/DroppedVariableStatsMIRTest.cpp
new file mode 100644
index 00000000000000..b26a89c7adcbad
--- /dev/null
+++ b/llvm/unittests/MIR/DroppedVariableStatsMIRTest.cpp
@@ -0,0 +1,1067 @@
+//===- unittests/IR/DroppedVariableStatsTest.cpp - TimePassesHandler tests
+//----------===//
+//
+// 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/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/Passes/StandardInstrumentations.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "gtest/gtest.h"
+#include <gtest/gtest.h>
+#include <llvm/ADT/SmallString.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/Module.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 TT, StringRef CPU, StringRef FS) {
+ std::string Error;
+ const Target *T = TargetRegistry::lookupTarget(TT, Error);
+ if (!T)
+ return nullptr;
+ TargetOptions Options;
+ return std::unique_ptr<TargetMachine>(
+ static_cast<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
+hasEHCatchret: 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--"), "", "");
+ 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
+hasEHCatchret: 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--"), "", "");
+ 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
+hasEHCatchret: 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--"), "", "");
+ 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
+hasEHCatchret: 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--"), "", "");
+ 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
+hasEHCatchret: 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--"), "", "");
+ 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
+hasEHCatchret: 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--"), "", "");
+ 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
+hasEHCatchret: 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--"), "", "");
+ 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
More information about the llvm-commits
mailing list