#ifndef LLVM_CODEGEN_MACHINETRACEMETRICS_H
#define LLVM_CODEGEN_MACHINETRACEMETRICS_H
#include "llvm/ADT/SparseSet.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/TargetSchedule.h"
namespace llvm {
class AnalysisUsage;
class MachineFunction;
class MachineInstr;
class MachineLoop;
class MachineLoopInfo;
class MachineRegisterInfo;
struct MCSchedClassDesc;
class raw_ostream;
class TargetInstrInfo;
class TargetRegisterInfo;
struct LiveRegUnit {
unsigned RegUnit;
unsigned Cycle = 0;
const MachineInstr *MI = nullptr;
unsigned Op = 0;
unsigned getSparseSetIndex() const { return RegUnit; }
LiveRegUnit(unsigned RU) : RegUnit(RU) {}
};
class MachineTraceMetrics : public MachineFunctionPass {
const MachineFunction *MF = nullptr;
const TargetInstrInfo *TII = nullptr;
const TargetRegisterInfo *TRI = nullptr;
const MachineRegisterInfo *MRI = nullptr;
const MachineLoopInfo *Loops = nullptr;
TargetSchedModel SchedModel;
public:
friend class Ensemble;
friend class Trace;
class Ensemble;
static char ID;
MachineTraceMetrics();
void getAnalysisUsage(AnalysisUsage&) const override;
bool runOnMachineFunction(MachineFunction&) override;
void releaseMemory() override;
void verifyAnalysis() const override;
struct FixedBlockInfo {
unsigned InstrCount = ~0u;
bool HasCalls = false;
FixedBlockInfo() = default;
bool hasResources() const { return InstrCount != ~0u; }
void invalidate() { InstrCount = ~0u; }
};
const FixedBlockInfo *getResources(const MachineBasicBlock*);
ArrayRef<unsigned> getProcResourceCycles(unsigned MBBNum) const;
struct LiveInReg {
Register Reg;
unsigned Height;
LiveInReg(Register Reg, unsigned Height = 0) : Reg(Reg), Height(Height) {}
};
struct TraceBlockInfo {
const MachineBasicBlock *Pred = nullptr;
const MachineBasicBlock *Succ = nullptr;
unsigned Head;
unsigned Tail;
unsigned InstrDepth = ~0u;
unsigned InstrHeight = ~0u;
TraceBlockInfo() = default;
bool hasValidDepth() const { return InstrDepth != ~0u; }
bool hasValidHeight() const { return InstrHeight != ~0u; }
void invalidateDepth() { InstrDepth = ~0u; HasValidInstrDepths = false; }
void invalidateHeight() { InstrHeight = ~0u; HasValidInstrHeights = false; }
bool isUsefulDominator(const TraceBlockInfo &TBI) const {
if (!hasValidDepth() || !TBI.hasValidDepth())
return false;
if (Head != TBI.Head)
return false;
return HasValidInstrDepths && InstrDepth <= TBI.InstrDepth;
}
bool HasValidInstrDepths = false;
bool HasValidInstrHeights = false;
unsigned CriticalPath;
SmallVector<LiveInReg, 4> LiveIns;
void print(raw_ostream&) const;
};
struct InstrCycles {
unsigned Depth;
unsigned Height;
};
class Trace {
Ensemble &TE;
TraceBlockInfo &TBI;
unsigned getBlockNum() const { return &TBI - &TE.BlockInfo[0]; }
public:
explicit Trace(Ensemble &te, TraceBlockInfo &tbi) : TE(te), TBI(tbi) {}
void print(raw_ostream&) const;
unsigned getInstrCount() const {
return TBI.InstrDepth + TBI.InstrHeight;
}
unsigned getResourceDepth(bool Bottom) const;
unsigned getResourceLength(
ArrayRef<const MachineBasicBlock *> Extrablocks = None,
ArrayRef<const MCSchedClassDesc *> ExtraInstrs = None,
ArrayRef<const MCSchedClassDesc *> RemoveInstrs = None) const;
unsigned getCriticalPath() const { return TBI.CriticalPath; }
InstrCycles getInstrCycles(const MachineInstr &MI) const {
return TE.Cycles.lookup(&MI);
}
unsigned getInstrSlack(const MachineInstr &MI) const;
unsigned getPHIDepth(const MachineInstr &PHI) const;
bool isDepInTrace(const MachineInstr &DefMI,
const MachineInstr &UseMI) const;
};
class Ensemble {
friend class Trace;
SmallVector<TraceBlockInfo, 4> BlockInfo;
DenseMap<const MachineInstr*, InstrCycles> Cycles;
SmallVector<unsigned, 0> ProcResourceDepths;
SmallVector<unsigned, 0> ProcResourceHeights;
void computeTrace(const MachineBasicBlock*);
void computeDepthResources(const MachineBasicBlock*);
void computeHeightResources(const MachineBasicBlock*);
unsigned computeCrossBlockCriticalPath(const TraceBlockInfo&);
void computeInstrDepths(const MachineBasicBlock*);
void computeInstrHeights(const MachineBasicBlock*);
void addLiveIns(const MachineInstr *DefMI, unsigned DefOp,
ArrayRef<const MachineBasicBlock*> Trace);
protected:
MachineTraceMetrics &MTM;
explicit Ensemble(MachineTraceMetrics*);
virtual const MachineBasicBlock *pickTracePred(const MachineBasicBlock*) =0;
virtual const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*) =0;
const MachineLoop *getLoopFor(const MachineBasicBlock*) const;
const TraceBlockInfo *getDepthResources(const MachineBasicBlock*) const;
const TraceBlockInfo *getHeightResources(const MachineBasicBlock*) const;
ArrayRef<unsigned> getProcResourceDepths(unsigned MBBNum) const;
ArrayRef<unsigned> getProcResourceHeights(unsigned MBBNum) const;
public:
virtual ~Ensemble();
virtual const char *getName() const = 0;
void print(raw_ostream&) const;
void invalidate(const MachineBasicBlock *MBB);
void verify() const;
Trace getTrace(const MachineBasicBlock *MBB);
void updateDepth(TraceBlockInfo &TBI, const MachineInstr&,
SparseSet<LiveRegUnit> &RegUnits);
void updateDepth(const MachineBasicBlock *, const MachineInstr&,
SparseSet<LiveRegUnit> &RegUnits);
void updateDepths(MachineBasicBlock::iterator Start,
MachineBasicBlock::iterator End,
SparseSet<LiveRegUnit> &RegUnits);
};
enum Strategy {
TS_MinInstrCount,
TS_NumStrategies
};
Ensemble *getEnsemble(Strategy);
void invalidate(const MachineBasicBlock *MBB);
private:
SmallVector<FixedBlockInfo, 4> BlockInfo;
SmallVector<unsigned, 0> ProcResourceCycles;
Ensemble* Ensembles[TS_NumStrategies];
unsigned getCycles(unsigned Scaled) {
unsigned Factor = SchedModel.getLatencyFactor();
return (Scaled + Factor - 1) / Factor;
}
};
inline raw_ostream &operator<<(raw_ostream &OS,
const MachineTraceMetrics::Trace &Tr) {
Tr.print(OS);
return OS;
}
inline raw_ostream &operator<<(raw_ostream &OS,
const MachineTraceMetrics::Ensemble &En) {
En.print(OS);
return OS;
}
}
#endif