1fa99cb64SMircea Trofin //===- RegAllocScore.cpp - evaluate regalloc policy quality ---------------===//
2fa99cb64SMircea Trofin //
3fa99cb64SMircea Trofin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fa99cb64SMircea Trofin // See https://llvm.org/LICENSE.txt for license information.
5fa99cb64SMircea Trofin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fa99cb64SMircea Trofin //
7fa99cb64SMircea Trofin //===----------------------------------------------------------------------===//
8fa99cb64SMircea Trofin /// Calculate a measure of the register allocation policy quality. This is used
9fa99cb64SMircea Trofin /// to construct a reward for the training of the ML-driven allocation policy.
10fa99cb64SMircea Trofin /// Currently, the score is the sum of the machine basic block frequency-weighed
11fa99cb64SMircea Trofin /// number of loads, stores, copies, and remat instructions, each factored with
12fa99cb64SMircea Trofin /// a relative weight.
13fa99cb64SMircea Trofin //===----------------------------------------------------------------------===//
14fa99cb64SMircea Trofin
15fa99cb64SMircea Trofin #include "RegAllocScore.h"
16989f1c72Sserge-sans-paille #include "llvm/ADT/DenseMapInfo.h"
17ed98c1b3Sserge-sans-paille #include "llvm/ADT/STLForwardCompat.h"
18989f1c72Sserge-sans-paille #include "llvm/ADT/SetVector.h"
19ed98c1b3Sserge-sans-paille #include "llvm/ADT/ilist_iterator.h"
20ed98c1b3Sserge-sans-paille #include "llvm/CodeGen/MachineBasicBlock.h"
21ed98c1b3Sserge-sans-paille #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
22ed98c1b3Sserge-sans-paille #include "llvm/CodeGen/MachineFunction.h"
23ed98c1b3Sserge-sans-paille #include "llvm/CodeGen/MachineInstr.h"
24ed98c1b3Sserge-sans-paille #include "llvm/CodeGen/MachineInstrBundleIterator.h"
25fa99cb64SMircea Trofin #include "llvm/CodeGen/TargetInstrInfo.h"
26989f1c72Sserge-sans-paille #include "llvm/CodeGen/TargetSubtargetInfo.h"
27989f1c72Sserge-sans-paille #include "llvm/MC/MCInstrDesc.h"
28989f1c72Sserge-sans-paille #include "llvm/Support/CommandLine.h"
29fa99cb64SMircea Trofin
30fa99cb64SMircea Trofin using namespace llvm;
31fa99cb64SMircea Trofin cl::opt<double> CopyWeight("regalloc-copy-weight", cl::init(0.2), cl::Hidden);
32fa99cb64SMircea Trofin cl::opt<double> LoadWeight("regalloc-load-weight", cl::init(4.0), cl::Hidden);
33fa99cb64SMircea Trofin cl::opt<double> StoreWeight("regalloc-store-weight", cl::init(1.0), cl::Hidden);
34fa99cb64SMircea Trofin cl::opt<double> CheapRematWeight("regalloc-cheap-remat-weight", cl::init(0.2),
35fa99cb64SMircea Trofin cl::Hidden);
36fa99cb64SMircea Trofin cl::opt<double> ExpensiveRematWeight("regalloc-expensive-remat-weight",
37fa99cb64SMircea Trofin cl::init(1.0), cl::Hidden);
38fa99cb64SMircea Trofin #define DEBUG_TYPE "regalloc-score"
39fa99cb64SMircea Trofin
operator +=(const RegAllocScore & Other)40fa99cb64SMircea Trofin RegAllocScore &RegAllocScore::operator+=(const RegAllocScore &Other) {
41fa99cb64SMircea Trofin CopyCounts += Other.copyCounts();
42fa99cb64SMircea Trofin LoadCounts += Other.loadCounts();
43fa99cb64SMircea Trofin StoreCounts += Other.storeCounts();
44fa99cb64SMircea Trofin LoadStoreCounts += Other.loadStoreCounts();
45fa99cb64SMircea Trofin CheapRematCounts += Other.cheapRematCounts();
46fa99cb64SMircea Trofin ExpensiveRematCounts += Other.expensiveRematCounts();
47fa99cb64SMircea Trofin return *this;
48fa99cb64SMircea Trofin }
49fa99cb64SMircea Trofin
operator ==(const RegAllocScore & Other) const50fa99cb64SMircea Trofin bool RegAllocScore::operator==(const RegAllocScore &Other) const {
51fa99cb64SMircea Trofin return copyCounts() == Other.copyCounts() &&
52fa99cb64SMircea Trofin loadCounts() == Other.loadCounts() &&
53fa99cb64SMircea Trofin storeCounts() == Other.storeCounts() &&
54fa99cb64SMircea Trofin loadStoreCounts() == Other.loadStoreCounts() &&
55fa99cb64SMircea Trofin cheapRematCounts() == Other.cheapRematCounts() &&
56fa99cb64SMircea Trofin expensiveRematCounts() == Other.expensiveRematCounts();
57fa99cb64SMircea Trofin }
58fa99cb64SMircea Trofin
operator !=(const RegAllocScore & Other) const59fa99cb64SMircea Trofin bool RegAllocScore::operator!=(const RegAllocScore &Other) const {
60fa99cb64SMircea Trofin return !(*this == Other);
61fa99cb64SMircea Trofin }
62fa99cb64SMircea Trofin
getScore() const63fa99cb64SMircea Trofin double RegAllocScore::getScore() const {
64fa99cb64SMircea Trofin double Ret = 0.0;
65fa99cb64SMircea Trofin Ret += CopyWeight * copyCounts();
66fa99cb64SMircea Trofin Ret += LoadWeight * loadCounts();
67fa99cb64SMircea Trofin Ret += StoreWeight * storeCounts();
68fa99cb64SMircea Trofin Ret += (LoadWeight + StoreWeight) * loadStoreCounts();
69fa99cb64SMircea Trofin Ret += CheapRematWeight * cheapRematCounts();
70fa99cb64SMircea Trofin Ret += ExpensiveRematWeight * expensiveRematCounts();
71fa99cb64SMircea Trofin
72fa99cb64SMircea Trofin return Ret;
73fa99cb64SMircea Trofin }
74fa99cb64SMircea Trofin
75fa99cb64SMircea Trofin RegAllocScore
calculateRegAllocScore(const MachineFunction & MF,const MachineBlockFrequencyInfo & MBFI)76fa99cb64SMircea Trofin llvm::calculateRegAllocScore(const MachineFunction &MF,
77*8d0383ebSMatt Arsenault const MachineBlockFrequencyInfo &MBFI) {
78fa99cb64SMircea Trofin return calculateRegAllocScore(
79fa99cb64SMircea Trofin MF,
80fa99cb64SMircea Trofin [&](const MachineBasicBlock &MBB) {
81fa99cb64SMircea Trofin return MBFI.getBlockFreqRelativeToEntryBlock(&MBB);
82fa99cb64SMircea Trofin },
83fa99cb64SMircea Trofin [&](const MachineInstr &MI) {
84fa99cb64SMircea Trofin return MF.getSubtarget().getInstrInfo()->isTriviallyReMaterializable(
85*8d0383ebSMatt Arsenault MI);
86fa99cb64SMircea Trofin });
87fa99cb64SMircea Trofin }
88fa99cb64SMircea Trofin
calculateRegAllocScore(const MachineFunction & MF,llvm::function_ref<double (const MachineBasicBlock &)> GetBBFreq,llvm::function_ref<bool (const MachineInstr &)> IsTriviallyRematerializable)89fa99cb64SMircea Trofin RegAllocScore llvm::calculateRegAllocScore(
90fa99cb64SMircea Trofin const MachineFunction &MF,
91fa99cb64SMircea Trofin llvm::function_ref<double(const MachineBasicBlock &)> GetBBFreq,
92fa99cb64SMircea Trofin llvm::function_ref<bool(const MachineInstr &)>
93fa99cb64SMircea Trofin IsTriviallyRematerializable) {
94fa99cb64SMircea Trofin RegAllocScore Total;
95fa99cb64SMircea Trofin
96fa99cb64SMircea Trofin for (const MachineBasicBlock &MBB : MF) {
97fa99cb64SMircea Trofin double BlockFreqRelativeToEntrypoint = GetBBFreq(MBB);
98fa99cb64SMircea Trofin RegAllocScore MBBScore;
99fa99cb64SMircea Trofin
100fa99cb64SMircea Trofin for (const MachineInstr &MI : MBB) {
101fa99cb64SMircea Trofin if (MI.isDebugInstr() || MI.isKill() || MI.isInlineAsm()) {
102fa99cb64SMircea Trofin continue;
103fa99cb64SMircea Trofin }
104fa99cb64SMircea Trofin if (MI.isCopy()) {
105fa99cb64SMircea Trofin MBBScore.onCopy(BlockFreqRelativeToEntrypoint);
106fa99cb64SMircea Trofin } else if (IsTriviallyRematerializable(MI)) {
107fa99cb64SMircea Trofin if (MI.getDesc().isAsCheapAsAMove()) {
108fa99cb64SMircea Trofin MBBScore.onCheapRemat(BlockFreqRelativeToEntrypoint);
109fa99cb64SMircea Trofin } else {
110fa99cb64SMircea Trofin MBBScore.onExpensiveRemat(BlockFreqRelativeToEntrypoint);
111fa99cb64SMircea Trofin }
112fa99cb64SMircea Trofin } else if (MI.mayLoad() && MI.mayStore()) {
113fa99cb64SMircea Trofin MBBScore.onLoadStore(BlockFreqRelativeToEntrypoint);
114fa99cb64SMircea Trofin } else if (MI.mayLoad()) {
115fa99cb64SMircea Trofin MBBScore.onLoad(BlockFreqRelativeToEntrypoint);
116fa99cb64SMircea Trofin } else if (MI.mayStore()) {
117fa99cb64SMircea Trofin MBBScore.onStore(BlockFreqRelativeToEntrypoint);
118fa99cb64SMircea Trofin }
119fa99cb64SMircea Trofin }
120fa99cb64SMircea Trofin Total += MBBScore;
121fa99cb64SMircea Trofin }
122fa99cb64SMircea Trofin return Total;
123fa99cb64SMircea Trofin }
124