Path: blob/main/contrib/llvm-project/llvm/lib/MCA/Support.cpp
35260 views
//===--------------------- Support.cpp --------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file implements a few helper functions used by various pipeline10/// components.11///12//===----------------------------------------------------------------------===//1314#include "llvm/MCA/Support.h"15#include "llvm/MC/MCSchedule.h"16#include <numeric>1718namespace llvm {19namespace mca {2021#define DEBUG_TYPE "llvm-mca"2223ReleaseAtCycles &ReleaseAtCycles::operator+=(const ReleaseAtCycles &RHS) {24if (Denominator == RHS.Denominator)25Numerator += RHS.Numerator;26else {27// Create a common denominator for LHS and RHS by calculating the least28// common multiple from the GCD.29unsigned GCD = std::gcd(Denominator, RHS.Denominator);30unsigned LCM = (Denominator * RHS.Denominator) / GCD;31unsigned LHSNumerator = Numerator * (LCM / Denominator);32unsigned RHSNumerator = RHS.Numerator * (LCM / RHS.Denominator);33Numerator = LHSNumerator + RHSNumerator;34Denominator = LCM;35}36return *this;37}3839void computeProcResourceMasks(const MCSchedModel &SM,40MutableArrayRef<uint64_t> Masks) {41unsigned ProcResourceID = 0;4243assert(Masks.size() == SM.getNumProcResourceKinds() &&44"Invalid number of elements");45// Resource at index 0 is the 'InvalidUnit'. Set an invalid mask for it.46Masks[0] = 0;4748// Create a unique bitmask for every processor resource unit.49for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {50const MCProcResourceDesc &Desc = *SM.getProcResource(I);51if (Desc.SubUnitsIdxBegin)52continue;53Masks[I] = 1ULL << ProcResourceID;54ProcResourceID++;55}5657// Create a unique bitmask for every processor resource group.58for (unsigned I = 1, E = SM.getNumProcResourceKinds(); I < E; ++I) {59const MCProcResourceDesc &Desc = *SM.getProcResource(I);60if (!Desc.SubUnitsIdxBegin)61continue;62Masks[I] = 1ULL << ProcResourceID;63for (unsigned U = 0; U < Desc.NumUnits; ++U) {64uint64_t OtherMask = Masks[Desc.SubUnitsIdxBegin[U]];65Masks[I] |= OtherMask;66}67ProcResourceID++;68}6970#ifndef NDEBUG71LLVM_DEBUG(dbgs() << "\nProcessor resource masks:"72<< "\n");73for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {74const MCProcResourceDesc &Desc = *SM.getProcResource(I);75LLVM_DEBUG(dbgs() << '[' << format_decimal(I,2) << "] " << " - "76<< format_hex(Masks[I],16) << " - "77<< Desc.Name << '\n');78}79#endif80}8182double computeBlockRThroughput(const MCSchedModel &SM, unsigned DispatchWidth,83unsigned NumMicroOps,84ArrayRef<unsigned> ProcResourceUsage) {85// The block throughput is bounded from above by the hardware dispatch86// throughput. That is because the DispatchWidth is an upper bound on the87// number of opcodes that can be part of a single dispatch group.88double Max = static_cast<double>(NumMicroOps) / DispatchWidth;8990// The block throughput is also limited by the amount of hardware parallelism.91// The number of available resource units affects the resource pressure92// distribution, as well as how many blocks can be executed every cycle.93for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {94unsigned ReleaseAtCycles = ProcResourceUsage[I];95if (!ReleaseAtCycles)96continue;9798const MCProcResourceDesc &MCDesc = *SM.getProcResource(I);99double Throughput = static_cast<double>(ReleaseAtCycles) / MCDesc.NumUnits;100Max = std::max(Max, Throughput);101}102103// The block reciprocal throughput is computed as the MAX of:104// - (NumMicroOps / DispatchWidth)105// - (NumUnits / ReleaseAtCycles) for every consumed processor resource.106return Max;107}108109} // namespace mca110} // namespace llvm111112113