10eae32dcSDimitry Andric //===- RegAllocScore.cpp - evaluate regalloc policy quality ---------------===//
20eae32dcSDimitry Andric //
30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60eae32dcSDimitry Andric //
70eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
80eae32dcSDimitry Andric /// Calculate a measure of the register allocation policy quality. This is used
90eae32dcSDimitry Andric /// to construct a reward for the training of the ML-driven allocation policy.
100eae32dcSDimitry Andric /// Currently, the score is the sum of the machine basic block frequency-weighed
110eae32dcSDimitry Andric /// number of loads, stores, copies, and remat instructions, each factored with
120eae32dcSDimitry Andric /// a relative weight.
130eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
140eae32dcSDimitry Andric
150eae32dcSDimitry Andric #include "RegAllocScore.h"
1681ad6265SDimitry Andric #include "llvm/ADT/ilist_iterator.h"
1781ad6265SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
1881ad6265SDimitry Andric #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
1981ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
2081ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
2181ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstrBundleIterator.h"
220eae32dcSDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
2381ad6265SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
2481ad6265SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
2581ad6265SDimitry Andric #include "llvm/Support/CommandLine.h"
260eae32dcSDimitry Andric
270eae32dcSDimitry Andric using namespace llvm;
280eae32dcSDimitry Andric cl::opt<double> CopyWeight("regalloc-copy-weight", cl::init(0.2), cl::Hidden);
290eae32dcSDimitry Andric cl::opt<double> LoadWeight("regalloc-load-weight", cl::init(4.0), cl::Hidden);
300eae32dcSDimitry Andric cl::opt<double> StoreWeight("regalloc-store-weight", cl::init(1.0), cl::Hidden);
310eae32dcSDimitry Andric cl::opt<double> CheapRematWeight("regalloc-cheap-remat-weight", cl::init(0.2),
320eae32dcSDimitry Andric cl::Hidden);
330eae32dcSDimitry Andric cl::opt<double> ExpensiveRematWeight("regalloc-expensive-remat-weight",
340eae32dcSDimitry Andric cl::init(1.0), cl::Hidden);
350eae32dcSDimitry Andric #define DEBUG_TYPE "regalloc-score"
360eae32dcSDimitry Andric
operator +=(const RegAllocScore & Other)370eae32dcSDimitry Andric RegAllocScore &RegAllocScore::operator+=(const RegAllocScore &Other) {
380eae32dcSDimitry Andric CopyCounts += Other.copyCounts();
390eae32dcSDimitry Andric LoadCounts += Other.loadCounts();
400eae32dcSDimitry Andric StoreCounts += Other.storeCounts();
410eae32dcSDimitry Andric LoadStoreCounts += Other.loadStoreCounts();
420eae32dcSDimitry Andric CheapRematCounts += Other.cheapRematCounts();
430eae32dcSDimitry Andric ExpensiveRematCounts += Other.expensiveRematCounts();
440eae32dcSDimitry Andric return *this;
450eae32dcSDimitry Andric }
460eae32dcSDimitry Andric
operator ==(const RegAllocScore & Other) const470eae32dcSDimitry Andric bool RegAllocScore::operator==(const RegAllocScore &Other) const {
480eae32dcSDimitry Andric return copyCounts() == Other.copyCounts() &&
490eae32dcSDimitry Andric loadCounts() == Other.loadCounts() &&
500eae32dcSDimitry Andric storeCounts() == Other.storeCounts() &&
510eae32dcSDimitry Andric loadStoreCounts() == Other.loadStoreCounts() &&
520eae32dcSDimitry Andric cheapRematCounts() == Other.cheapRematCounts() &&
530eae32dcSDimitry Andric expensiveRematCounts() == Other.expensiveRematCounts();
540eae32dcSDimitry Andric }
550eae32dcSDimitry Andric
operator !=(const RegAllocScore & Other) const560eae32dcSDimitry Andric bool RegAllocScore::operator!=(const RegAllocScore &Other) const {
570eae32dcSDimitry Andric return !(*this == Other);
580eae32dcSDimitry Andric }
590eae32dcSDimitry Andric
getScore() const600eae32dcSDimitry Andric double RegAllocScore::getScore() const {
610eae32dcSDimitry Andric double Ret = 0.0;
620eae32dcSDimitry Andric Ret += CopyWeight * copyCounts();
630eae32dcSDimitry Andric Ret += LoadWeight * loadCounts();
640eae32dcSDimitry Andric Ret += StoreWeight * storeCounts();
650eae32dcSDimitry Andric Ret += (LoadWeight + StoreWeight) * loadStoreCounts();
660eae32dcSDimitry Andric Ret += CheapRematWeight * cheapRematCounts();
670eae32dcSDimitry Andric Ret += ExpensiveRematWeight * expensiveRematCounts();
680eae32dcSDimitry Andric
690eae32dcSDimitry Andric return Ret;
700eae32dcSDimitry Andric }
710eae32dcSDimitry Andric
720eae32dcSDimitry Andric RegAllocScore
calculateRegAllocScore(const MachineFunction & MF,const MachineBlockFrequencyInfo & MBFI)730eae32dcSDimitry Andric llvm::calculateRegAllocScore(const MachineFunction &MF,
74*fcaf7f86SDimitry Andric const MachineBlockFrequencyInfo &MBFI) {
750eae32dcSDimitry Andric return calculateRegAllocScore(
760eae32dcSDimitry Andric MF,
770eae32dcSDimitry Andric [&](const MachineBasicBlock &MBB) {
780eae32dcSDimitry Andric return MBFI.getBlockFreqRelativeToEntryBlock(&MBB);
790eae32dcSDimitry Andric },
800eae32dcSDimitry Andric [&](const MachineInstr &MI) {
810eae32dcSDimitry Andric return MF.getSubtarget().getInstrInfo()->isTriviallyReMaterializable(
82*fcaf7f86SDimitry Andric MI);
830eae32dcSDimitry Andric });
840eae32dcSDimitry Andric }
850eae32dcSDimitry Andric
calculateRegAllocScore(const MachineFunction & MF,llvm::function_ref<double (const MachineBasicBlock &)> GetBBFreq,llvm::function_ref<bool (const MachineInstr &)> IsTriviallyRematerializable)860eae32dcSDimitry Andric RegAllocScore llvm::calculateRegAllocScore(
870eae32dcSDimitry Andric const MachineFunction &MF,
880eae32dcSDimitry Andric llvm::function_ref<double(const MachineBasicBlock &)> GetBBFreq,
890eae32dcSDimitry Andric llvm::function_ref<bool(const MachineInstr &)>
900eae32dcSDimitry Andric IsTriviallyRematerializable) {
910eae32dcSDimitry Andric RegAllocScore Total;
920eae32dcSDimitry Andric
930eae32dcSDimitry Andric for (const MachineBasicBlock &MBB : MF) {
940eae32dcSDimitry Andric double BlockFreqRelativeToEntrypoint = GetBBFreq(MBB);
950eae32dcSDimitry Andric RegAllocScore MBBScore;
960eae32dcSDimitry Andric
970eae32dcSDimitry Andric for (const MachineInstr &MI : MBB) {
980eae32dcSDimitry Andric if (MI.isDebugInstr() || MI.isKill() || MI.isInlineAsm()) {
990eae32dcSDimitry Andric continue;
1000eae32dcSDimitry Andric }
1010eae32dcSDimitry Andric if (MI.isCopy()) {
1020eae32dcSDimitry Andric MBBScore.onCopy(BlockFreqRelativeToEntrypoint);
1030eae32dcSDimitry Andric } else if (IsTriviallyRematerializable(MI)) {
1040eae32dcSDimitry Andric if (MI.getDesc().isAsCheapAsAMove()) {
1050eae32dcSDimitry Andric MBBScore.onCheapRemat(BlockFreqRelativeToEntrypoint);
1060eae32dcSDimitry Andric } else {
1070eae32dcSDimitry Andric MBBScore.onExpensiveRemat(BlockFreqRelativeToEntrypoint);
1080eae32dcSDimitry Andric }
1090eae32dcSDimitry Andric } else if (MI.mayLoad() && MI.mayStore()) {
1100eae32dcSDimitry Andric MBBScore.onLoadStore(BlockFreqRelativeToEntrypoint);
1110eae32dcSDimitry Andric } else if (MI.mayLoad()) {
1120eae32dcSDimitry Andric MBBScore.onLoad(BlockFreqRelativeToEntrypoint);
1130eae32dcSDimitry Andric } else if (MI.mayStore()) {
1140eae32dcSDimitry Andric MBBScore.onStore(BlockFreqRelativeToEntrypoint);
1150eae32dcSDimitry Andric }
1160eae32dcSDimitry Andric }
1170eae32dcSDimitry Andric Total += MBBScore;
1180eae32dcSDimitry Andric }
1190eae32dcSDimitry Andric return Total;
1200eae32dcSDimitry Andric }
121