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