[llvm] [MCA][ResourceManager] Fix a bug in the instruction issue logic. (PR #108386)
Andrea Di Biagio via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 12 06:48:59 PDT 2024
================
@@ -344,9 +344,90 @@ uint64_t ResourceManager::checkAvailability(const InstrDesc &Desc) const {
return BusyResourceMask;
}
-void ResourceManager::issueInstruction(
- const InstrDesc &Desc,
- SmallVectorImpl<std::pair<ResourceRef, ReleaseAtCycles>> &Pipes) {
+void ResourceManager::issueInstructionImpl(
+ const InstrDesc &Desc, SmallVectorImpl<ResourceWithCycles> &Pipes) {
+
+ // Step 1.
+ // - Issue writes to non-group resources.
+ // - Issue writes to groups with only a single resource unit available.
+ // - Update reserved groups (if any)
+ // - Add any remaining resource usage requests to a Worklist.
+ SmallVector<std::pair<uint64_t, ResourceUsage>, 4> Worklist;
+
+ using ResourceWithUsage = std::pair<uint64_t, ResourceUsage>;
+
+ for (const ResourceWithUsage &R : Desc.Resources) {
+ const CycleSegment &CS = R.second.CS;
+ if (!CS.size()) {
+ releaseResource(R.first);
+ continue;
+ }
+
+ assert(CS.begin() == 0 && "Invalid {Start, End} cycles!");
+ if (R.second.isReserved()) {
+ assert((llvm::popcount(R.first) > 1) && "Expected a group!");
+ // Mark this group as reserved.
+ assert(R.second.isReserved());
+ reserveResource(R.first);
+ BusyResources[ResourceRef(R.first, R.first)] += CS.size();
+ continue;
+ }
+
+ const ResourceState &RS = *Resources[getResourceStateIndex(R.first)];
+ if (RS.isAResourceGroup() && RS.getNumReadyUnits() > 1) {
+ Worklist.push_back(R);
+ continue;
+ }
+
+ ResourceRef Pipe = selectPipe(R.first);
+ use(Pipe);
+ BusyResources[Pipe] += CS.size();
+ Pipes.emplace_back(std::make_pair(Pipe, ReleaseAtCycles(CS.size())));
+ }
+
+ // Step 2.
+ // Prioritize writes to groups with less available resources.
+ // NOTE: this algorithm has quadratic complexity in the worst case scenario.
+ // On average, this algorithm is expected to perform quite well and always
+ // converge in very few iterations. That is mainly because instructions rarely
+ // consume more than two or three resource groups.
+
+ while (!Worklist.empty()) {
+ sort(Worklist, [&](const ResourceWithUsage &lhs,
+ const ResourceWithUsage &rhs) {
+ const ResourceState &lhsRS = *Resources[getResourceStateIndex(lhs.first)];
+ const ResourceState &rhsRS = *Resources[getResourceStateIndex(rhs.first)];
+ uint64_t lhsReadyUnits = lhsRS.getNumReadyUnits();
+ uint64_t rhsReadyUnits = rhsRS.getNumReadyUnits();
+ if (lhsReadyUnits == rhsReadyUnits)
+ return lhs.first < rhs.first;
+ return lhsReadyUnits < rhsReadyUnits;
+ });
+
+ SmallVector<ResourceWithUsage, 4> NewWorklist;
+
+ for (unsigned I = 0; I < Worklist.size(); ++I) {
----------------
adibiagio wrote:
Thanks. It should be fixed now.
https://github.com/llvm/llvm-project/pull/108386
More information about the llvm-commits
mailing list