summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-mca/Views/BottleneckAnalysis.h')
-rw-r--r--llvm/tools/llvm-mca/Views/BottleneckAnalysis.h65
1 files changed, 38 insertions, 27 deletions
diff --git a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
index 4c4dc193e13..c208847fe9f 100644
--- a/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
+++ b/llvm/tools/llvm-mca/Views/BottleneckAnalysis.h
@@ -63,7 +63,8 @@ class PressureTracker {
// There is one entry for every processor resource unit declared by the
// processor model. An all_ones value is treated like an invalid instruction
// identifier.
- SmallVector<unsigned, 4> ResourceUsers;
+ using User = std::pair<unsigned, unsigned>;
+ SmallVector<User, 4> ResourceUsers;
struct InstructionPressureInfo {
unsigned RegisterPressureCycles;
@@ -74,7 +75,7 @@ class PressureTracker {
void updateResourcePressureDistribution(uint64_t CumulativeMask);
- unsigned getResourceUser(unsigned ProcResID, unsigned UnitID) const {
+ User getResourceUser(unsigned ProcResID, unsigned UnitID) const {
unsigned Index = ProcResID2ResourceUsersIndex[ProcResID];
return ResourceUsers[Index + UnitID];
}
@@ -86,8 +87,8 @@ public:
return ResourcePressureDistribution;
}
- void getUniqueUsers(uint64_t ResourceMask,
- SmallVectorImpl<unsigned> &Users) const;
+ void getResourceUsers(uint64_t ResourceMask,
+ SmallVectorImpl<User> &Users) const;
unsigned getRegisterPressureCycles(unsigned IID) const {
assert(IPI.find(IID) != IPI.end() && "Instruction is not tracked!");
@@ -107,12 +108,18 @@ public:
return Info.ResourcePressureCycles;
}
+ void onInstructionDispatched(unsigned IID);
+ void onInstructionExecuted(unsigned IID);
+
void handlePressureEvent(const HWPressureEvent &Event);
- void handleInstructionEvent(const HWInstructionEvent &Event);
+ void handleInstructionIssuedEvent(const HWInstructionIssuedEvent &Event);
};
class DependencyGraph {
+ enum DependencyType { DT_REGISTER, DT_MEMORY, DT_RESOURCE };
+
struct DependencyEdge {
+ DependencyType Type;
unsigned IID;
uint64_t ResourceOrRegID;
uint64_t Cycles;
@@ -120,46 +127,44 @@ class DependencyGraph {
struct DGNode {
unsigned NumPredecessors;
- SmallVector<DependencyEdge, 8> RegDeps;
- SmallVector<DependencyEdge, 8> MemDeps;
- SmallVector<DependencyEdge, 8> ResDeps;
+ SmallVector<DependencyEdge, 8> OutgoingEdges;
};
SmallVector<DGNode, 16> Nodes;
- void addDepImpl(SmallVectorImpl<DependencyEdge> &Vec, DependencyEdge &&DE);
-
DependencyGraph(const DependencyGraph &) = delete;
DependencyGraph &operator=(const DependencyGraph &) = delete;
+ void addDependency(unsigned From, DependencyEdge &&DE);
+
+#ifndef NDEBUG
+ void dumpDependencyEdge(raw_ostream &OS, unsigned FromIID,
+ const DependencyEdge &DE, MCInstPrinter &MCIP) const;
+#endif
+
public:
- DependencyGraph(unsigned NumNodes) : Nodes(NumNodes, DGNode()) {}
+ DependencyGraph(unsigned Size) : Nodes(Size) {}
- void addRegDep(unsigned From, unsigned To, unsigned RegID, unsigned Cy) {
- addDepImpl(Nodes[From].RegDeps, {To, RegID, Cy});
+ void addRegisterDep(unsigned From, unsigned To, unsigned RegID, unsigned Cy) {
+ addDependency(From, {DT_REGISTER, To, RegID, Cy});
}
- void addMemDep(unsigned From, unsigned To, unsigned Cy) {
- addDepImpl(Nodes[From].MemDeps, {To, /* unused */ 0, Cy});
+
+ void addMemoryDep(unsigned From, unsigned To, unsigned Cy) {
+ addDependency(From, {DT_MEMORY, To, /* unused */ 0, Cy});
}
+
void addResourceDep(unsigned From, unsigned To, uint64_t Mask, unsigned Cy) {
- addDepImpl(Nodes[From].ResDeps, {To, Mask, Cy});
+ addDependency(From, {DT_RESOURCE, To, Mask, Cy});
}
#ifndef NDEBUG
- void dumpRegDeps(raw_ostream &OS, MCInstPrinter &MCIP) const;
- void dumpMemDeps(raw_ostream &OS) const;
- void dumpResDeps(raw_ostream &OS) const;
-
- void dump(raw_ostream &OS, MCInstPrinter &MCIP) const {
- dumpRegDeps(OS, MCIP);
- dumpMemDeps(OS);
- dumpResDeps(OS);
- }
+ void dump(raw_ostream &OS, MCInstPrinter &MCIP) const;
#endif
};
/// A view that collects and prints a few performance numbers.
class BottleneckAnalysis : public View {
const MCSubtargetInfo &STI;
+ MCInstPrinter &MCIP;
PressureTracker Tracker;
DependencyGraph DG;
@@ -189,8 +194,14 @@ class BottleneckAnalysis : public View {
// Prints a bottleneck message to OS.
void printBottleneckHints(raw_ostream &OS) const;
+ // Used to populate the dependency graph DG.
+ void addRegisterDep(unsigned From, unsigned To, unsigned RegID, unsigned Cy);
+ void addMemoryDep(unsigned From, unsigned To, unsigned Cy);
+ void addResourceDep(unsigned From, unsigned To, uint64_t Mask, unsigned Cy);
+
public:
- BottleneckAnalysis(const MCSubtargetInfo &STI, ArrayRef<MCInst> Sequence);
+ BottleneckAnalysis(const MCSubtargetInfo &STI, MCInstPrinter &MCIP,
+ ArrayRef<MCInst> Sequence);
void onCycleEnd() override;
void onEvent(const HWStallEvent &Event) override { SeenStallCycles = true; }
@@ -200,7 +211,7 @@ public:
void printView(raw_ostream &OS) const override;
#ifndef NDEBUG
- void dump(raw_ostream &OS, MCInstPrinter &MCIP) const { DG.dump(OS, MCIP); }
+ void dump(raw_ostream &OS) const { DG.dump(OS, MCIP); }
#endif
};
OpenPOWER on IntegriCloud