LLVM 20.0.0git
MachineTraceMetrics.h
Go to the documentation of this file.
1//===- lib/CodeGen/MachineTraceMetrics.h - Super-scalar metrics -*- 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 defines the interface for the MachineTraceMetrics analysis pass
10// that estimates CPU resource usage and critical data dependency paths through
11// preferred traces. This is useful for super-scalar CPUs where execution speed
12// can be limited both by data dependencies and by limited execution resources.
13//
14// Out-of-order CPUs will often be executing instructions from multiple basic
15// blocks at the same time. This makes it difficult to estimate the resource
16// usage accurately in a single basic block. Resources can be estimated better
17// by looking at a trace through the current basic block.
18//
19// For every block, the MachineTraceMetrics pass will pick a preferred trace
20// that passes through the block. The trace is chosen based on loop structure,
21// branch probabilities, and resource usage. The intention is to pick likely
22// traces that would be the most affected by code transformations.
23//
24// It is expensive to compute a full arbitrary trace for every block, so to
25// save some computations, traces are chosen to be convergent. This means that
26// if the traces through basic blocks A and B ever cross when moving away from
27// A and B, they never diverge again. This applies in both directions - If the
28// traces meet above A and B, they won't diverge when going further back.
29//
30// Traces tend to align with loops. The trace through a block in an inner loop
31// will begin at the loop entry block and end at a back edge. If there are
32// nested loops, the trace may begin and end at those instead.
33//
34// For each trace, we compute the critical path length, which is the number of
35// cycles required to execute the trace when execution is limited by data
36// dependencies only. We also compute the resource height, which is the number
37// of cycles required to execute all instructions in the trace when ignoring
38// data dependencies.
39//
40// Every instruction in the current block has a slack - the number of cycles
41// execution of the instruction can be delayed without extending the critical
42// path.
43//
44//===----------------------------------------------------------------------===//
45
46#ifndef LLVM_CODEGEN_MACHINETRACEMETRICS_H
47#define LLVM_CODEGEN_MACHINETRACEMETRICS_H
48
49#include "llvm/ADT/ArrayRef.h"
50#include "llvm/ADT/DenseMap.h"
52#include "llvm/ADT/SparseSet.h"
57
58namespace llvm {
59
60class AnalysisUsage;
61class MachineFunction;
62class MachineInstr;
63class MachineLoop;
64class MachineLoopInfo;
65class MachineRegisterInfo;
66struct MCSchedClassDesc;
67class raw_ostream;
68class TargetInstrInfo;
69class TargetRegisterInfo;
70
71// Keep track of physreg data dependencies by recording each live register unit.
72// Associate each regunit with an instruction operand. Depending on the
73// direction instructions are scanned, it could be the operand that defined the
74// regunit, or the highest operand to read the regunit.
76 unsigned RegUnit;
77 unsigned Cycle = 0;
78 const MachineInstr *MI = nullptr;
79 unsigned Op = 0;
80
81 unsigned getSparseSetIndex() const { return RegUnit; }
82
83 LiveRegUnit(unsigned RU) : RegUnit(RU) {}
84};
85
86/// Strategies for selecting traces.
88 /// Select the trace through a block that has the fewest instructions.
90 /// Select the trace that contains only the current basic block. For instance,
91 /// this strategy can be used by MachineCombiner to make better decisions when
92 /// we estimate critical path for in-order cores.
95};
96
98 const MachineFunction *MF = nullptr;
99 const TargetInstrInfo *TII = nullptr;
100 const TargetRegisterInfo *TRI = nullptr;
101 const MachineRegisterInfo *MRI = nullptr;
102 const MachineLoopInfo *Loops = nullptr;
103 TargetSchedModel SchedModel;
104
105public:
107 friend class Ensemble;
108 friend class Trace;
109
110 class Ensemble;
111
112 // For legacy pass.
114
116 init(MF, LI);
117 }
118
120
122
123 void init(MachineFunction &Func, const MachineLoopInfo &LI);
124 void clear();
125
126 /// Per-basic block information that doesn't depend on the trace through the
127 /// block.
129 /// The number of non-trivial instructions in the block.
130 /// Doesn't count PHI and COPY instructions that are likely to be removed.
131 unsigned InstrCount = ~0u;
132
133 /// True when the block contains calls.
134 bool HasCalls = false;
135
136 FixedBlockInfo() = default;
137
138 /// Returns true when resource information for this block has been computed.
139 bool hasResources() const { return InstrCount != ~0u; }
140
141 /// Invalidate resource information.
142 void invalidate() { InstrCount = ~0u; }
143 };
144
145 /// Get the fixed resource information about MBB. Compute it on demand.
146 const FixedBlockInfo *getResources(const MachineBasicBlock*);
147
148 /// Get the scaled number of cycles used per processor resource in MBB.
149 /// This is an array with SchedModel.getNumProcResourceKinds() entries.
150 /// The getResources() function above must have been called first.
151 ///
152 /// These numbers have already been scaled by SchedModel.getResourceFactor().
153 ArrayRef<unsigned> getProcReleaseAtCycles(unsigned MBBNum) const;
154
155 /// A virtual register or regunit required by a basic block or its trace
156 /// successors.
157 struct LiveInReg {
158 /// The virtual register required, or a register unit.
160
161 /// For virtual registers: Minimum height of the defining instruction.
162 /// For regunits: Height of the highest user in the trace.
163 unsigned Height;
164
166 };
167
168 /// Per-basic block information that relates to a specific trace through the
169 /// block. Convergent traces means that only one of these is required per
170 /// block in a trace ensemble.
172 /// Trace predecessor, or NULL for the first block in the trace.
173 /// Valid when hasValidDepth().
174 const MachineBasicBlock *Pred = nullptr;
175
176 /// Trace successor, or NULL for the last block in the trace.
177 /// Valid when hasValidHeight().
178 const MachineBasicBlock *Succ = nullptr;
179
180 /// The block number of the head of the trace. (When hasValidDepth()).
181 unsigned Head;
182
183 /// The block number of the tail of the trace. (When hasValidHeight()).
184 unsigned Tail;
185
186 /// Accumulated number of instructions in the trace above this block.
187 /// Does not include instructions in this block.
188 unsigned InstrDepth = ~0u;
189
190 /// Accumulated number of instructions in the trace below this block.
191 /// Includes instructions in this block.
192 unsigned InstrHeight = ~0u;
193
194 TraceBlockInfo() = default;
195
196 /// Returns true if the depth resources have been computed from the trace
197 /// above this block.
198 bool hasValidDepth() const { return InstrDepth != ~0u; }
199
200 /// Returns true if the height resources have been computed from the trace
201 /// below this block.
202 bool hasValidHeight() const { return InstrHeight != ~0u; }
203
204 /// Invalidate depth resources when some block above this one has changed.
206
207 /// Invalidate height resources when a block below this one has changed.
209
210 /// Assuming that this is a dominator of TBI, determine if it contains
211 /// useful instruction depths. A dominating block can be above the current
212 /// trace head, and any dependencies from such a far away dominator are not
213 /// expected to affect the critical path.
214 ///
215 /// Also returns true when TBI == this.
216 bool isUsefulDominator(const TraceBlockInfo &TBI) const {
217 // The trace for TBI may not even be calculated yet.
218 if (!hasValidDepth() || !TBI.hasValidDepth())
219 return false;
220 // Instruction depths are only comparable if the traces share a head.
221 if (Head != TBI.Head)
222 return false;
223 // It is almost always the case that TBI belongs to the same trace as
224 // this block, but rare convoluted cases involving irreducible control
225 // flow, a dominator may share a trace head without actually being on the
226 // same trace as TBI. This is not a big problem as long as it doesn't
227 // increase the instruction depth.
229 }
230
231 // Data-dependency-related information. Per-instruction depth and height
232 // are computed from data dependencies in the current trace, using
233 // itinerary data.
234
235 /// Instruction depths have been computed. This implies hasValidDepth().
237
238 /// Instruction heights have been computed. This implies hasValidHeight().
240
241 /// Critical path length. This is the number of cycles in the longest data
242 /// dependency chain through the trace. This is only valid when both
243 /// HasValidInstrDepths and HasValidInstrHeights are set.
244 unsigned CriticalPath;
245
246 /// Live-in registers. These registers are defined above the current block
247 /// and used by this block or a block below it.
248 /// This does not include PHI uses in the current block, but it does
249 /// include PHI uses in deeper blocks.
251
252 void print(raw_ostream&) const;
253 void dump() const { print(dbgs()); }
254 };
255
256 /// InstrCycles represents the cycle height and depth of an instruction in a
257 /// trace.
258 struct InstrCycles {
259 /// Earliest issue cycle as determined by data dependencies and instruction
260 /// latencies from the beginning of the trace. Data dependencies from
261 /// before the trace are not included.
262 unsigned Depth;
263
264 /// Minimum number of cycles from this instruction is issued to the of the
265 /// trace, as determined by data dependencies and instruction latencies.
266 unsigned Height;
267 };
268
269 /// A trace represents a plausible sequence of executed basic blocks that
270 /// passes through the current basic block one. The Trace class serves as a
271 /// handle to internal cached data structures.
272 class Trace {
273 Ensemble &TE;
274 TraceBlockInfo &TBI;
275
276 unsigned getBlockNum() const { return &TBI - &TE.BlockInfo[0]; }
277
278 public:
279 explicit Trace(Ensemble &te, TraceBlockInfo &tbi) : TE(te), TBI(tbi) {}
280
281 void print(raw_ostream&) const;
282 void dump() const { print(dbgs()); }
283
284 /// Compute the total number of instructions in the trace.
285 unsigned getInstrCount() const {
286 return TBI.InstrDepth + TBI.InstrHeight;
287 }
288
289 /// Return the resource depth of the top/bottom of the trace center block.
290 /// This is the number of cycles required to execute all instructions from
291 /// the trace head to the trace center block. The resource depth only
292 /// considers execution resources, it ignores data dependencies.
293 /// When Bottom is set, instructions in the trace center block are included.
294 unsigned getResourceDepth(bool Bottom) const;
295
296 /// Return the resource length of the trace. This is the number of cycles
297 /// required to execute the instructions in the trace if they were all
298 /// independent, exposing the maximum instruction-level parallelism.
299 ///
300 /// Any blocks in Extrablocks are included as if they were part of the
301 /// trace. Likewise, extra resources required by the specified scheduling
302 /// classes are included. For the caller to account for extra machine
303 /// instructions, it must first resolve each instruction's scheduling class.
304 unsigned getResourceLength(
306 ArrayRef<const MCSchedClassDesc *> ExtraInstrs = {},
307 ArrayRef<const MCSchedClassDesc *> RemoveInstrs = {}) const;
308
309 /// Return the length of the (data dependency) critical path through the
310 /// trace.
311 unsigned getCriticalPath() const { return TBI.CriticalPath; }
312
313 /// Return the depth and height of MI. The depth is only valid for
314 /// instructions in or above the trace center block. The height is only
315 /// valid for instructions in or below the trace center block.
317 return TE.Cycles.lookup(&MI);
318 }
319
320 /// Return the slack of MI. This is the number of cycles MI can be delayed
321 /// before the critical path becomes longer.
322 /// MI must be an instruction in the trace center block.
323 unsigned getInstrSlack(const MachineInstr &MI) const;
324
325 /// Return the Depth of a PHI instruction in a trace center block successor.
326 /// The PHI does not have to be part of the trace.
327 unsigned getPHIDepth(const MachineInstr &PHI) const;
328
329 /// A dependence is useful if the basic block of the defining instruction
330 /// is part of the trace of the user instruction. It is assumed that DefMI
331 /// dominates UseMI (see also isUsefulDominator).
332 bool isDepInTrace(const MachineInstr &DefMI,
333 const MachineInstr &UseMI) const;
334 };
335
336 /// A trace ensemble is a collection of traces selected using the same
337 /// strategy, for example 'minimum resource height'. There is one trace for
338 /// every block in the function.
339 class Ensemble {
340 friend class Trace;
341
344 SmallVector<unsigned, 0> ProcResourceDepths;
345 SmallVector<unsigned, 0> ProcResourceHeights;
346
347 void computeTrace(const MachineBasicBlock*);
348 void computeDepthResources(const MachineBasicBlock*);
349 void computeHeightResources(const MachineBasicBlock*);
350 unsigned computeCrossBlockCriticalPath(const TraceBlockInfo&);
351 void computeInstrDepths(const MachineBasicBlock*);
352 void computeInstrHeights(const MachineBasicBlock*);
353 void addLiveIns(const MachineInstr *DefMI, unsigned DefOp,
355
356 protected:
358
359 explicit Ensemble(MachineTraceMetrics*);
360
363 const MachineLoop *getLoopFor(const MachineBasicBlock*) const;
366 ArrayRef<unsigned> getProcResourceDepths(unsigned MBBNum) const;
367 ArrayRef<unsigned> getProcResourceHeights(unsigned MBBNum) const;
368
369 public:
370 virtual ~Ensemble();
371
372 virtual const char *getName() const = 0;
373 void print(raw_ostream &) const;
374 void dump() const { print(dbgs()); }
375 void invalidate(const MachineBasicBlock *MBB);
376 void verify() const;
377
378 /// Get the trace that passes through MBB.
379 /// The trace is computed on demand.
381
382 /// Updates the depth of an machine instruction, given RegUnits.
383 void updateDepth(TraceBlockInfo &TBI, const MachineInstr&,
384 SparseSet<LiveRegUnit> &RegUnits);
385 void updateDepth(const MachineBasicBlock *, const MachineInstr&,
386 SparseSet<LiveRegUnit> &RegUnits);
387
388 /// Updates the depth of the instructions from Start to End.
391 SparseSet<LiveRegUnit> &RegUnits);
392
393 };
394
395 /// Get the trace ensemble representing the given trace selection strategy.
396 /// The returned Ensemble object is owned by the MachineTraceMetrics analysis,
397 /// and valid for the lifetime of the analysis pass.
399
400 /// Invalidate cached information about MBB. This must be called *before* MBB
401 /// is erased, or the CFG is otherwise changed.
402 ///
403 /// This invalidates per-block information about resource usage for MBB only,
404 /// and it invalidates per-trace information for any trace that passes
405 /// through MBB.
406 ///
407 /// Call Ensemble::getTrace() again to update any trace handles.
408 void invalidate(const MachineBasicBlock *MBB);
409
410 /// Handle invalidation explicitly.
413
414 void verifyAnalysis() const;
415
416private:
417 // One entry per basic block, indexed by block number.
419
420 // Cycles consumed on each processor resource per block.
421 // The number of processor resource kinds is constant for a given subtarget,
422 // but it is not known at compile time. The number of cycles consumed by
423 // block B on processor resource R is at ProcReleaseAtCycles[B*Kinds + R]
424 // where Kinds = SchedModel.getNumProcResourceKinds().
425 SmallVector<unsigned, 0> ProcReleaseAtCycles;
426
427 // One ensemble per strategy.
428 std::unique_ptr<Ensemble>
429 Ensembles[static_cast<size_t>(MachineTraceStrategy::TS_NumStrategies)];
430
431 // Convert scaled resource usage to a cycle count that can be compared with
432 // latencies.
433 unsigned getCycles(unsigned Scaled) {
434 unsigned Factor = SchedModel.getLatencyFactor();
435 return (Scaled + Factor - 1) / Factor;
436 }
437};
438
440 const MachineTraceMetrics::Trace &Tr) {
441 Tr.print(OS);
442 return OS;
443}
444
447 En.print(OS);
448 return OS;
449}
450
452 : public AnalysisInfoMixin<MachineTraceMetricsAnalysis> {
454 static AnalysisKey Key;
455
456public:
459};
460
461/// Verifier pass for \c MachineTraceMetrics.
463 : PassInfoMixin<MachineTraceMetricsVerifierPass> {
466 static bool isRequired() { return true; }
467};
468
470public:
471 static char ID;
473
475
476 void getAnalysisUsage(AnalysisUsage &) const override;
477 bool runOnMachineFunction(MachineFunction &) override;
478 void releaseMemory() override { MTM.clear(); }
479 void verifyAnalysis() const override { MTM.verifyAnalysis(); }
481};
482
483} // end namespace llvm
484
485#endif // LLVM_CODEGEN_MACHINETRACEMETRICS_H
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
Rewrite undef for PHI
@ Scaled
MachineBasicBlock & MBB
This file defines the DenseMap class.
bool End
Definition: ELF_riscv.cpp:480
IRTranslator LLVM IR MI
LiveInRegUnits addLiveIns(MBB)
raw_pwrite_stream & OS
This file defines the SmallVector class.
This file defines the SparseSet class derived from the version described in Briggs,...
API to communicate dependencies between analyses during invalidation.
Definition: PassManager.h:292
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
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:41
This class represents an Operation in the Expression.
A possibly irreducible generalization of a Loop.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void getAnalysisUsage(AnalysisUsage &) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool runOnMachineFunction(MachineFunction &) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void verifyAnalysis() const override
verifyAnalysis() - This member can be implemented by a analysis pass to check state of analysis infor...
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
A trace ensemble is a collection of traces selected using the same strategy, for example 'minimum res...
void invalidate(const MachineBasicBlock *MBB)
Invalidate traces through BadMBB.
ArrayRef< unsigned > getProcResourceHeights(unsigned MBBNum) const
Get an array of processor resource heights for MBB.
virtual const MachineBasicBlock * pickTracePred(const MachineBasicBlock *)=0
void updateDepth(TraceBlockInfo &TBI, const MachineInstr &, SparseSet< LiveRegUnit > &RegUnits)
Updates the depth of an machine instruction, given RegUnits.
const MachineLoop * getLoopFor(const MachineBasicBlock *) const
const TraceBlockInfo * getHeightResources(const MachineBasicBlock *) const
void updateDepths(MachineBasicBlock::iterator Start, MachineBasicBlock::iterator End, SparseSet< LiveRegUnit > &RegUnits)
Updates the depth of the instructions from Start to End.
const TraceBlockInfo * getDepthResources(const MachineBasicBlock *) const
virtual const char * getName() const =0
ArrayRef< unsigned > getProcResourceDepths(unsigned MBBNum) const
Get an array of processor resource depths for MBB.
virtual const MachineBasicBlock * pickTraceSucc(const MachineBasicBlock *)=0
Trace getTrace(const MachineBasicBlock *MBB)
Get the trace that passes through MBB.
A trace represents a plausible sequence of executed basic blocks that passes through the current basi...
unsigned getInstrCount() const
Compute the total number of instructions in the trace.
unsigned getResourceLength(ArrayRef< const MachineBasicBlock * > Extrablocks={}, ArrayRef< const MCSchedClassDesc * > ExtraInstrs={}, ArrayRef< const MCSchedClassDesc * > RemoveInstrs={}) const
Return the resource length of the trace.
InstrCycles getInstrCycles(const MachineInstr &MI) const
Return the depth and height of MI.
unsigned getInstrSlack(const MachineInstr &MI) const
Return the slack of MI.
bool isDepInTrace(const MachineInstr &DefMI, const MachineInstr &UseMI) const
A dependence is useful if the basic block of the defining instruction is part of the trace of the use...
Trace(Ensemble &te, TraceBlockInfo &tbi)
unsigned getCriticalPath() const
Return the length of the (data dependency) critical path through the trace.
unsigned getPHIDepth(const MachineInstr &PHI) const
Return the Depth of a PHI instruction in a trace center block successor.
unsigned getResourceDepth(bool Bottom) const
Return the resource depth of the top/bottom of the trace center block.
MachineTraceMetrics(MachineTraceMetrics &&)=default
Ensemble * getEnsemble(MachineTraceStrategy)
Get the trace ensemble representing the given trace selection strategy.
void invalidate(const MachineBasicBlock *MBB)
Invalidate cached information about MBB.
const FixedBlockInfo * getResources(const MachineBasicBlock *)
Get the fixed resource information about MBB. Compute it on demand.
ArrayRef< unsigned > getProcReleaseAtCycles(unsigned MBBNum) const
Get the scaled number of cycles used per processor resource in MBB.
void init(MachineFunction &Func, const MachineLoopInfo &LI)
MachineTraceMetrics(MachineFunction &MF, const MachineLoopInfo &LI)
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
SparseSet - Fast set implementation for objects that can be identified by small unsigned keys.
Definition: SparseSet.h:124
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Provide an instruction scheduling machine model to CodeGen passes.
unsigned getLatencyFactor() const
Multiply cycle count by this factor to normalize it relative to other resources.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineTraceStrategy
Strategies for selecting traces.
@ TS_MinInstrCount
Select the trace through a block that has the fewest instructions.
@ TS_Local
Select the trace that contains only the current basic block.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:303
A CRTP mix-in that provides informational APIs needed for analysis passes.
Definition: PassManager.h:92
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: Analysis.h:28
unsigned getSparseSetIndex() const
const MachineInstr * MI
LiveRegUnit(unsigned RU)
Verifier pass for MachineTraceMetrics.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Per-basic block information that doesn't depend on the trace through the block.
bool hasResources() const
Returns true when resource information for this block has been computed.
unsigned InstrCount
The number of non-trivial instructions in the block.
void invalidate()
Invalidate resource information.
bool HasCalls
True when the block contains calls.
InstrCycles represents the cycle height and depth of an instruction in a trace.
unsigned Height
Minimum number of cycles from this instruction is issued to the of the trace, as determined by data d...
unsigned Depth
Earliest issue cycle as determined by data dependencies and instruction latencies from the beginning ...
A virtual register or regunit required by a basic block or its trace successors.
unsigned Height
For virtual registers: Minimum height of the defining instruction.
Register Reg
The virtual register required, or a register unit.
LiveInReg(Register Reg, unsigned Height=0)
Per-basic block information that relates to a specific trace through the block.
unsigned InstrDepth
Accumulated number of instructions in the trace above this block.
void invalidateDepth()
Invalidate depth resources when some block above this one has changed.
const MachineBasicBlock * Pred
Trace predecessor, or NULL for the first block in the trace.
unsigned InstrHeight
Accumulated number of instructions in the trace below this block.
SmallVector< LiveInReg, 4 > LiveIns
Live-in registers.
const MachineBasicBlock * Succ
Trace successor, or NULL for the last block in the trace.
bool hasValidDepth() const
Returns true if the depth resources have been computed from the trace above this block.
bool isUsefulDominator(const TraceBlockInfo &TBI) const
Assuming that this is a dominator of TBI, determine if it contains useful instruction depths.
void invalidateHeight()
Invalidate height resources when a block below this one has changed.
unsigned CriticalPath
Critical path length.
unsigned Head
The block number of the head of the trace. (When hasValidDepth()).
bool HasValidInstrDepths
Instruction depths have been computed. This implies hasValidDepth().
bool hasValidHeight() const
Returns true if the height resources have been computed from the trace below this block.
unsigned Tail
The block number of the tail of the trace. (When hasValidHeight()).
bool HasValidInstrHeights
Instruction heights have been computed. This implies hasValidHeight().
A CRTP mix-in to automatically provide informational APIs needed for passes.
Definition: PassManager.h:69