1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

[Debugify] Support checking Machine IR debug info

Add mir-check-debug pass to check MIR-level debug info.

For IR-level, currently, LLVM have debugify + check-debugify to generate
and check debug IR. Much like the IR-level pass debugify, mir-debugify
inserts sequentially increasing line locations to each MachineInstr in a
Module, But there is no equivalent MIR-level check-debugify pass, So now
we support it at "mir-check-debug".

Reviewed By: djtodoro

Differential Revision: https://reviews.llvm.org/D91595
This commit is contained in:
Xiang1 Zhang 2020-12-16 20:23:29 -08:00
parent f195aa7b4b
commit 7ce08bafea
16 changed files with 433 additions and 55 deletions

View File

@ -342,8 +342,8 @@ A variant of the ``debugify`` utility described in
:ref:`Mutation testing for IR-level transformations<IRDebugify>` can be used
for MIR-level transformations as well: much like the IR-level pass,
``mir-debugify`` inserts sequentially increasing line locations to each
``MachineInstr`` in a ``Module`` (although there is no equivalent MIR-level
``check-debugify`` pass).
``MachineInstr`` in a ``Module``. And the MIR-level ``mir-check-debugify`` is
similar to IR-level ``check-debugify`` pass.
For example, here is a snippet before:
@ -403,16 +403,32 @@ and ``-start-after``. For example:
$ llc -debugify-and-strip-all-safe -run-pass=... <other llc args>
$ llc -debugify-and-strip-all-safe -O1 <other llc args>
If you want to check it after each pass in a pipeline, use
``-debugify-check-and-strip-all-safe``. This can also be combined with
``-start-before`` and ``-start-after``. For example:
.. code-block:: bash
$ llc -debugify-check-and-strip-all-safe -run-pass=... <other llc args>
$ llc -debugify-check-and-strip-all-safe -O1 <other llc args>
To check all debug info from a test, use ``mir-check-debugify``, like:
.. code-block:: bash
$ llc -run-pass=mir-debugify,other-pass,mir-check-debugify
To strip out all debug info from a test, use ``mir-strip-debug``, like:
.. code-block:: bash
$ llc -run-pass=mir-debugify,other-pass,mir-strip-debug
It can be useful to combine ``mir-debugify`` and ``mir-strip-debug`` to
identify backend transformations which break in the presence of debug info.
For example, to run the AArch64 backend tests with all normal passes
"sandwiched" in between MIRDebugify and MIRStripDebugify mutation passes, run:
It can be useful to combine ``mir-debugify``, ``mir-check-debugify`` and/or
``mir-strip-debug`` to identify backend transformations which break in
the presence of debug info. For example, to run the AArch64 backend tests
with all normal passes "sandwiched" in between MIRDebugify and
MIRStripDebugify mutation passes, run:
.. code-block:: bash

View File

