LLVM 22.0.0git
DebugSSAUpdater.h
Go to the documentation of this file.
1//===- DebugSSAUpdater.h - Debug SSA Update Tool ----------------*- 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// This file declares the DebugSSAUpdater class, which is used to evaluate the
10// live values of debug variables in IR. This uses SSA construction, treating
11// debug value records as definitions, to determine at each point in the program
12// which definition(s) are live at a given point. This is useful for analysis of
13// the state of debug variables, such as measuring the change in values of a
14// variable over time, or calculating coverage stats.
15//
16// NB: This is an expensive analysis that is generally not suitable for use in
17// LLVM passes, but may be useful for standalone tools.
18//
19//===----------------------------------------------------------------------===//
20
21#ifndef LLVM_TRANSFORMS_UTILS_DEBUGSSAUPDATER_H
22#define LLVM_TRANSFORMS_UTILS_DEBUGSSAUPDATER_H
23
25#include "llvm/IR/BasicBlock.h"
26#include "llvm/IR/CFG.h"
29#include "llvm/IR/Instruction.h"
30#include "llvm/IR/ValueHandle.h"
31#include "llvm/IR/ValueMap.h"
32#include <cstdint>
33
34namespace llvm {
35
36////////////////////////////////////////
37// SSAUpdater specialization classes
38
39class DbgSSAPhi;
40template <typename T> class SSAUpdaterTraits;
41
42/// A definition of a variable; can represent either a debug value, no
43/// definition (the variable has not yet been defined), or a phi value*.
44/// *Meaning multiple definitions that are live-in to a block from different
45/// predecessors, not a debug value that uses an IR PHINode.
48 bool IsUndef;
52
54 : Phi(nullptr), IsUndef(true), IsMemory(false), Locations(nullptr),
55 Expression(nullptr) {}
57 : Phi(nullptr), IsUndef(true), IsMemory(false), Locations(nullptr),
58 Expression(nullptr) {}
63 assert(!DVR->isDbgAssign() && "#dbg_assign not yet supported");
64 IsUndef = DVR->isKillLocation();
68 }
72
74 if (IsUndef && Other.IsUndef)
75 return true;
76 return std::tie(Phi, IsUndef, IsMemory, Locations, Expression) ==
77 std::tie(Other.Phi, Other.IsUndef, Other.IsMemory, Other.Locations,
78 Other.Expression);
79 }
80
81 operator bool() const { return !IsUndef; }
82 bool operator==(DbgValueDef Other) const { return agreesWith(Other); }
83 bool operator!=(DbgValueDef Other) const { return !agreesWith(Other); }
84
85 void print(raw_ostream &OS) const;
86};
87
88class DbgSSABlock;
89class DebugSSAUpdater;
90
91/// Represents the live-in definitions of a variable to a block with multiple
92/// predecessors.
93class DbgSSAPhi {
94public:
98
100 unsigned getNumIncomingValues() const { return IncomingValues.size(); }
102 return IncomingValues[Idx].first;
103 }
105 return IncomingValues[Idx].second;
106 }
108 IncomingValues.push_back({BB, DV});
109 }
110
111 void print(raw_ostream &OS) const;
112};
113
115 DV.print(OS);
116 return OS;
117}
119 PHI.print(OS);
120 return OS;
121}
122
123/// Thin wrapper around a block successor iterator.
143
144/// Thin wrapper around a block successor iterator.
164
166public:
170 /// List of PHIs in this block. There should only ever be one, but this needs
171 /// to be a list for the SSAUpdater.
173
176
180
184
188
192
196
200
201 /// SSAUpdater has requested a PHI: create that within this block record.
203 assert(PHIList.empty() &&
204 "Only one PHI should exist per-block per-variable");
205 PHIList.emplace_back(this);
206 return &PHIList.back();
207 }
208
209 /// SSAUpdater wishes to know what PHIs already exist in this block.
210 PHIListT &phis() { return PHIList; }
211};
212
213/// Class used to determine the live ranges of debug variables in IR using
214/// SSA construction (via the SSAUpdaterImpl class), used for analysis purposes.
216 friend class SSAUpdaterTraits<DebugSSAUpdater>;
217 using AvailableValsTy = DenseMap<DbgSSABlock *, DbgValueDef>;
218
219private:
220 /// This keeps track of which value to use on a per-block basis. When we
221 /// insert PHI nodes, we keep track of them here.
222 AvailableValsTy AV;
223
224 /// Pointer to an optionally-passed vector into which, if it is non-null,
225 /// the PHIs that describe ambiguous variable locations will be inserted.
226 SmallVectorImpl<DbgSSAPhi *> *InsertedPHIs;
227
229
230public:
231 /// If InsertedPHIs is specified, it will be filled
232 /// in with all PHI Nodes created by rewriting.
233 explicit DebugSSAUpdater(
234 SmallVectorImpl<DbgSSAPhi *> *InsertedPHIs = nullptr);
237
239 for (auto &Block : BlockMap)
240 delete Block.second;
241 }
242
243 void reset() {
244 for (auto &Block : BlockMap)
245 delete Block.second;
246
247 if (InsertedPHIs)
248 InsertedPHIs->clear();
249 BlockMap.clear();
250 }
251
252 void initialize();
253
254 /// For a given BB, create a wrapper block for it. Stores it in the
255 /// DebugSSAUpdater block map.
257 auto it = BlockMap.find(BB);
258 if (it == BlockMap.end()) {
259 BlockMap[BB] = new DbgSSABlock(*BB, *this);
260 it = BlockMap.find(BB);
261 }
262 return it->second;
263 }
264
265 /// Indicate that a rewritten value is available in the specified block
266 /// with the specified value.
268
269 /// Return true if the DebugSSAUpdater already has a value for the specified
270 /// block.
271 bool hasValueForBlock(DbgSSABlock *BB) const;
272
273 /// Return the value for the specified block if the DebugSSAUpdater has one,
274 /// otherwise return nullptr.
276
277 /// Construct SSA form, materializing a value that is live at the end
278 /// of the specified block.
280
281 /// Construct SSA form, materializing a value that is live in the
282 /// middle of the specified block.
283 ///
284 /// \c getValueInMiddleOfBlock is the same as \c GetValueAtEndOfBlock except
285 /// in one important case: if there is a definition of the rewritten value
286 /// after the 'use' in BB. Consider code like this:
287 ///
288 /// \code
289 /// X1 = ...
290 /// SomeBB:
291 /// use(X)
292 /// X2 = ...
293 /// br Cond, SomeBB, OutBB
294 /// \endcode
295 ///
296 /// In this case, there are two values (X1 and X2) added to the AvailableVals
297 /// set by the client of the rewriter, and those values are both live out of
298 /// their respective blocks. However, the use of X happens in the *middle* of
299 /// a block. Because of this, we need to insert a new PHI node in SomeBB to
300 /// merge the appropriate values, and this value isn't live out of the block.
302
303private:
304 DbgValueDef getValueAtEndOfBlockInternal(DbgSSABlock *BB);
305};
306
313
314/// Utility class used to store the names of SSA values after their owning
315/// modules have been destroyed. Values are added via \c addValue to receive a
316/// corresponding ID, which can then be used to retrieve the name of the SSA
317/// value via \c getName at any point. Adding the same value multiple times
318/// returns the same ID, making \c addValue idempotent.
320 struct Config : ValueMapConfig<Value *> {
321 enum { FollowRAUW = false };
322 };
323
324public:
327 std::string getName(ValueID ID) { return ValueIDToNameMap[ID]; }
328
329private:
330 DenseMap<ValueID, std::string> ValueIDToNameMap;
332 ValueID NextID = 0;
333};
334
335/// Utility class used to find and store the live debug ranges for variables in
336/// a module. This class uses the DebugSSAUpdater for each variable added with
337/// \c addVariable to find either a single-location value, e.g. #dbg_declare, or
338/// a set of live value ranges corresponding to the set of #dbg_value records.
341 OrigVariableValueRangeTable;
342 DenseMap<DebugVariableAggregate, DbgValueDef> OrigSingleLocVariableValueTable;
343
344public:
347 return OrigVariableValueRangeTable.contains(DVA) ||
348 OrigSingleLocVariableValueTable.contains(DVA);
349 }
351 return OrigSingleLocVariableValueTable.contains(DVA);
352 }
354 return OrigVariableValueRangeTable[DVA];
355 }
357 return OrigSingleLocVariableValueTable[DVA];
358 }
359
361};
362
363} // end namespace llvm
364
365#endif // LLVM_TRANSFORMS_UTILS_DEBUGSSAUPDATER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Rewrite undef for PHI
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
#define F(x, y, z)
Definition MD5.cpp:55
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
LLVM Basic Block Representation.
Definition BasicBlock.h:62
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
DWARF expression.
Thin wrapper around a block successor iterator.
DbgSSABlockPredIterator(pred_iterator PredIt, DebugSSAUpdater &Updater)
bool operator!=(const DbgSSABlockPredIterator &OtherIt) const
DbgSSABlockPredIterator & operator++()
Thin wrapper around a block successor iterator.
DbgSSABlockSuccIterator(succ_iterator SuccIt, DebugSSAUpdater &Updater)
bool operator!=(const DbgSSABlockSuccIterator &OtherIt) const
DbgSSABlockSuccIterator & operator++()
DebugSSAUpdater & Updater
iterator_range< DbgSSABlockPredIterator > predecessors()
DbgSSABlockSuccIterator succ_end()
SmallVector< DbgSSAPhi, 1 > PHIListT
DbgSSABlockPredIterator pred_end()
DbgSSABlockPredIterator pred_begin()
DbgSSABlockSuccIterator succ_begin()
PHIListT & phis()
SSAUpdater wishes to know what PHIs already exist in this block.
PHIListT PHIList
List of PHIs in this block.
DbgSSAPhi * newPHI()
SSAUpdater has requested a PHI: create that within this block record.
iterator_range< DbgSSABlockSuccIterator > successors()
DbgSSABlock(BasicBlock &BB, DebugSSAUpdater &Updater)
Represents the live-in definitions of a variable to a block with multiple predecessors.
SmallVector< std::pair< DbgSSABlock *, DbgValueDef >, 4 > IncomingValues
void addIncoming(DbgSSABlock *BB, DbgValueDef DV)
DbgSSABlock * getParent()
DbgSSAPhi(DbgSSABlock *ParentBlock)
void print(raw_ostream &OS) const
DbgSSABlock * ParentBlock
DbgValueDef getIncomingValue(size_t Idx)
unsigned getNumIncomingValues() const
DbgSSABlock * getIncomingBlock(size_t Idx)
Utility class used to find and store the live debug ranges for variables in a module.
DbgValueDef getSingleLoc(DebugVariableAggregate DVA)
ArrayRef< DbgRangeEntry > getVariableRanges(DebugVariableAggregate DVA)
void printValues(DebugVariableAggregate DVA, raw_ostream &OS)
void addVariable(Function *F, DebugVariableAggregate DVA)
bool hasSingleLocEntry(DebugVariableAggregate DVA) const
bool hasVariableEntry(DebugVariableAggregate DVA) const
Record of a variable value-assignment, aka a non instruction representation of the dbg....
LLVM_ABI bool isKillLocation() const
bool isAddressOfVariable() const
Does this describe the address of a local variable.
DIExpression * getExpression() const
Metadata * getRawLocation() const
Returns the metadata operand for the first location description.
Class used to determine the live ranges of debug variables in IR using SSA construction (via the SSAU...
DebugSSAUpdater(SmallVectorImpl< DbgSSAPhi * > *InsertedPHIs=nullptr)
If InsertedPHIs is specified, it will be filled in with all PHI Nodes created by rewriting.
DebugSSAUpdater & operator=(const DebugSSAUpdater &)=delete
DbgValueDef findValueForBlock(DbgSSABlock *BB) const
Return the value for the specified block if the DebugSSAUpdater has one, otherwise return nullptr.
DebugSSAUpdater(const DebugSSAUpdater &)=delete
void addAvailableValue(DbgSSABlock *BB, DbgValueDef DV)
Indicate that a rewritten value is available in the specified block with the specified value.
DbgValueDef getValueAtEndOfBlock(DbgSSABlock *BB)
Construct SSA form, materializing a value that is live at the end of the specified block.
DbgSSABlock * getDbgSSABlock(BasicBlock *BB)
For a given BB, create a wrapper block for it.
DbgValueDef getValueInMiddleOfBlock(DbgSSABlock *BB)
Construct SSA form, materializing a value that is live in the middle of the specified block.
bool hasValueForBlock(DbgSSABlock *BB) const
Return true if the DebugSSAUpdater already has a value for the specified block.
Identifies a unique instance of a whole variable (discards/ignores fragment information).
Root of the metadata hierarchy.
Definition Metadata.h:63
Utility class used to store the names of SSA values after their owning modules have been destroyed.
std::string getName(ValueID ID)
ValueID addValue(Value *V)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
See the file comment.
Definition ValueMap.h:84
LLVM Value Representation.
Definition Value.h:75
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
auto pred_end(const MachineBasicBlock *BB)
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
@ Other
Any other memory.
Definition ModRef.h:68
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
PredIterator< BasicBlock, Value::user_iterator > pred_iterator
Definition CFG.h:105
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
auto pred_begin(const MachineBasicBlock *BB)
SuccIterator< Instruction, BasicBlock > succ_iterator
Definition CFG.h:243
BasicBlock::iterator End
BasicBlock::iterator Start
A definition of a variable; can represent either a debug value, no definition (the variable has not y...
DbgValueDef(DbgVariableRecord *DVR)
DbgValueDef(DbgSSAPhi *Phi)
bool operator!=(DbgValueDef Other) const
void print(raw_ostream &OS) const
DIExpression * Expression
bool operator==(DbgValueDef Other) const
DbgValueDef(bool IsMemory, Metadata *Locations, DIExpression *Expression)
bool agreesWith(DbgValueDef Other) const
This class defines the default behavior for configurable aspects of ValueMap<>.
Definition ValueMap.h:56