LLVM 23.0.0git
ReachingDefAnalysis.h
Go to the documentation of this file.
1//==--- llvm/CodeGen/ReachingDefAnalysis.h - Reaching Def Analysis -*- 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/// \file Reaching Defs Analysis pass.
10///
11/// This pass tracks for each instruction what is the "closest" reaching def of
12/// a given register. It is used by BreakFalseDeps (for clearance calculation)
13/// and ExecutionDomainFix (for arbitrating conflicting domains).
14///
15/// Note that this is different from the usual definition notion of liveness.
16/// The CPU doesn't care whether or not we consider a register killed.
17///
18//
19//===----------------------------------------------------------------------===//
20
21#ifndef LLVM_CODEGEN_REACHINGDEFANALYSIS_H
22#define LLVM_CODEGEN_REACHINGDEFANALYSIS_H
23
24#include "llvm/ADT/DenseMap.h"
31
32namespace llvm {
33
35class MachineInstr;
36
37/// Thin wrapper around "int" used to store reaching definitions,
38/// using an encoding that makes it compatible with TinyPtrVector.
39/// The 0th LSB is forced zero (and will be used for pointer union tagging),
40/// The 1st LSB is forced one (to make sure the value is non-zero).
41class ReachingDef {
42 uintptr_t Encoded;
43 friend struct PointerLikeTypeTraits<ReachingDef>;
44 explicit ReachingDef(uintptr_t Encoded) : Encoded(Encoded) {}
45
46public:
47 ReachingDef(std::nullptr_t) : Encoded(0) {}
48 ReachingDef(int Instr) : Encoded(((uintptr_t) Instr << 2) | 2) {}
49 operator int() const { return ((int) Encoded) >> 2; }
50};
51
52template<>
54 static constexpr int NumLowBitsAvailable = 1;
55
56 static inline void *getAsVoidPointer(const ReachingDef &RD) {
57 return reinterpret_cast<void *>(RD.Encoded);
58 }
59
60 static inline ReachingDef getFromVoidPointer(void *P) {
61 return ReachingDef(reinterpret_cast<uintptr_t>(P));
62 }
63
64 static inline ReachingDef getFromVoidPointer(const void *P) {
65 return ReachingDef(reinterpret_cast<uintptr_t>(P));
66 }
67};
68
69// The storage for all reaching definitions.
71public:
72 void init(unsigned NumBlockIDs) { AllReachingDefs.resize(NumBlockIDs); }
73
74 unsigned numBlockIDs() const { return AllReachingDefs.size(); }
75
76 void startBasicBlock(unsigned MBBNumber, unsigned NumRegUnits) {
77 AllReachingDefs[MBBNumber].resize(NumRegUnits);
78 }
79
80 void append(unsigned MBBNumber, MCRegUnit Unit, int Def) {
81 AllReachingDefs[MBBNumber][static_cast<unsigned>(Unit)].push_back(Def);
82 }
83
84 void prepend(unsigned MBBNumber, MCRegUnit Unit, int Def) {
85 auto &Defs = AllReachingDefs[MBBNumber][static_cast<unsigned>(Unit)];
86 Defs.insert(Defs.begin(), Def);
87 }
88
89 void replaceFront(unsigned MBBNumber, MCRegUnit Unit, int Def) {
90 assert(!AllReachingDefs[MBBNumber][static_cast<unsigned>(Unit)].empty());
91 *AllReachingDefs[MBBNumber][static_cast<unsigned>(Unit)].begin() = Def;
92 }
93
94 void clear() { AllReachingDefs.clear(); }
95
96 ArrayRef<ReachingDef> defs(unsigned MBBNumber, MCRegUnit Unit) const {
97 if (AllReachingDefs[MBBNumber].empty())
98 // Block IDs are not necessarily dense.
99 return ArrayRef<ReachingDef>();
100 return AllReachingDefs[MBBNumber][static_cast<unsigned>(Unit)];
101 }
102
103private:
104 /// All reaching defs of a given RegUnit for a given MBB.
105 using MBBRegUnitDefs = TinyPtrVector<ReachingDef>;
106 /// All reaching defs of all reg units for a given MBB
107 using MBBDefsInfo = std::vector<MBBRegUnitDefs>;
108
109 /// All reaching defs of all reg units for all MBBs
110 SmallVector<MBBDefsInfo, 4> AllReachingDefs;
111};
112
113/// This class provides the reaching def analysis.
115private:
116 MachineFunction *MF = nullptr;
117 const TargetRegisterInfo *TRI = nullptr;
118 const TargetInstrInfo *TII = nullptr;
119 LoopTraversal::TraversalOrder TraversedMBBOrder;
120 unsigned NumRegUnits = 0;
121 unsigned NumStackObjects = 0;
122 int ObjectIndexBegin = 0;
123 /// Instruction that defined each register, relative to the beginning of the
124 /// current basic block. When a LiveRegsDefInfo is used to represent a
125 /// live-out register, this value is relative to the end of the basic block,
126 /// so it will be a negative number.
127 using LiveRegsDefInfo = std::vector<int>;
128 LiveRegsDefInfo LiveRegs;
129
130 /// Keeps clearance information for all registers. Note that this
131 /// is different from the usual definition notion of liveness. The CPU
132 /// doesn't care whether or not we consider a register killed.
133 using OutRegsInfoMap = SmallVector<LiveRegsDefInfo, 4>;
134 OutRegsInfoMap MBBOutRegsInfos;
135
136 /// Current instruction number.
137 /// The first instruction in each basic block is 0.
138 int CurInstr = -1;
139
140 /// Maps instructions to their instruction Ids, relative to the beginning of
141 /// their basic blocks.
143
144 MBBReachingDefsInfo MBBReachingDefs;
145
146 /// MBBFrameObjsReachingDefs[{i, j}] is a list of instruction indices
147 /// (relative to begining of MBB i) that define frame index j in MBB i. This
148 /// is used in answering reaching definition queries.
149 using MBBFrameObjsReachingDefsInfo =
151 MBBFrameObjsReachingDefsInfo MBBFrameObjsReachingDefs;
152
153 /// Default values are 'nothing happened a long time ago'.
154 static constexpr int ReachingDefDefaultVal = -(1 << 21);
155 /// Special values for function live-ins.
156 static constexpr int FunctionLiveInMarker = -1;
157
158 using InstSet = SmallPtrSetImpl<MachineInstr*>;
160
161public:
165 /// Handle invalidation explicitly.
167 MachineFunctionAnalysisManager::Invalidator &);
168
169 void run(MachineFunction &mf);
170 void print(raw_ostream &OS);
171 void releaseMemory();
172
173 /// Re-run the analysis.
174 void reset();
175
176 /// Initialize data structures.
177 void init();
178
179 /// Traverse the machine function, mapping definitions.
180 void traverse();
181
182 /// Provides the instruction id of the closest reaching def instruction of
183 /// Reg that reaches MI, relative to the begining of MI's basic block.
184 /// Note that Reg may represent a stack slot.
186
187 /// Return whether A and B use the same def of Reg.
189
190 /// Return whether the reaching def for MI also is live out of its parent
191 /// block.
193
194 /// Return the local MI that produces the live out value for Reg, or
195 /// nullptr for a non-live out or non-local def.
197 Register Reg) const;
198
199 /// If a single MachineInstr creates the reaching definition, then return it.
200 /// Otherwise return null.
202
203 /// If a single MachineInstr creates the reaching definition, for MIs operand
204 /// at Idx, then return it. Otherwise return null.
205 MachineInstr *getMIOperand(MachineInstr *MI, unsigned Idx) const;
206
207 /// If a single MachineInstr creates the reaching definition, for MIs MO,
208 /// then return it. Otherwise return null.
210
211 /// Provide whether the register has been defined in the same basic block as,
212 /// and before, MI.
214
215 /// Return whether the given register is used after MI, whether it's a local
216 /// use or a live out.
218
219 /// Return whether the given register is defined after MI.
221
222 /// Provides the clearance - the number of instructions since the closest
223 /// reaching def instuction of Reg that reaches MI.
225
226 /// Provides the uses, in the same block as MI, of register that MI defines.
227 /// This does not consider live-outs.
229 InstSet &Uses) const;
230
231 /// Search MBB for a definition of Reg and insert it into Defs. If no
232 /// definition is found, recursively search the predecessor blocks for them.
233 void getLiveOuts(MachineBasicBlock *MBB, Register Reg, InstSet &Defs,
234 BlockSet &VisitedBBs) const;
235 void getLiveOuts(MachineBasicBlock *MBB, Register Reg, InstSet &Defs) const;
236
237 /// For the given block, collect the instructions that use the live-in
238 /// value of the provided register. Return whether the value is still
239 /// live on exit.
240 bool getLiveInUses(MachineBasicBlock *MBB, Register Reg, InstSet &Uses) const;
241
242 /// Collect the users of the value stored in Reg, which is defined
243 /// by MI.
244 void getGlobalUses(MachineInstr *MI, Register Reg, InstSet &Uses) const;
245
246 /// Collect all possible definitions of the value stored in Reg, which is
247 /// used by MI.
249 InstSet &Defs) const;
250
251 /// Return whether From can be moved forwards to just before To.
252 bool isSafeToMoveForwards(MachineInstr *From, MachineInstr *To) const;
253
254 /// Return whether From can be moved backwards to just after To.
255 bool isSafeToMoveBackwards(MachineInstr *From, MachineInstr *To) const;
256
257 /// Assuming MI is dead, recursively search the incoming operands which are
258 /// killed by MI and collect those that would become dead.
259 void collectKilledOperands(MachineInstr *MI, InstSet &Dead) const;
260
261 /// Return whether removing this instruction will have no effect on the
262 /// program, returning the redundant use-def chain.
263 bool isSafeToRemove(MachineInstr *MI, InstSet &ToRemove) const;
264
265 /// Return whether removing this instruction will have no effect on the
266 /// program, ignoring the possible effects on some instructions, returning
267 /// the redundant use-def chain.
268 bool isSafeToRemove(MachineInstr *MI, InstSet &ToRemove,
269 InstSet &Ignore) const;
270
271 /// Return whether a MachineInstr could be inserted at MI and safely define
272 /// the given register without affecting the program.
274
275 /// Return whether a MachineInstr could be inserted at MI and safely define
276 /// the given register without affecting the program, ignoring any effects
277 /// on the provided instructions.
278 bool isSafeToDefRegAt(MachineInstr *MI, Register Reg, InstSet &Ignore) const;
279
280private:
281 /// Set up LiveRegs by merging predecessor live-out values.
282 void enterBasicBlock(MachineBasicBlock *MBB);
283
284 /// Update live-out values.
285 void leaveBasicBlock(MachineBasicBlock *MBB);
286
287 /// Process he given basic block.
288 void processBasicBlock(const LoopTraversal::TraversedMBBInfo &TraversedMBB);
289
290 /// Process block that is part of a loop again.
291 void reprocessBasicBlock(MachineBasicBlock *MBB);
292
293 /// Update def-ages for registers defined by MI.
294 /// Also break dependencies on partial defs and undef uses.
295 void processDefs(MachineInstr *);
296
297 /// Utility function for isSafeToMoveForwards/Backwards.
298 template<typename Iterator>
299 bool isSafeToMove(MachineInstr *From, MachineInstr *To) const;
300
301 /// Return whether removing this instruction will have no effect on the
302 /// program, ignoring the possible effects on some instructions, returning
303 /// the redundant use-def chain.
304 bool isSafeToRemove(MachineInstr *MI, InstSet &Visited,
305 InstSet &ToRemove, InstSet &Ignore) const;
306
307 /// Provides the MI, from the given block, corresponding to the Id or a
308 /// nullptr if the id does not refer to the block.
309 MachineInstr *getInstFromId(MachineBasicBlock *MBB, int InstId) const;
310
311 /// Provides the instruction of the closest reaching def instruction of
312 /// Reg that reaches MI, relative to the begining of MI's basic block.
313 /// Note that Reg may represent a stack slot.
314 MachineInstr *getReachingLocalMIDef(MachineInstr *MI, Register Reg) const;
315};
316
317class ReachingDefAnalysis : public AnalysisInfoMixin<ReachingDefAnalysis> {
319 static AnalysisKey Key;
320
321public:
323
325};
326
327/// Printer pass for the \c ReachingDefInfo results.
328class ReachingDefPrinterPass : public PassInfoMixin<ReachingDefPrinterPass> {
329 raw_ostream &OS;
330
331public:
332 explicit ReachingDefPrinterPass(raw_ostream &OS) : OS(OS) {}
333
336
337 static bool isRequired() { return true; }
338};
339
341 ReachingDefInfo RDI;
342
343public:
344 static char ID;
345
347
348 void getAnalysisUsage(AnalysisUsage &AU) const override;
350 bool runOnMachineFunction(MachineFunction &F) override;
351 void releaseMemory() override { RDI.releaseMemory(); }
352
353 ReachingDefInfo &getRDI() { return RDI; }
354 const ReachingDefInfo &getRDI() const { return RDI; }
355};
356
357} // namespace llvm
358
359#endif // LLVM_CODEGEN_REACHINGDEFANALYSIS_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet InstSet & Ignore
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock & MBB
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
Register Reg
#define P(N)
Remove Loads Into Fake Uses
This file defines the SmallVector class.
Represent the analysis usage information of a pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
SmallVector< TraversedMBBInfo, 4 > TraversalOrder
Identifies basic blocks that are part of loops and should to be visited twice and returns efficient t...
void prepend(unsigned MBBNumber, MCRegUnit Unit, int Def)
void replaceFront(unsigned MBBNumber, MCRegUnit Unit, int Def)
ArrayRef< ReachingDef > defs(unsigned MBBNumber, MCRegUnit Unit) const
void init(unsigned NumBlockIDs)
void append(unsigned MBBNumber, MCRegUnit Unit, int Def)
void startBasicBlock(unsigned MBBNumber, unsigned NumRegUnits)
Properties which a MachineFunction may have at a given point in time.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool runOnMachineFunction(MachineFunction &F) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const ReachingDefInfo & getRDI() const
MachineFunctionProperties getRequiredProperties() const override
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
This class provides the reaching def analysis.
MachineInstr * getUniqueReachingMIDef(MachineInstr *MI, Register Reg) const
If a single MachineInstr creates the reaching definition, then return it.
bool isReachingDefLiveOut(MachineInstr *MI, Register Reg) const
Return whether the reaching def for MI also is live out of its parent block.
bool isSafeToMoveForwards(MachineInstr *From, MachineInstr *To) const
Return whether From can be moved forwards to just before To.
int getReachingDef(MachineInstr *MI, Register Reg) const
Provides the instruction id of the closest reaching def instruction of Reg that reaches MI,...
void run(MachineFunction &mf)
void getReachingLocalUses(MachineInstr *MI, Register Reg, InstSet &Uses) const
Provides the uses, in the same block as MI, of register that MI defines.
int getClearance(MachineInstr *MI, Register Reg) const
Provides the clearance - the number of instructions since the closest reaching def instuction of Reg ...
bool isRegDefinedAfter(MachineInstr *MI, Register Reg) const
Return whether the given register is defined after MI.
void init()
Initialize data structures.
void print(raw_ostream &OS)
bool hasLocalDefBefore(MachineInstr *MI, Register Reg) const
Provide whether the register has been defined in the same basic block as, and before,...
void reset()
Re-run the analysis.
void getGlobalUses(MachineInstr *MI, Register Reg, InstSet &Uses) const
Collect the users of the value stored in Reg, which is defined by MI.
MachineInstr * getMIOperand(MachineInstr *MI, unsigned Idx) const
If a single MachineInstr creates the reaching definition, for MIs operand at Idx, then return it.
void getLiveOuts(MachineBasicBlock *MBB, Register Reg, InstSet &Defs, BlockSet &VisitedBBs) const
Search MBB for a definition of Reg and insert it into Defs.
void traverse()
Traverse the machine function, mapping definitions.
bool isSafeToMoveBackwards(MachineInstr *From, MachineInstr *To) const
Return whether From can be moved backwards to just after To.
void collectKilledOperands(MachineInstr *MI, InstSet &Dead) const
Assuming MI is dead, recursively search the incoming operands which are killed by MI and collect thos...
bool hasSameReachingDef(MachineInstr *A, MachineInstr *B, Register Reg) const
Return whether A and B use the same def of Reg.
bool isRegUsedAfter(MachineInstr *MI, Register Reg) const
Return whether the given register is used after MI, whether it's a local use or a live out.
void getGlobalReachingDefs(MachineInstr *MI, Register Reg, InstSet &Defs) const
Collect all possible definitions of the value stored in Reg, which is used by MI.
bool isSafeToRemove(MachineInstr *MI, InstSet &ToRemove) const
Return whether removing this instruction will have no effect on the program, returning the redundant ...
ReachingDefInfo(ReachingDefInfo &&)
MachineInstr * getLocalLiveOutMIDef(MachineBasicBlock *MBB, Register Reg) const
Return the local MI that produces the live out value for Reg, or nullptr for a non-live out or non-lo...
bool invalidate(MachineFunction &F, const PreservedAnalyses &PA, MachineFunctionAnalysisManager::Invalidator &)
Handle invalidation explicitly.
bool getLiveInUses(MachineBasicBlock *MBB, Register Reg, InstSet &Uses) const
For the given block, collect the instructions that use the live-in value of the provided register.
bool isSafeToDefRegAt(MachineInstr *MI, Register Reg) const
Return whether a MachineInstr could be inserted at MI and safely define the given register without af...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Thin wrapper around "int" used to store reaching definitions, using an encoding that makes it compati...
ReachingDef(std::nullptr_t)
Wrapper class representing virtual and physical registers.
Definition Register.h:20
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
ArrayRef(const T &OneElt) -> ArrayRef< T >
A CRTP mix-in that provides informational APIs needed for analysis passes.
Definition PassManager.h:93
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition Analysis.h:29
A CRTP mix-in to automatically provide informational APIs needed for passes.
Definition PassManager.h:70
static ReachingDef getFromVoidPointer(const void *P)
static void * getAsVoidPointer(const ReachingDef &RD)
A traits type that is used to handle pointer types and things that are just wrappers for pointers as ...