@ -482,6 +482,9 @@ namespace llvm {
/// info was generated by another source such as clang.
ModulePass *createStripDebugMachineModulePass(bool OnlyDebugified);
/// Creates MIR Check Debug pass. \see MachineCheckDebugify.cpp
ModulePass *createCheckDebugMachineModulePass();
/// The pass fixups statepoint machine instruction to replace usage of
/// caller saved registers with stack slots.
extern char &FixupStatepointCallerSavedID;

View File

@ -313,6 +313,9 @@ public:
/// Add a pass to remove debug info from the MIR.
void addStripDebugPass();
/// Add a pass to check synthesized debug info for MIR.
void addCheckDebugPass();
/// Add standard passes before a pass that's about to be added. For example,
/// the DebugifyMachineModulePass if it is enabled.
void addMachinePrePasses(bool AllowDebugify = true);

View File

@ -112,6 +112,7 @@ void initializeCallGraphViewerPass(PassRegistry&);
void initializeCallGraphWrapperPassPass(PassRegistry&);
void initializeCallSiteSplittingLegacyPassPass(PassRegistry&);
void initializeCalledValuePropagationLegacyPassPass(PassRegistry &);
void initializeCheckDebugMachineModulePass(PassRegistry &);
void initializeCodeGenPreparePass(PassRegistry&);
void initializeConstantHoistingLegacyPassPass(PassRegistry&);
void initializeConstantMergeLegacyPassPass(PassRegistry&);

View File

@ -74,6 +74,7 @@ add_llvm_component_library(LLVMCodeGen
MachineCombiner.cpp
MachineCopyPropagation.cpp
MachineCSE.cpp
MachineCheckDebugify.cpp
MachineDebugify.cpp
MachineDominanceFrontier.cpp
MachineDominators.cpp

View File

@ -25,6 +25,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializeBranchRelaxationPass(Registry);
initializeCFGuardLongjmpPass(Registry);
initializeCFIInstrInserterPass(Registry);
initializeCheckDebugMachineModulePass(Registry);
initializeCodeGenPreparePass(Registry);
initializeDeadMachineInstructionElimPass(Registry);
initializeDebugifyMachineModulePass(Registry);

View File

@ -0,0 +1,126 @@
//===- MachineCheckDebugify.cpp - Check debug info ------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file This checks debug info after mir-debugify (+ pass-to-test). Currently
/// it simply checks the integrity of line info in DILocation and
/// DILocalVariable which mir-debugifiy generated before.
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Utils/Debugify.h"
#define DEBUG_TYPE "mir-check-debugify"
using namespace llvm;
namespace {
struct CheckDebugMachineModule : public ModulePass {
bool runOnModule(Module &M) override {
MachineModuleInfo &MMI =
getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
NamedMDNode *NMD = M.getNamedMetadata("llvm.mir.debugify");
if (!NMD) {
errs() << "WARNING: Please run mir-debugify to generate "
"llvm.mir.debugify metadata first.\n";
return false;
}
auto getDebugifyOperand = [&](unsigned Idx) -> unsigned {
return mdconst::extract<ConstantInt>(NMD->getOperand(Idx)->getOperand(0))
->getZExtValue();
};
assert(NMD->getNumOperands() == 2 &&
"llvm.mir.debugify should have exactly 2 operands!");
unsigned NumLines = getDebugifyOperand(0);
unsigned NumVars = getDebugifyOperand(1);
BitVector MissingLines{NumLines, true};
BitVector MissingVars{NumVars, true};
for (Function &F : M.functions()) {
MachineFunction *MF = MMI.getMachineFunction(F);
if (!MF)
continue;
for (MachineBasicBlock &MBB : *MF) {
// Find missing lines.
// TODO: Avoid meta instructions other than dbg_val.
for (MachineInstr &MI : MBB) {
if (MI.isDebugValue())
continue;
const DebugLoc DL = MI.getDebugLoc();
if (DL && DL.getLine() != 0) {
MissingLines.reset(DL.getLine() - 1);
continue;
}
if (!DL) {
errs() << "WARNING: Instruction with empty DebugLoc in function ";
errs() << F.getName() << " --";
MI.print(errs());
}
}
// Find missing variables.
// TODO: Handle DBG_INSTR_REF which is under an experimental option now.
for (MachineInstr &MI : MBB) {
if (!MI.isDebugValue())
continue;
const DILocalVariable *LocalVar = MI.getDebugVariable();
unsigned Var = ~0U;
(void)to_integer(LocalVar->getName(), Var, 10);
assert(Var <= NumVars && "Unexpected name for DILocalVariable");
MissingVars.reset(Var - 1);
}
}
}
bool Fail = false;
for (unsigned Idx : MissingLines.set_bits()) {
errs() << "WARNING: Missing line " << Idx + 1 << "\n";
Fail = true;
}
for (unsigned Idx : MissingVars.set_bits()) {
errs() << "WARNING: Missing variable " << Idx + 1 << "\n";
Fail = true;
}
errs() << "Machine IR debug info check: ";
errs() << (Fail ? "FAIL" : "PASS") << "\n";
return false;
}
CheckDebugMachineModule() : ModulePass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineModuleInfoWrapperPass>();
AU.addPreserved<MachineModuleInfoWrapperPass>();
AU.setPreservesCFG();
}
static char ID; // Pass identification.
};
char CheckDebugMachineModule::ID = 0;
} // end anonymous namespace
INITIALIZE_PASS_BEGIN(CheckDebugMachineModule, DEBUG_TYPE,
"Machine Check Debug Module", false, false)
INITIALIZE_PASS_END(CheckDebugMachineModule, DEBUG_TYPE,
"Machine Check Debug Module", false, false)
ModulePass *llvm::createCheckDebugMachineModulePass() {
return new CheckDebugMachineModule();
}

View File

@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
@ -89,10 +90,11 @@ bool applyDebugifyMetadataToMachineFunction(MachineModuleInfo &MMI,
// Do this by introducing debug uses of each register definition. If that is
// not possible (e.g. we have a phi or a meta instruction), emit a constant.
uint64_t NextImm = 0;
SmallSet<DILocalVariable *, 16> VarSet;
const MCInstrDesc &DbgValDesc = TII.get(TargetOpcode::DBG_VALUE);
for (MachineBasicBlock &MBB : MF) {
MachineBasicBlock::iterator FirstNonPHIIt = MBB.getFirstNonPHI();
for (auto I = MBB.begin(), E = MBB.end(); I != E; ) {
for (auto I = MBB.begin(), E = MBB.end(); I != E;) {
MachineInstr &MI = *I;
++I;
@ -113,6 +115,7 @@ bool applyDebugifyMetadataToMachineFunction(MachineModuleInfo &MMI,
Line = EarliestDVI->getDebugLoc().getLine();
DILocalVariable *LocalVar = Line2Var[Line];
assert(LocalVar && "No variable for current line?");
VarSet.insert(LocalVar);
// Emit DBG_VALUEs for register definitions.
SmallVector<MachineOperand *, 4> RegDefs;
@ -132,6 +135,33 @@ bool applyDebugifyMetadataToMachineFunction(MachineModuleInfo &MMI,
}
}
// Here we save the number of lines and variables into "llvm.mir.debugify".
// It is useful for mir-check-debugify.
NamedMDNode *NMD = M.getNamedMetadata("llvm.mir.debugify");
IntegerType *Int32Ty = Type::getInt32Ty(Ctx);
if (!NMD) {
NMD = M.getOrInsertNamedMetadata("llvm.mir.debugify");
auto addDebugifyOperand = [&](unsigned N) {
NMD->addOperand(MDNode::get(
Ctx, ValueAsMetadata::getConstant(ConstantInt::get(Int32Ty, N))));
};
// Add number of lines.
addDebugifyOperand(NextLine - 1);
// Add number of variables.
addDebugifyOperand(VarSet.size());
} else {
assert(NMD->getNumOperands() == 2 &&
"llvm.mir.debugify should have exactly 2 operands!");
auto setDebugifyOperand = [&](unsigned Idx, unsigned N) {
NMD->setOperand(Idx, MDNode::get(Ctx, ValueAsMetadata::getConstant(
ConstantInt::get(Int32Ty, N))));
};
// Set number of lines.
setDebugifyOperand(0, NextLine - 1);
// Set number of variables.
setDebugifyOperand(1, VarSet.size());
}
return true;
}

View File

@ -120,6 +120,12 @@ static cl::opt<cl::boolOrDefault> DebugifyAndStripAll(
"Debugify MIR before and Strip debug after "
"each pass except those known to be unsafe when debug info is present"),
cl::ZeroOrMore);
static cl::opt<cl::boolOrDefault> DebugifyCheckAndStripAll(
"debugify-check-and-strip-all-safe", cl::Hidden,
cl::desc(
"Debugify MIR before, by checking and stripping the debug info after, "
"each pass except those known to be unsafe when debug info is present"),
cl::ZeroOrMore);
enum RunOutliner { AlwaysOutline, NeverOutline, TargetDefault };
// Enable or disable the MachineOutliner.
static cl::opt<RunOutliner> EnableMachineOutliner(
@ -625,15 +631,26 @@ void TargetPassConfig::addStripDebugPass() {
PM->add(createStripDebugMachineModulePass(/*OnlyDebugified=*/true));
}
void TargetPassConfig::addCheckDebugPass() {
PM->add(createCheckDebugMachineModulePass());
}
void TargetPassConfig::addMachinePrePasses(bool AllowDebugify) {
if (AllowDebugify && DebugifyAndStripAll == cl::BOU_TRUE && DebugifyIsSafe)
if (AllowDebugify && DebugifyIsSafe &&
(DebugifyAndStripAll == cl::BOU_TRUE ||
DebugifyCheckAndStripAll == cl::BOU_TRUE))
addDebugifyPass();
}
void TargetPassConfig::addMachinePostPasses(const std::string &Banner,
bool AllowVerify, bool AllowStrip) {
if (DebugifyAndStripAll == cl::BOU_TRUE && DebugifyIsSafe)
if (DebugifyIsSafe) {
if (DebugifyCheckAndStripAll == cl::BOU_TRUE) {
addCheckDebugPass();
addStripDebugPass();
} else if (DebugifyAndStripAll == cl::BOU_TRUE)
addStripDebugPass();
}
if (AllowVerify)
addVerifyPass(Banner);
}

View File

@ -13,17 +13,17 @@ body: |
liveins: $x0
; CHECK-LABEL: name: fconstant_to_constant_s32
; CHECK: liveins: $x0
; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0, debug-location !10
; CHECK: DBG_VALUE [[COPY]](p0), $noreg, !8, !DIExpression(), debug-location !10
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x3FA99999A0000000, debug-location !DILocation(line: 2, column: 1, scope: !5)
; CHECK: DBG_VALUE [[C]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 2, column: 1, scope: !5)
; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 524, debug-location !DILocation(line: 3, column: 1, scope: !5)
; CHECK: DBG_VALUE [[C1]](s64), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 3, column: 1, scope: !5)
; CHECK: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C1]](s64), debug-location !DILocation(line: 4, column: 1, scope: !5)
; CHECK: DBG_VALUE [[PTR_ADD]](p0), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 4, column: 1, scope: !5)
; CHECK: G_STORE [[C]](s32), [[PTR_ADD]](p0), debug-location !DILocation(line: 5, column: 1, scope: !5) :: (store 4)
; CHECK: DBG_VALUE 0, $noreg, !8, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !5)
; CHECK: RET_ReallyLR debug-location !DILocation(line: 6, column: 1, scope: !5)
; CHECK: [[COPY:%[0-9]+]]:_(p0) = COPY $x0, debug-location !11
; CHECK: DBG_VALUE [[COPY]](p0), $noreg, !9, !DIExpression(), debug-location !11
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x3FA99999A0000000, debug-location !DILocation(line: 2, column: 1, scope: !6)
; CHECK: DBG_VALUE [[C]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 2, column: 1, scope: !6)
; CHECK: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 524, debug-location !DILocation(line: 3, column: 1, scope: !6)
; CHECK: DBG_VALUE [[C1]](s64), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 3, column: 1, scope: !6)
; CHECK: [[PTR_ADD:%[0-9]+]]:_(p0) = G_PTR_ADD [[COPY]], [[C1]](s64), debug-location !DILocation(line: 4, column: 1, scope: !6)
; CHECK: DBG_VALUE [[PTR_ADD]](p0), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 4, column: 1, scope: !6)
; CHECK: G_STORE [[C]](s32), [[PTR_ADD]](p0), debug-location !DILocation(line: 5, column: 1, scope: !6) :: (store 4)
; CHECK: DBG_VALUE 0, $noreg, !9, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !6)
; CHECK: RET_ReallyLR debug-location !DILocation(line: 6, column: 1, scope: !6)
%0:_(p0) = COPY $x0
%3:_(s32) = G_FCONSTANT float 0x3FA99999A0000000
%1:_(s64) = G_CONSTANT i64 524

