xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/RegAllocScore.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 
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 
470eae32dcSDimitry 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 
560eae32dcSDimitry Andric bool RegAllocScore::operator!=(const RegAllocScore &Other) const {
570eae32dcSDimitry Andric   return !(*this == Other);
580eae32dcSDimitry Andric }
590eae32dcSDimitry Andric 
600eae32dcSDimitry 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
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 
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