1//===- MachineStripDebug.cpp - Strip debug info ---------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file This removes debug info from everything. It can be used to ensure
10/// tests can be debugified without affecting the output MIR.
11//===----------------------------------------------------------------------===//
12
13#include "llvm/CodeGen/MachineStripDebug.h"
14#include "llvm/CodeGen/MachineBasicBlock.h"
15#include "llvm/CodeGen/MachineFunction.h"
16#include "llvm/CodeGen/MachineFunctionAnalysis.h"
17#include "llvm/CodeGen/MachineModuleInfo.h"
18#include "llvm/CodeGen/Passes.h"
19#include "llvm/IR/Analysis.h"
20#include "llvm/IR/Module.h"
21#include "llvm/IR/PassManager.h"
22#include "llvm/InitializePasses.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Transforms/Utils/Debugify.h"
25
26#define DEBUG_TYPE "mir-strip-debug"
27
28using namespace llvm;
29
30namespace {
31
32cl::opt<bool>
33 OnlyDebugifiedDefault("mir-strip-debugify-only",
34 cl::desc("Should mir-strip-debug only strip debug "
35 "info from debugified modules by default"),
36 cl::init(Val: true));
37
38bool stripDebugMachineModuleImpl(
39 Module &M, bool OnlyDebugified,
40 llvm::function_ref<MachineFunction *(Function &)> GetMF) {
41 if (OnlyDebugified) {
42 NamedMDNode *DebugifyMD = M.getNamedMetadata(Name: "llvm.debugify");
43 if (!DebugifyMD) {
44 LLVM_DEBUG(dbgs() << "Not stripping debug info"
45 " (debugify metadata not found)?\n");
46 return false;
47 }
48 }
49
50 bool Changed = false;
51 for (Function &F : M.functions()) {
52 MachineFunction *MaybeMF = GetMF(F);
53 if (!MaybeMF)
54 continue;
55 MachineFunction &MF = *MaybeMF;
56 for (MachineBasicBlock &MBB : MF) {
57 for (MachineInstr &MI : llvm::make_early_inc_range(Range: MBB.instrs())) {
58 if (MI.isDebugInstr()) {
59 // FIXME: We should remove all of them. However, AArch64 emits an
60 // invalid `DBG_VALUE $lr` with only one operand instead of
61 // the usual three and has a test that depends on it's
62 // preservation. Preserve it for now.
63 if (MI.getNumOperands() > 1) {
64 LLVM_DEBUG(dbgs() << "Removing debug instruction " << MI);
65 MBB.erase_instr(I: &MI);
66 Changed |= true;
67 continue;
68 }
69 }
70 if (MI.getDebugLoc()) {
71 LLVM_DEBUG(dbgs() << "Removing location " << MI);
72 MI.setDebugLoc(DebugLoc());
73 Changed |= true;
74 continue;
75 }
76 LLVM_DEBUG(dbgs() << "Keeping " << MI);
77 }
78 }
79 }
80
81 Changed |= stripDebugifyMetadata(M);
82
83 return Changed;
84}
85
86struct StripDebugMachineModule : public ModulePass {
87 bool runOnModule(Module &M) override {
88 MachineModuleInfo &MMI =
89 getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
90 return stripDebugMachineModuleImpl(
91 M, OnlyDebugified, GetMF: [&MMI](Function &F) -> MachineFunction * {
92 return MMI.getMachineFunction(F);
93 });
94 }
95
96 StripDebugMachineModule() : StripDebugMachineModule(OnlyDebugifiedDefault) {}
97 StripDebugMachineModule(bool OnlyDebugified)
98 : ModulePass(ID), OnlyDebugified(OnlyDebugified) {}
99
100 void getAnalysisUsage(AnalysisUsage &AU) const override {
101 AU.addRequired<MachineModuleInfoWrapperPass>();
102 AU.addPreserved<MachineModuleInfoWrapperPass>();
103 AU.setPreservesCFG();
104 }
105
106 static char ID; // Pass identification.
107
108protected:
109 bool OnlyDebugified;
110};
111char StripDebugMachineModule::ID = 0;
112
113} // end anonymous namespace
114
115INITIALIZE_PASS_BEGIN(StripDebugMachineModule, DEBUG_TYPE,
116 "Machine Strip Debug Module", false, false)
117INITIALIZE_PASS_END(StripDebugMachineModule, DEBUG_TYPE,
118 "Machine Strip Debug Module", false, false)
119
120ModulePass *llvm::createStripDebugMachineModuleLegacyPass(bool OnlyDebugified) {
121 return new StripDebugMachineModule(OnlyDebugified);
122}
123
124PreservedAnalyses StripDebugMachineModulePass::run(Module &M,
125 ModuleAnalysisManager &AM) {
126 FunctionAnalysisManager &FAM =
127 AM.getResult<FunctionAnalysisManagerModuleProxy>(IR&: M).getManager();
128 const bool Changed = stripDebugMachineModuleImpl(
129 M, OnlyDebugified: OnlyDebugifiedDefault, GetMF: [&FAM](Function &F) -> MachineFunction * {
130 return &FAM.getResult<MachineFunctionAnalysis>(IR&: F).getMF();
131 });
132 if (!Changed)
133 return PreservedAnalyses::all();
134
135 PreservedAnalyses PA;
136 PA.preserve<MachineModuleAnalysis>();
137 PA.preserve<FunctionAnalysisManagerModuleProxy>();
138 PA.preserveSet<CFGAnalyses>();
139 return PA;
140}
141