View File

@ -36,41 +36,41 @@ body: |
; CHECK: bb.0:
; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000)
; CHECK: liveins: $w0
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0, debug-location !10
; CHECK: DBG_VALUE [[COPY]](s32), $noreg, !8, !DIExpression(), debug-location !10
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0, debug-location !DILocation(line: 2, column: 1, scope: !5)
; CHECK: DBG_VALUE [[C]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 2, column: 1, scope: !5)
; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1, debug-location !DILocation(line: 3, column: 1, scope: !5)
; CHECK: DBG_VALUE [[C1]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 3, column: 1, scope: !5)
; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2, debug-location !DILocation(line: 4, column: 1, scope: !5)
; CHECK: DBG_VALUE [[C2]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 4, column: 1, scope: !5)
; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), [[COPY]](s32), [[C]], debug-location !DILocation(line: 5, column: 1, scope: !5)
; CHECK: DBG_VALUE [[ICMP]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !5)
; CHECK: G_BRCOND [[ICMP]](s1), %bb.1, debug-location !DILocation(line: 6, column: 1, scope: !5)
; CHECK: G_BR %bb.2, debug-location !DILocation(line: 7, column: 1, scope: !5)
; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $w0, debug-location !11
; CHECK: DBG_VALUE [[COPY]](s32), $noreg, !9, !DIExpression(), debug-location !11
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0, debug-location !DILocation(line: 2, column: 1, scope: !6)
; CHECK: DBG_VALUE [[C]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 2, column: 1, scope: !6)
; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1, debug-location !DILocation(line: 3, column: 1, scope: !6)
; CHECK: DBG_VALUE [[C1]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 3, column: 1, scope: !6)
; CHECK: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2, debug-location !DILocation(line: 4, column: 1, scope: !6)
; CHECK: DBG_VALUE [[C2]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 4, column: 1, scope: !6)
; CHECK: [[ICMP:%[0-9]+]]:_(s1) = G_ICMP intpred(ugt), [[COPY]](s32), [[C]], debug-location !DILocation(line: 5, column: 1, scope: !6)
; CHECK: DBG_VALUE [[ICMP]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !6)
; CHECK: G_BRCOND [[ICMP]](s1), %bb.1, debug-location !DILocation(line: 6, column: 1, scope: !6)
; CHECK: G_BR %bb.2, debug-location !DILocation(line: 7, column: 1, scope: !6)
; CHECK: bb.1:
; CHECK: successors: %bb.3(0x80000000)
; CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[C1]], debug-location !DILocation(line: 8, column: 1, scope: !5)
; CHECK: DBG_VALUE [[ADD]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 8, column: 1, scope: !5)
; CHECK: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ADD]](s32), debug-location !DILocation(line: 9, column: 1, scope: !5)
; CHECK: DBG_VALUE [[TRUNC]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 9, column: 1, scope: !5)
; CHECK: G_BR %bb.3, debug-location !DILocation(line: 10, column: 1, scope: !5)
; CHECK: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[C1]], debug-location !DILocation(line: 8, column: 1, scope: !6)
; CHECK: DBG_VALUE [[ADD]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 8, column: 1, scope: !6)
; CHECK: [[TRUNC:%[0-9]+]]:_(s1) = G_TRUNC [[ADD]](s32), debug-location !DILocation(line: 9, column: 1, scope: !6)
; CHECK: DBG_VALUE [[TRUNC]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 9, column: 1, scope: !6)
; CHECK: G_BR %bb.3, debug-location !DILocation(line: 10, column: 1, scope: !6)
; CHECK: bb.2:
; CHECK: successors: %bb.3(0x80000000)
; CHECK: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[C2]], debug-location !DILocation(line: 11, column: 1, scope: !5)
; CHECK: DBG_VALUE [[ADD1]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 11, column: 1, scope: !5)
; CHECK: [[TRUNC1:%[0-9]+]]:_(s1) = G_TRUNC [[ADD1]](s32), debug-location !DILocation(line: 12, column: 1, scope: !5)
; CHECK: DBG_VALUE [[TRUNC1]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 12, column: 1, scope: !5)
; CHECK: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[C2]], debug-location !DILocation(line: 11, column: 1, scope: !6)
; CHECK: DBG_VALUE [[ADD1]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 11, column: 1, scope: !6)
; CHECK: [[TRUNC1:%[0-9]+]]:_(s1) = G_TRUNC [[ADD1]](s32), debug-location !DILocation(line: 12, column: 1, scope: !6)
; CHECK: DBG_VALUE [[TRUNC1]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 12, column: 1, scope: !6)
; CHECK: bb.3:
; CHECK: [[PHI:%[0-9]+]]:_(s1) = G_PHI [[TRUNC]](s1), %bb.1, [[TRUNC1]](s1), %bb.2, debug-location !DILocation(line: 13, column: 1, scope: !5)
; CHECK: [[PHI1:%[0-9]+]]:_(s1) = G_PHI [[TRUNC]](s1), %bb.1, [[TRUNC1]](s1), %bb.2, debug-location !DILocation(line: 14, column: 1, scope: !5)
; CHECK: DBG_VALUE [[PHI]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 13, column: 1, scope: !5)
; CHECK: DBG_VALUE [[PHI1]](s1), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 14, column: 1, scope: !5)
; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[PHI]](s1), debug-location !DILocation(line: 15, column: 1, scope: !5)
; CHECK: DBG_VALUE [[ZEXT]](s32), $noreg, !8, !DIExpression(), debug-location !DILocation(line: 15, column: 1, scope: !5)
; CHECK: $w0 = COPY [[ZEXT]](s32), debug-location !DILocation(line: 16, column: 1, scope: !5)
; CHECK: DBG_VALUE $w0, $noreg, !8, !DIExpression(), debug-location !DILocation(line: 16, column: 1, scope: !5)
; CHECK: RET_ReallyLR implicit $w0, debug-location !DILocation(line: 17, column: 1, scope: !5)
; CHECK: [[PHI:%[0-9]+]]:_(s1) = G_PHI [[TRUNC]](s1), %bb.1, [[TRUNC1]](s1), %bb.2, debug-location !DILocation(line: 13, column: 1, scope: !6)
; CHECK: [[PHI1:%[0-9]+]]:_(s1) = G_PHI [[TRUNC]](s1), %bb.1, [[TRUNC1]](s1), %bb.2, debug-location !DILocation(line: 14, column: 1, scope: !6)
; CHECK: DBG_VALUE [[PHI]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 13, column: 1, scope: !6)
; CHECK: DBG_VALUE [[PHI1]](s1), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 14, column: 1, scope: !6)
; CHECK: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[PHI]](s1), debug-location !DILocation(line: 15, column: 1, scope: !6)
; CHECK: DBG_VALUE [[ZEXT]](s32), $noreg, !9, !DIExpression(), debug-location !DILocation(line: 15, column: 1, scope: !6)
; CHECK: $w0 = COPY [[ZEXT]](s32), debug-location !DILocation(line: 16, column: 1, scope: !6)
; CHECK: DBG_VALUE $w0, $noreg, !9, !DIExpression(), debug-location !DILocation(line: 16, column: 1, scope: !6)
; CHECK: RET_ReallyLR implicit $w0, debug-location !DILocation(line: 17, column: 1, scope: !6)
bb.0:
successors: %bb.1(0x40000000), %bb.2(0x40000000)
liveins: $w0

