LLVM 24.0.0git
DXILDebugInfo.cpp
Go to the documentation of this file.
1//===--- DXILDebugInfo.cpp - analysis&lowering for Debug info -*- C++ -*- ---=//
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#include "DXILDebugInfo.h"
10#include "../DirectX.h"
11#include "DXILAttributes.h"
12#include "llvm/ADT/DenseSet.h"
15#include "llvm/IR/Attributes.h"
16#include "llvm/IR/DebugInfo.h"
18#include "llvm/IR/Module.h"
19#include "llvm/Pass.h"
22
23#define DEBUG_TYPE "dx-debug-info"
24
25using namespace llvm;
26using namespace llvm::dxil;
27
28static bool lowerDXILDebugInfo(Module &M) {
29 // Convert debug markers back to dbg.value intrinsics. Record whether any
30 // changes were made.
31 bool Modified = M.convertFromNewDbgValues();
33 DIF.processModule(M);
34
35 {
36 Function *DVDecl = nullptr;
37
38 // Logically these should be variables in the
39 // for (BasicBlock &BB : F) loop.
40 // They are defined here and cleared at the start of the loop body to avoid
41 // the cost of deconstruction and reconstruction.
43 DbgValues;
45 std::pair<Instruction *, DbgValueInst *>>
46 DbgValueFragments;
47 // Likewise, logically, this should be a variable in the
48 // for (Function &F : M) loop.
49 DenseSet<DILocalVariable *> DbgVariablesSeen;
50
51 const AttributeMask &AttrMask = getNonDXILAttributeMask();
52
53 for (Function &F : M) {
54 F.removeFnAttrs(AttrMask);
55 F.removeRetAttrs(AttrMask);
56 for (unsigned ArgNo = 0; ArgNo != F.arg_size(); ++ArgNo)
57 F.removeParamAttrs(ArgNo, AttrMask);
58
59 bool IsEntryBlock = true;
60 DbgVariablesSeen.clear();
61 for (BasicBlock &BB : F) {
62 Instruction *NextNonDebugInst = nullptr;
63 DbgValues.clear();
64 DbgValueFragments.clear();
66 I.eraseMetadataIf([](unsigned KindID, MDNode *) {
67 return KindID == LLVMContext::MD_DIAssignID;
68 });
70 NextNonDebugInst = &I;
71 continue;
72 }
73 if (auto *DL = dyn_cast<DbgLabelInst>(&I)) {
74 DL->eraseFromParent();
75 Modified = true;
76 continue;
77 }
78 // Process both llvm.dbg.value and llvm.dbg.assign here. We convert
79 // llvm.dbg.assign to llvm.dbg.value by dropping the last arguments,
80 // and remove redundant llvm.dbg.values.
81 if (auto *DV = dyn_cast<DbgValueInst>(&I)) {
82 // Keep track of the last location where we saw any debug value for
83 // a variable.
84 DILocalVariable *V = DV->getVariable();
85 DIExpression *E = DV->getExpression();
86 // If this is already an llvm.dbg.value instruction that we can
87 // keep, just do that, otherwise convert it.
88 auto *Val = cast<MetadataAsValue>(DV->getArgOperand(0));
89 auto *Var = cast<MetadataAsValue>(DV->getArgOperand(1));
90 auto *Expr = cast<MetadataAsValue>(DV->getArgOperand(2));
91 bool Replace = DV->getIntrinsicID() != Intrinsic::dbg_value;
92 if (!isa<ValueAsMetadata>(Val->getMetadata())) {
93 // This may be a DIArgList which is not supported in LLVM 3.7. If
94 // it is, we cannot record the new value, but we still need to
95 // kill any old value. Do this by poison. We do not know the
96 // correct type to use here and arbitrarily use i1.
97 // This should never be anything other than ValueAsMetadata or
98 // DIArgList, but in manually constructed LLVM IR, it can be.
99 // Handle this gracefully by also replacing it with poison.
102 Type::getInt1Ty(M.getContext()))));
103 E = DIExpression::get(M.getContext(), {});
104 Expr = MetadataAsValue::get(M.getContext(), E);
105 Replace = true;
106 }
107 std::pair<Instruction *, DbgValueInst *> &DbgValue = DbgValues[V];
108 std::pair<Instruction *, DbgValueInst *> &DbgValueFragment =
109 DbgValueFragments[{V, E}];
110 if (DbgValue.second) {
111 // If there is a later value of the same fragment at the same
112 // location, this value is redundant.
113 if (DbgValueFragment.first == NextNonDebugInst) {
114 DV->eraseFromParent();
115 Modified = true;
116 continue;
117 }
118 // If there is a later identical value of the same fragment at a
119 // later point, and there have been no intervening values of
120 // different possibly overlapping fragments, that later value is
121 // redundant.
122 if (DbgValueFragment.second &&
123 DbgValueFragment.second == DbgValue.second &&
124 DbgValueFragment.second->getValue() == DV->getValue()) {
125 DbgValue.second->eraseFromParent();
126 Modified = true;
127 }
128 }
129 DbgValueInst *NewDV;
130 if (Replace) {
131 if (!DVDecl) {
132 DVDecl =
133 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::dbg_value);
134 AttributeMask AM;
135 for (Attribute A : DVDecl->getAttributes().getFnAttrs())
136 if (A.isStringAttribute() ||
137 (A.getKindAsEnum() != Attribute::NoUnwind &&
138 A.getKindAsEnum() != Attribute::Memory))
139 AM.addAttribute(A);
140 DVDecl->removeFnAttrs(AM);
141 }
142 NewDV = cast<DbgValueInst>(
143 CallInst::Create(DVDecl, {Val, Var, Expr}, {}, "",
144 std::next(DV->getIterator())));
145 NewDV->setTailCall();
146 NewDV->setDebugLoc(DV->getDebugLoc());
147 DV->eraseFromParent();
148 Modified = true;
149 } else {
150 NewDV = DV;
151 }
152 DbgValue = DbgValueFragment = {NextNonDebugInst, NewDV};
153 continue;
154 }
155 }
156 // If this is the entry block, if the first value we see for each debug
157 // value is undef, it is redundant.
158 if (IsEntryBlock) {
159 for (Instruction &I : make_early_inc_range(BB)) {
160 auto *DV = dyn_cast<DbgValueInst>(&I);
161 if (!DV || DbgVariablesSeen.contains(DV->getVariable()))
162 continue;
163 if (isa<UndefValue>(DV->getValue())) {
164 DV->eraseFromParent();
165 Modified = true;
166 continue;
167 }
168 DbgVariablesSeen.insert(DV->getVariable());
169 }
170 }
171 IsEntryBlock = false;
172 }
173 }
174 }
175
176 for (DISubprogram *SP : DIF.subprograms()) {
177 if (MDTuple *RN = cast_or_null<MDTuple>(SP->getRawRetainedNodes())) {
178 SmallVector<Metadata *> MDs(RN->operands());
179 MDs.erase(std::remove_if(MDs.begin(), MDs.end(),
180 [](Metadata *M) { return isa<DILabel>(M); }),
181 MDs.end());
182 SP->replaceRetainedNodes(MDTuple::get(M.getContext(), MDs));
183 Modified = true;
184 }
185 }
186
187 return Modified;
188}
189
194
195namespace {
196class DXILDebugInfoLegacy : public ModulePass {
197public:
198 static char ID;
199
200 DXILDebugInfoLegacy() : ModulePass(ID) {}
201
202 bool runOnModule(Module &M) override { return lowerDXILDebugInfo(M); }
203
204 void getAnalysisUsage(AnalysisUsage &AU) const override {
205 AU.setPreservesAll();
206 }
207};
208} // namespace
209
210char DXILDebugInfoLegacy::ID = 0;
211
212INITIALIZE_PASS(DXILDebugInfoLegacy, DEBUG_TYPE, "DXIL Debug Info", false,
213 false)
214
216 return new DXILDebugInfoLegacy();
217}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool lowerDXILDebugInfo(Module &M)
This file defines the DenseSet and SmallDenseSet classes.
This file contains constants used for implementing Dwarf debug support.
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
Class recording the (high level) value of a variable.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
This class stores enough information to efficiently remove some attributes from an existing AttrBuild...
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:106
LLVM Basic Block Representation.
Definition BasicBlock.h:62
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
void setTailCall(bool IsTc=true)
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:537
DWARF expression.
Subprogram description. Uses SubclassData1.
This represents the llvm.dbg.value instruction.
Utility to find all debug info in a module.
Definition DebugInfo.h:105
LLVM_ABI void processModule(const Module &M)
Process entire module and collect debug info anchors.
iterator_range< subprogram_iterator > subprograms() const
Definition DebugInfo.h:153
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
void removeFnAttrs(const AttributeMask &Attrs)
Definition Function.cpp:696
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition Function.h:329
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Metadata node.
Definition Metadata.h:1069
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1567
Tuple of metadata.
Definition Metadata.h:1484
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1513
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:111
Root of the metadata hierarchy.
Definition Metadata.h:64
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
iterator erase(const_iterator CI)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:182
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
const AttributeMask & getNonDXILAttributeMask()
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
auto cast_or_null(const Y &Val)
Definition Casting.h:714
ModulePass * createDXILDebugInfoLegacyPass()
Pass to downgrade debug information to forms supported by DXIL.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39