[llvm] r341980 - [llvm-mca] Delay calculation of Cycles per Resources, separate the cycles and resource quantities.
Matt Davis via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 11 11:47:48 PDT 2018
Author: mattd
Date: Tue Sep 11 11:47:48 2018
New Revision: 341980
URL: http://llvm.org/viewvc/llvm-project?rev=341980&view=rev
Log:
[llvm-mca] Delay calculation of Cycles per Resources, separate the cycles and resource quantities.
Summary:
This patch removes the storing of accumulated floating point data
within the llvm-mca library.
This patch splits-up the two quantities: cycles and number of resource units.
By splitting-up these two quantities, we delay the calculation of "cycles per resource unit"
until that value is read, reducing the chance of accumulating floating point error.
I considered using the APFloat, but after measuring performance, for a large (many iteration)
sample, I decided to go with this faster solution.
Reviewers: andreadb, courbet, RKSimon
Reviewed By: andreadb
Subscribers: llvm-commits, javed.absar, tschuett, gbedwell
Differential Revision: https://reviews.llvm.org/D51903
Modified:
llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.cpp
llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.h
llvm/trunk/tools/llvm-mca/include/HWEventListener.h
llvm/trunk/tools/llvm-mca/include/HardwareUnits/ResourceManager.h
llvm/trunk/tools/llvm-mca/include/HardwareUnits/Scheduler.h
llvm/trunk/tools/llvm-mca/include/Stages/ExecuteStage.h
llvm/trunk/tools/llvm-mca/include/Stages/InstructionTables.h
llvm/trunk/tools/llvm-mca/include/Support.h
llvm/trunk/tools/llvm-mca/lib/HardwareUnits/ResourceManager.cpp
llvm/trunk/tools/llvm-mca/lib/HardwareUnits/Scheduler.cpp
llvm/trunk/tools/llvm-mca/lib/Stages/ExecuteStage.cpp
llvm/trunk/tools/llvm-mca/lib/Stages/InstructionTables.cpp
Modified: llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.cpp?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.cpp (original)
+++ llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.cpp Tue Sep 11 11:47:48 2018
@@ -46,7 +46,8 @@ void ResourcePressureView::onEvent(const
return;
const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event);
const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size();
- for (const std::pair<ResourceRef, double> &Use : IssueEvent.UsedResources) {
+ for (const std::pair<ResourceRef, ResourceCycles> &Use :
+ IssueEvent.UsedResources) {
const ResourceRef &RR = Use.first;
assert(Resource2VecIndex.find(RR.first) != Resource2VecIndex.end());
unsigned R2VIndex = Resource2VecIndex[RR.first];
Modified: llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.h?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.h (original)
+++ llvm/trunk/tools/llvm-mca/Views/ResourcePressureView.h Tue Sep 11 11:47:48 2018
@@ -79,7 +79,7 @@ class ResourcePressureView : public View
llvm::DenseMap<unsigned, unsigned> Resource2VecIndex;
// Table of resources used by instructions.
- std::vector<double> ResourceUsage;
+ std::vector<ResourceCycles> ResourceUsage;
unsigned NumResourceUnits;
const llvm::MCInst &GetMCInstFromIndex(unsigned Index) const;
Modified: llvm/trunk/tools/llvm-mca/include/HWEventListener.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/HWEventListener.h?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/HWEventListener.h (original)
+++ llvm/trunk/tools/llvm-mca/include/HWEventListener.h Tue Sep 11 11:47:48 2018
@@ -16,8 +16,8 @@
#define LLVM_TOOLS_LLVM_MCA_HWEVENTLISTENER_H
#include "Instruction.h"
+#include "Support.h"
#include "llvm/ADT/ArrayRef.h"
-#include <utility>
namespace mca {
@@ -61,11 +61,12 @@ public:
class HWInstructionIssuedEvent : public HWInstructionEvent {
public:
using ResourceRef = std::pair<uint64_t, uint64_t>;
- HWInstructionIssuedEvent(const InstRef &IR,
- llvm::ArrayRef<std::pair<ResourceRef, double>> UR)
+ HWInstructionIssuedEvent(
+ const InstRef &IR,
+ llvm::ArrayRef<std::pair<ResourceRef, ResourceCycles>> UR)
: HWInstructionEvent(HWInstructionEvent::Issued, IR), UsedResources(UR) {}
- llvm::ArrayRef<std::pair<ResourceRef, double>> UsedResources;
+ llvm::ArrayRef<std::pair<ResourceRef, ResourceCycles>> UsedResources;
};
class HWInstructionDispatchedEvent : public HWInstructionEvent {
Modified: llvm/trunk/tools/llvm-mca/include/HardwareUnits/ResourceManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/HardwareUnits/ResourceManager.h?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/HardwareUnits/ResourceManager.h (original)
+++ llvm/trunk/tools/llvm-mca/include/HardwareUnits/ResourceManager.h Tue Sep 11 11:47:48 2018
@@ -17,6 +17,7 @@
#define LLVM_TOOLS_LLVM_MCA_RESOURCE_MANAGER_H
#include "Instruction.h"
+#include "Support.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
@@ -344,7 +345,7 @@ public:
void issueInstruction(
const InstrDesc &Desc,
- llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
+ llvm::SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &Pipes);
void cycleEvent(llvm::SmallVectorImpl<ResourceRef> &ResourcesFreed);
Modified: llvm/trunk/tools/llvm-mca/include/HardwareUnits/Scheduler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/HardwareUnits/Scheduler.h?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/HardwareUnits/Scheduler.h (original)
+++ llvm/trunk/tools/llvm-mca/include/HardwareUnits/Scheduler.h Tue Sep 11 11:47:48 2018
@@ -18,6 +18,7 @@
#include "HardwareUnits/HardwareUnit.h"
#include "HardwareUnits/LSUnit.h"
#include "ResourceManager.h"
+#include "Support.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCSchedule.h"
@@ -103,7 +104,7 @@ class Scheduler : public HardwareUnit {
/// Issue an instruction without updating the ready queue.
void issueInstructionImpl(
InstRef &IR,
- llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes);
+ llvm::SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &Pipes);
// Identify instructions that have finished executing, and remove them from
// the IssuedSet. References to executed instructions are added to input
@@ -164,10 +165,10 @@ public:
/// Issue an instruction and populates a vector of used pipeline resources,
/// and a vector of instructions that transitioned to the ready state as a
/// result of this event.
- void
- issueInstruction(InstRef &IR,
- llvm::SmallVectorImpl<std::pair<ResourceRef, double>> &Used,
- llvm::SmallVectorImpl<InstRef> &Ready);
+ void issueInstruction(
+ InstRef &IR,
+ llvm::SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &Used,
+ llvm::SmallVectorImpl<InstRef> &Ready);
/// Returns true if IR has to be issued immediately, or if IR is a zero
/// latency instruction.
Modified: llvm/trunk/tools/llvm-mca/include/Stages/ExecuteStage.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/Stages/ExecuteStage.h?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/Stages/ExecuteStage.h (original)
+++ llvm/trunk/tools/llvm-mca/include/Stages/ExecuteStage.h Tue Sep 11 11:47:48 2018
@@ -59,9 +59,9 @@ public:
llvm::Error cycleStart() override;
llvm::Error execute(InstRef &IR) override;
- void
- notifyInstructionIssued(const InstRef &IR,
- llvm::ArrayRef<std::pair<ResourceRef, double>> Used);
+ void notifyInstructionIssued(
+ const InstRef &IR,
+ llvm::ArrayRef<std::pair<ResourceRef, ResourceCycles>> Used);
void notifyInstructionExecuted(const InstRef &IR);
void notifyInstructionReady(const InstRef &IR);
void notifyResourceAvailable(const ResourceRef &RR);
Modified: llvm/trunk/tools/llvm-mca/include/Stages/InstructionTables.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/Stages/InstructionTables.h?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/Stages/InstructionTables.h (original)
+++ llvm/trunk/tools/llvm-mca/include/Stages/InstructionTables.h Tue Sep 11 11:47:48 2018
@@ -28,7 +28,7 @@ namespace mca {
class InstructionTables final : public Stage {
const llvm::MCSchedModel &SM;
InstrBuilder &IB;
- llvm::SmallVector<std::pair<ResourceRef, double>, 4> UsedResources;
+ llvm::SmallVector<std::pair<ResourceRef, ResourceCycles>, 4> UsedResources;
public:
InstructionTables(const llvm::MCSchedModel &Model, InstrBuilder &Builder)
Modified: llvm/trunk/tools/llvm-mca/include/Support.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/Support.h?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/Support.h (original)
+++ llvm/trunk/tools/llvm-mca/include/Support.h Tue Sep 11 11:47:48 2018
@@ -21,6 +21,46 @@
namespace mca {
+/// This class represents the number of cycles per resource (fractions of
+/// cycles). That quantity is managed here as a ratio, and accessed via the
+/// double cast-operator below. The two quantities, number of cycles and
+/// number of resources, are kept separate. This is used by the
+/// ResourcePressureView to calculate the average resource cycles
+/// per instruction/iteration.
+class ResourceCycles {
+ unsigned Numerator, Denominator;
+
+public:
+ ResourceCycles() : Numerator(0), Denominator(1) {}
+ ResourceCycles(unsigned Cycles, unsigned ResourceUnits = 1)
+ : Numerator(Cycles), Denominator(ResourceUnits) {}
+
+ operator double() const {
+ assert(Denominator && "Invalid denominator (must be non-zero).");
+ return (Denominator == 1) ? Numerator : (double)Numerator / Denominator;
+ }
+
+ // Add the components of RHS to this instance. Instead of calculating
+ // the final value here, we keep track of the numerator and denominator
+ // separately, to reduce floating point error.
+ ResourceCycles &operator+=(const ResourceCycles &RHS) {
+ if (Denominator == RHS.Denominator)
+ Numerator += RHS.Numerator;
+ else {
+ // Create a common denominator for LHS and RHS by calculating the least
+ // common multiple from the GCD.
+ unsigned GCD =
+ llvm::GreatestCommonDivisor64(Denominator, RHS.Denominator);
+ unsigned LCM = (Denominator * RHS.Denominator) / GCD;
+ unsigned LHSNumerator = Numerator * (LCM / Denominator);
+ unsigned RHSNumerator = RHS.Numerator * (LCM / RHS.Denominator);
+ Numerator = LHSNumerator + RHSNumerator;
+ Denominator = LCM;
+ }
+ return *this;
+ }
+};
+
/// Populates vector Masks with processor resource masks.
///
/// The number of bits set in a mask depends on the processor resource type.
Modified: llvm/trunk/tools/llvm-mca/lib/HardwareUnits/ResourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/HardwareUnits/ResourceManager.cpp?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/HardwareUnits/ResourceManager.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/HardwareUnits/ResourceManager.cpp Tue Sep 11 11:47:48 2018
@@ -247,7 +247,7 @@ bool ResourceManager::mustIssueImmediate
void ResourceManager::issueInstruction(
const InstrDesc &Desc,
- SmallVectorImpl<std::pair<ResourceRef, double>> &Pipes) {
+ SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &Pipes) {
for (const std::pair<uint64_t, ResourceUsage> &R : Desc.Resources) {
const CycleSegment &CS = R.second.CS;
if (!CS.size()) {
@@ -263,8 +263,8 @@ void ResourceManager::issueInstruction(
// Replace the resource mask with a valid processor resource index.
const ResourceState &RS = *Resources[getResourceStateIndex(Pipe.first)];
Pipe.first = RS.getProcResourceID();
- Pipes.emplace_back(
- std::pair<ResourceRef, double>(Pipe, static_cast<double>(CS.size())));
+ Pipes.emplace_back(std::pair<ResourceRef, ResourceCycles>(
+ Pipe, ResourceCycles(CS.size())));
} else {
assert((countPopulation(R.first) > 1) && "Expected a group!");
// Mark this group as reserved.
Modified: llvm/trunk/tools/llvm-mca/lib/HardwareUnits/Scheduler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/HardwareUnits/Scheduler.cpp?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/HardwareUnits/Scheduler.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/HardwareUnits/Scheduler.cpp Tue Sep 11 11:47:48 2018
@@ -66,7 +66,7 @@ Scheduler::Status Scheduler::isAvailable
void Scheduler::issueInstructionImpl(
InstRef &IR,
- SmallVectorImpl<std::pair<ResourceRef, double>> &UsedResources) {
+ SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &UsedResources) {
Instruction *IS = IR.getInstruction();
const InstrDesc &D = IS->getDesc();
@@ -86,7 +86,8 @@ void Scheduler::issueInstructionImpl(
// Release the buffered resources and issue the instruction.
void Scheduler::issueInstruction(
- InstRef &IR, SmallVectorImpl<std::pair<ResourceRef, double>> &UsedResources,
+ InstRef &IR,
+ SmallVectorImpl<std::pair<ResourceRef, ResourceCycles>> &UsedResources,
SmallVectorImpl<InstRef> &ReadyInstructions) {
const Instruction &Inst = *IR.getInstruction();
bool HasDependentUsers = Inst.hasDependentUsers();
Modified: llvm/trunk/tools/llvm-mca/lib/Stages/ExecuteStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/Stages/ExecuteStage.cpp?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/Stages/ExecuteStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/Stages/ExecuteStage.cpp Tue Sep 11 11:47:48 2018
@@ -53,11 +53,11 @@ bool ExecuteStage::isAvailable(const Ins
}
Error ExecuteStage::issueInstruction(InstRef &IR) {
- SmallVector<std::pair<ResourceRef, double>, 4> Used;
+ SmallVector<std::pair<ResourceRef, ResourceCycles>, 4> Used;
SmallVector<InstRef, 4> Ready;
HWS.issueInstruction(IR, Used, Ready);
- notifyReservedOrReleasedBuffers(IR, /* Reserved */false);
+ notifyReservedOrReleasedBuffers(IR, /* Reserved */ false);
notifyInstructionIssued(IR, Used);
if (IR.getInstruction()->isExecuted()) {
notifyInstructionExecuted(IR);
@@ -120,7 +120,7 @@ Error ExecuteStage::execute(InstRef &IR)
// be released after MCIS is issued, and all the ResourceCycles for those
// units have been consumed.
HWS.dispatch(IR);
- notifyReservedOrReleasedBuffers(IR, /* Reserved */true);
+ notifyReservedOrReleasedBuffers(IR, /* Reserved */ true);
if (!HWS.isReady(IR))
return ErrorSuccess();
@@ -156,10 +156,10 @@ void ExecuteStage::notifyResourceAvailab
}
void ExecuteStage::notifyInstructionIssued(
- const InstRef &IR, ArrayRef<std::pair<ResourceRef, double>> Used) {
+ const InstRef &IR, ArrayRef<std::pair<ResourceRef, ResourceCycles>> Used) {
LLVM_DEBUG({
dbgs() << "[E] Instruction Issued: #" << IR << '\n';
- for (const std::pair<ResourceRef, unsigned> &Resource : Used) {
+ for (const std::pair<ResourceRef, ResourceCycles> &Resource : Used) {
dbgs() << "[E] Resource Used: [" << Resource.first.first << '.'
<< Resource.first.second << "], ";
dbgs() << "cycles: " << Resource.second << '\n';
Modified: llvm/trunk/tools/llvm-mca/lib/Stages/InstructionTables.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/Stages/InstructionTables.cpp?rev=341980&r1=341979&r2=341980&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/Stages/InstructionTables.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/Stages/InstructionTables.cpp Tue Sep 11 11:47:48 2018
@@ -31,17 +31,17 @@ Error InstructionTables::execute(InstRef
// Skip zero-cycle resources (i.e., unused resources).
if (!Resource.second.size())
continue;
- double Cycles = static_cast<double>(Resource.second.size());
+ unsigned Cycles = Resource.second.size();
unsigned Index = std::distance(
Masks.begin(), std::find(Masks.begin(), Masks.end(), Resource.first));
const MCProcResourceDesc &ProcResource = *SM.getProcResource(Index);
unsigned NumUnits = ProcResource.NumUnits;
if (!ProcResource.SubUnitsIdxBegin) {
// The number of cycles consumed by each unit.
- Cycles /= NumUnits;
for (unsigned I = 0, E = NumUnits; I < E; ++I) {
ResourceRef ResourceUnit = std::make_pair(Index, 1U << I);
- UsedResources.emplace_back(std::make_pair(ResourceUnit, Cycles));
+ UsedResources.emplace_back(
+ std::make_pair(ResourceUnit, ResourceCycles(Cycles, NumUnits)));
}
continue;
}
@@ -53,10 +53,10 @@ Error InstructionTables::execute(InstRef
unsigned SubUnitIdx = ProcResource.SubUnitsIdxBegin[I1];
const MCProcResourceDesc &SubUnit = *SM.getProcResource(SubUnitIdx);
// Compute the number of cycles consumed by each resource unit.
- double RUCycles = Cycles / (NumUnits * SubUnit.NumUnits);
for (unsigned I2 = 0, E2 = SubUnit.NumUnits; I2 < E2; ++I2) {
ResourceRef ResourceUnit = std::make_pair(SubUnitIdx, 1U << I2);
- UsedResources.emplace_back(std::make_pair(ResourceUnit, RUCycles));
+ UsedResources.emplace_back(std::make_pair(
+ ResourceUnit, ResourceCycles(Cycles, NumUnits * SubUnit.NumUnits)));
}
}
}
More information about the llvm-commits
mailing list