View File

@ -0,0 +1,80 @@
# REQUIRES: x86-registered-target
# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=mir-check-debugify -o - %s 2>&1 | FileCheck %s
--- |
; ModuleID = 'check-line-and-variables.mir'
source_filename = "check-line-and-variables.c"
@ga = dso_local local_unnamed_addr global i32 2, align 4
; Function Attrs: nofree norecurse nounwind uwtable writeonly
define dso_local i32 @foo(i32 %a, i32 %b) local_unnamed_addr #0 !dbg !9 {
entry:
%add = add nsw i32 %b, %a, !dbg !15
call void @llvm.dbg.value(metadata i32 %add, metadata !12, metadata !DIExpression()), !dbg !15
%mul = shl nsw i32 %add, 1, !dbg !16
call void @llvm.dbg.value(metadata i32 %mul, metadata !14, metadata !DIExpression()), !dbg !16
store i32 %mul, i32* @ga, align 4, !dbg !17
ret i32 %add, !dbg !18
}
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}
!llvm.dbg.cu = !{!3}
!llvm.mir.debugify = !{!6, !7}
!llvm.debugify = !{!8, !7}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git c0a922b3db2d39f36c0c01776cce90cc160a7d62)"}
!3 = distinct !DICompileUnit(language: DW_LANG_C, file: !4, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !5)
!4 = !DIFile(filename: "main.mir", directory: "/")
!5 = !{}
!6 = !{i32 6}
!7 = !{i32 2}
!8 = !{i32 4}
!9 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: null, file: !4, line: 1, type: !10, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !3, retainedNodes: !11)
!10 = !DISubroutineType(types: !5)
!11 = !{!12, !14}
!12 = !DILocalVariable(name: "1", scope: !9, file: !4, line: 1, type: !13)
!13 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
!14 = !DILocalVariable(name: "2", scope: !9, file: !4, line: 2, type: !13)
!15 = !DILocation(line: 1, column: 1, scope: !9)
!16 = !DILocation(line: 2, column: 1, scope: !9)
!17 = !DILocation(line: 3, column: 1, scope: !9)
!18 = !DILocation(line: 4, column: 1, scope: !9)
...
---
name: foo
body: |
bb.0.entry:
liveins: $edi, $esi
%1:gr32 = COPY $esi, debug-location !15
DBG_VALUE %1, $noreg, !12, !DIExpression(), debug-location !15
; Let it missing !14 and debug-location !16
; %0:gr32 = COPY $edi, debug-location !16
; DBG_VALUE %0, $noreg, !14, !DIExpression(), debug-location !16
%0:gr32 = COPY $edi
%2:gr32 = nsw ADD32rr %1, %0, implicit-def dead $eflags, debug-location !17
DBG_VALUE %2, $noreg, !12, !DIExpression(), debug-location !17
DBG_VALUE $eflags, $noreg, !12, !DIExpression(), debug-location !17
%3:gr32 = nsw ADD32rr %2, %2, implicit-def dead $eflags, debug-location !18
DBG_VALUE %3, $noreg, !12, !DIExpression(), debug-location !18
DBG_VALUE $eflags, $noreg, !12, !DIExpression(), debug-location !18
MOV32mr $rip, 1, $noreg, @ga, $noreg, killed %3, debug-location !DILocation(line: 5, column: 1, scope: !9) :: (store 4 into @ga, !tbaa !18)
DBG_VALUE 0, $noreg, !12, !DIExpression(), debug-location !DILocation(line: 5, column: 1, scope: !9)
; Let it miss Line 6: Change "!DILocation(line: 6, ..." to "!DILocation(line: 5, ..."
$eax = COPY %2, debug-location !DILocation(line: 5, column: 1, scope: !9)
DBG_VALUE $eax, $noreg, !12, !DIExpression(), debug-location !DILocation(line: 6, column: 1, scope: !9)
RET 0, $eax, debug-location !DILocation(line: 7, column: 1, scope: !9)
;CHECK: WARNING: Instruction with empty DebugLoc in function foo --%1:gr32 = COPY $edi
;CHECK-NEXT: WARNING: Missing line 2
;CHECK-NEXT: WARNING: Missing line 6
;CHECK-NEXT: WARNING: Missing variable 2
;CHECK-NEXT: Machine IR debug info check: FAIL
...

