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 "../DirectX.h"
10#include "DXILAttributes.h"
11#include "llvm/ADT/DenseSet.h"
14#include "llvm/IR/Attributes.h"
15#include "llvm/IR/DebugInfo.h"
17#include "llvm/IR/Module.h"
18#include "llvm/Pass.h"
21
22#define DEBUG_TYPE "dx-debug-info"
23
24using namespace llvm;
25using namespace llvm::dxil;
26
27static bool lowerDXILDebugInfo(Module &M) {
28 // Convert debug markers back to dbg.value intrinsics. Record whether any
29 // changes were made.
30 bool Modified = M.convertFromNewDbgValues();
32 DIF.processModule(M);
33
34 {
35 Function *DVDecl = nullptr;
36
37 // Logically these should be variables in the
38 // for (BasicBlock &BB : F) loop.
39 // They are defined here and cleared at the start of the loop body to avoid
40 // the cost of deconstruction and reconstruction.
42 DbgValues;
44 std::pair<Instruction *, DbgValueInst *>>
45 DbgValueFragments;
46 // Likewise, logically, this should be a variable in the
47 // for (Function &F : M) loop.
48 DenseSet<DILocalVariable *> DbgVariablesSeen;
49
50 const AttributeMask &AttrMask = getNonDXILAttributeMask();
51
52 for (Function &F : M) {
53 F.removeFnAttrs(AttrMask);
54 F.removeRetAttrs(AttrMask);
55 for (unsigned ArgNo = 0; ArgNo != F.arg_size(); ++ArgNo)
56 F.removeParamAttrs(ArgNo, AttrMask);
57
58 bool IsEntryBlock = true;
59 DbgVariablesSeen.clear();
60 for (BasicBlock &BB : F) {
61 Instruction *NextNonDebugInst = nullptr;
62 DbgValues.clear();
63 DbgValueFragments.clear();
65 I.eraseMetadataIf([](unsigned KindID, MDNode *) {
66 return KindID == LLVMContext::MD_DIAssignID;
67 });
69 NextNonDebugInst = &I;
70 continue;
71 }
72 if (auto *DL = dyn_cast<DbgLabelInst>(&I)) {
73 DL->eraseFromParent();
74 Modified = true;
75 continue;
76 }
77 // Process both llvm.dbg.value and llvm.dbg.assign here. We convert
78 // llvm.dbg.assign to llvm.dbg.value by dropping the last arguments,
79 // and remove redundant llvm.dbg.values.
80 if (auto *DV = dyn_cast<DbgValueInst>(&I)) {
81 // Keep track of the last location where we saw any debug value for
82 // a variable.
83 DILocalVariable *V = DV->getVariable();
84 DIExpression *E = DV->getExpression();
85 // If this is already an llvm.dbg.value instruction that we can
86 // keep, just do that, otherwise convert it.
87 auto *Val = cast<MetadataAsValue>(DV->getArgOperand(0));
88 auto *Var = cast<MetadataAsValue>(DV->getArgOperand(1));
89 auto *Expr = cast<MetadataAsValue>(DV->getArgOperand(2));
90 bool Replace = DV->getIntrinsicID() != Intrinsic::dbg_value;
91 if (!isa<ValueAsMetadata>(Val->getMetadata())) {
92 // This may be a DIArgList which is not supported in LLVM 3.7. If
93 // it is, we cannot record the new value, but we still need to
94 // kill any old value. Do this by poison. We do not know the
95 // correct type to use here and arbitrarily use i1.
96 // This should never be anything other than ValueAsMetadata or
97 // DIArgList, but in manually constructed LLVM IR, it can be.
98 // Handle this gracefully by also replacing it with poison.
101 Type::getInt1Ty(M.getContext()))));
102 E = DIExpression::get(M.getContext(), {});
103 Expr = MetadataAsValue::get(M.getContext(), E);
104 Replace = true;
105 }
106 std::pair<Instruction *, DbgValueInst *> &DbgValue = DbgValues[V];
107 std::pair<Instruction *, DbgValueInst *> &DbgValueFragment =
108 DbgValueFragments[{V, E}];
109 if (DbgValue.second) {
110 // If there is a later value of the same fragment at the same
111 // location, this value is redundant.
112 if (DbgValueFragment.first == NextNonDebugInst) {
113 DV->eraseFromParent();
114 Modified = true;
115 continue;
116 }
117 // If there is a later identical value of the same fragment at a
118 // later point, and there have been no intervening values of
119 // different possibly overlapping fragments, that later value is
120 // redundant.
121 if (DbgValueFragment.second &&
122 DbgValueFragment.second == DbgValue.second &&
123 DbgValueFragment.second->getValue() == DV->getValue()) {
124 DbgValue.second->eraseFromParent();
125 Modified = true;
126 }
127 }
128 DbgValueInst *NewDV;
129 if (Replace) {
130 if (!DVDecl) {
131 DVDecl =
132 Intrinsic::getOrInsertDeclaration(&M, Intrinsic::dbg_value);
133 AttributeMask AM;
134 for (Attribute A : DVDecl->getAttributes().getFnAttrs())
135 if (A.isStringAttribute() ||
136 (A.getKindAsEnum() != Attribute::NoUnwind &&
137 A.getKindAsEnum() != Attribute::Memory))
138 AM.addAttribute(A);
139 DVDecl->removeFnAttrs(AM);
140 }
141 NewDV = cast<DbgValueInst>(
142 CallInst::Create(DVDecl, {Val, Var, Expr}, {}, "",
143 std::next(DV->getIterator())));
144 NewDV->setTailCall();
145 NewDV->setDebugLoc(DV->getDebugLoc());
146 DV->eraseFromParent();
147 Modified = true;
148 } else {
149 NewDV = DV;
150 }
151 DbgValue = DbgValueFragment = {NextNonDebugInst, NewDV};
152 continue;
153 }
154 }
155 // If this is the entry block, if the first value we see for each debug
156 // value is undef, it is redundant.
157 if (IsEntryBlock) {
158 for (Instruction &I : make_early_inc_range(BB)) {
159 auto *DV = dyn_cast<DbgValueInst>(&I);
160 if (!DV || DbgVariablesSeen.contains(DV->getVariable()))
161 continue;
162 if (isa<UndefValue>(DV->getValue())) {
163 DV->eraseFromParent();
164 Modified = true;
165 continue;
166 }
167 DbgVariablesSeen.insert(DV->getVariable());
168 }
169 }
170 IsEntryBlock = false;
171 }
172 }
173 }
174
175 for (DISubprogram *SP : DIF.subprograms()) {
176 if (MDTuple *RN = cast_or_null<MDTuple>(SP->getRawRetainedNodes())) {
177 SmallVector<Metadata *> MDs(RN->operands());
178 MDs.erase(std::remove_if(MDs.begin(), MDs.end(),
179 [](Metadata *M) { return isa<DILabel>(M); }),
180 MDs.end());
181 SP->replaceRetainedNodes(MDTuple::get(M.getContext(), MDs));
182 Modified = true;
183 }
184 }
185
186 return Modified;
187}
188
193
194namespace {
195class DXILDebugInfoLegacy : public ModulePass {
196public:
197 static char ID;
198
199 DXILDebugInfoLegacy() : ModulePass(ID) {}
200
201 bool runOnModule(Module &M) override { return lowerDXILDebugInfo(M); }
202
203 void getAnalysisUsage(AnalysisUsage &AU) const override {
204 AU.setPreservesAll();
205 }
206};
207} // namespace
208
209char DXILDebugInfoLegacy::ID = 0;
210
211INITIALIZE_PASS(DXILDebugInfoLegacy, DEBUG_TYPE, "DXIL Debug Info", false,
212 false)
213
215 return new DXILDebugInfoLegacy();
216}
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.
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:548
DWARF expression.
Subprogram description. Uses SubclassData1.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
This represents the llvm.dbg.value instruction.
Utility to find all debug info in a module.
Definition DebugInfo.h:102
LLVM_ABI void processModule(const Module &M)
Process entire module and collect debug info anchors.
iterator_range< subprogram_iterator > subprograms() const
Definition DebugInfo.h:150
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
void removeFnAttrs(const AttributeMask &Attrs)
Definition Function.cpp:697
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:1081
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
Tuple of metadata.
Definition Metadata.h:1496
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1525
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:107
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:253
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:296
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
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:649
auto cast_or_null(const Y &Val)
Definition Casting.h:714
ModulePass * createDXILDebugInfoLegacyPass()
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
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