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