View File

@ -0,0 +1,29 @@
; RUN: llc -debugify-check-and-strip-all-safe -o - %s 2>&1 | FileCheck %s
; ModuleID = 'main.c'
source_filename = "main.c"
@ga = dso_local global i32 2, align 4
define dso_local i32 @foo(i32 %a, i32 %b) {
entry:
%a.addr = alloca i32, align 4
%b.addr = alloca i32, align 4
%c = alloca i32, align 4
store i32 %a, i32* %a.addr, align 4
store i32 %b, i32* %b.addr, align 4
%0 = load i32, i32* %a.addr, align 4
%1 = load i32, i32* %b.addr, align 4
%add = add nsw i32 %0, %1
store i32 %add, i32* %c, align 4
%2 = load i32, i32* %c, align 4
%mul = mul nsw i32 %2, 2
store i32 %mul, i32* @ga, align 4
%3 = load i32, i32* %c, align 4
ret i32 %3
}
; Different Back-Ends may have different number of passes, here we only
; check two of them to make sure -debugify-check-and-strip-all-safe works.
;CHECK: Machine IR debug info check: PASS
;CHECK: Machine IR debug info check: PASS

View File

@ -0,0 +1,70 @@
# REQUIRES: x86-registered-target
# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=mir-debugify,dead-mi-elimination,mir-check-debugify -o - %s 2>&1 | FileCheck %s
# RUN: llc -mtriple=x86_64-unknown-linux-gnu -run-pass=mir-debugify,mir-check-debugify -o - %s 2>&1 | FileCheck %s --check-prefix=CHECK-PASS
--- |
; ModuleID = 'check-line-and-variables.mir'
source_filename = "check-line-and-variables.ll"
@ga = dso_local global i32 2, align 4
; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @foo(i32 %a, i32 %b) {
entry:
%a.addr = alloca i32, align 4
%b.addr = alloca i32, align 4
%c = alloca i32, align 4
store i32 %a, i32* %a.addr, align 4
store i32 %b, i32* %b.addr, align 4
%0 = load i32, i32* %a.addr, align 4
%1 = load i32, i32* %b.addr, align 4
%add = add nsw i32 %0, %1
store i32 %add, i32* %c, align 4
%2 = load i32, i32* %c, align 4
%mul = mul nsw i32 %2, 2
store i32 %mul, i32* @ga, align 4
%3 = load i32, i32* %c, align 4
; dead-mi-elimination will remove %4 = ...
%4 = load i32, i32* %a.addr, align 4
ret i32 %3
}
...
---
name: foo
alignment: 16
stack:
- { id: 0, name: a.addr, type: default, offset: 0, size: 4, alignment: 4,
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
- { id: 1, name: b.addr, type: default, offset: 0, size: 4, alignment: 4,
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
- { id: 2, name: c, type: default, offset: 0, size: 4, alignment: 4,
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
body: |
bb.0.entry:
liveins: $edi, $esi
%2:gr32 = COPY $esi
%0:gr32 = COPY $edi
%1:gr32 = COPY killed %0
%3:gr32 = COPY killed %2
MOV32mr %stack.0.a.addr, 1, $noreg, 0, $noreg, %1 :: (store 4 into %ir.a.addr)
MOV32mr %stack.1.b.addr, 1, $noreg, 0, $noreg, %3 :: (store 4 into %ir.b.addr)
%14:gr32 = MOV32rm %stack.0.a.addr, 1, $noreg, 0, $noreg :: (load 4 from %ir.a.addr)
%13:gr32 = ADD32rm killed %14, %stack.1.b.addr, 1, $noreg, 0, $noreg, implicit-def $eflags :: (load 4 from %ir.b.addr)
; dead-mi-elimination will remove %15:gr32 = ...
%15:gr32 = MOV32rm %stack.0.a.addr, 1, $noreg, 0, $noreg :: (load 4 from %ir.a.addr)
MOV32mr %stack.2.c, 1, $noreg, 0, $noreg, killed %13 :: (store 4 into %ir.c)
%9:gr32 = MOV32rm %stack.2.c, 1, $noreg, 0, $noreg :: (load 4 from %ir.c)
%8:gr32 = SHL32ri killed %9, 1, implicit-def $eflags
MOV32mr $noreg, 1, $noreg, @ga, $noreg, killed %8 :: (store 4 into @ga)
%5:gr32 = MOV32rm %stack.2.c, 1, $noreg, 0, $noreg :: (load 4 from %ir.c)
$eax = COPY %5
RETQ implicit $eax
;CHECK: WARNING: Missing line 9
;CHECK-NEXT: Machine IR debug info check: FAIL
;CHECK-PASS: Machine IR debug info check: PASS
...

View File

@ -17,10 +17,10 @@
ret i32 %sub
}
; ALL: !llvm.dbg.cu = !{!0}
; ALL: !llvm.dbg.cu = !{![[CU:[0-9]+]]}
; ALL: !llvm.debugify =
; ALL: !llvm.module.flags = !{![[VERSION:[0-9]+]]}
; ALL: !0 = distinct !DICompileUnit(
; ALL: ![[CU]] = distinct !DICompileUnit(
; ALL: ![[VERSION]] = !{i32 2, !"Debug Info Version", i32 3}
; VALUE: [[VAR1:![0-9]+]] = !DILocalVariable(name: "1"
; VALUE: [[VAR2:![0-9]+]] = !DILocalVariable(name: "2"
@ -44,8 +44,8 @@ body: |
; VALUE: DBG_VALUE %1(s32), $noreg, [[VAR2]], !DIExpression(), debug-location [[L2]]
; ALL: %2:_(s32) = G_CONSTANT i32 2, debug-location [[L3]]
; VALUE: DBG_VALUE %2(s32), $noreg, [[VAR1]], !DIExpression(), debug-location [[L3]]
; ALL: %3:_(s32) = G_ADD %0, %2, debug-location !DILocation(line: 4, column: 1, scope: !6)
; ALL: %3:_(s32) = G_ADD %0, %2, debug-location !DILocation(line: 4, column: 1, scope: [[SP:![0-9]+]])
; VALUE: DBG_VALUE %3(s32), $noreg, [[VAR1]], !DIExpression(), debug-location !DILocation(line: 4
; ALL: %4:_(s32) = G_SUB %3, %1, debug-location !DILocation(line: 5, column: 1, scope: !6)
; ALL: %4:_(s32) = G_SUB %3, %1, debug-location !DILocation(line: 5, column: 1, scope: [[SP]])
; VALUE: DBG_VALUE %4(s32), $noreg, [[VAR1]], !DIExpression(), debug-location !DILocation(line: 5
...

View File

@ -99,6 +99,7 @@ static_library("CodeGen") {
"MachineBlockPlacement.cpp",
"MachineBranchProbabilityInfo.cpp",
"MachineCSE.cpp",
"MachineCheckDebugify.cpp",
"MachineCombiner.cpp",
"MachineCopyPropagation.cpp",
"MachineDebugify.cpp",