| 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 | |
| 25 | using namespace llvm; |
| 26 | LLVM_ABI cl::opt<double> CopyWeight("regalloc-copy-weight" , cl::init(Val: 0.2), |
| 27 | cl::Hidden); |
| 28 | LLVM_ABI cl::opt<double> LoadWeight("regalloc-load-weight" , cl::init(Val: 4.0), |
| 29 | cl::Hidden); |
| 30 | LLVM_ABI cl::opt<double> StoreWeight("regalloc-store-weight" , cl::init(Val: 1.0), |
| 31 | cl::Hidden); |
| 32 | LLVM_ABI cl::opt<double> CheapRematWeight("regalloc-cheap-remat-weight" , |
| 33 | cl::init(Val: 0.2), cl::Hidden); |
| 34 | LLVM_ABI cl::opt<double> ExpensiveRematWeight("regalloc-expensive-remat-weight" , |
| 35 | cl::init(Val: 1.0), cl::Hidden); |
| 36 | #define DEBUG_TYPE "regalloc-score" |
| 37 | |
| 38 | RegAllocScore &RegAllocScore::operator+=(const RegAllocScore &Other) { |
| 39 | CopyCounts += Other.copyCounts(); |
| 40 | LoadCounts += Other.loadCounts(); |
| 41 | StoreCounts += Other.storeCounts(); |
| 42 | LoadStoreCounts += Other.loadStoreCounts(); |
| 43 | CheapRematCounts += Other.cheapRematCounts(); |
| 44 | ExpensiveRematCounts += Other.expensiveRematCounts(); |
| 45 | return *this; |
| 46 | } |
| 47 | |
| 48 | bool RegAllocScore::operator==(const RegAllocScore &Other) const { |
| 49 | return copyCounts() == Other.copyCounts() && |
| 50 | loadCounts() == Other.loadCounts() && |
| 51 | storeCounts() == Other.storeCounts() && |
| 52 | loadStoreCounts() == Other.loadStoreCounts() && |
| 53 | cheapRematCounts() == Other.cheapRematCounts() && |
| 54 | expensiveRematCounts() == Other.expensiveRematCounts(); |
| 55 | } |
| 56 | |
| 57 | bool RegAllocScore::operator!=(const RegAllocScore &Other) const { |
| 58 | return !(*this == Other); |
| 59 | } |
| 60 | |
| 61 | double RegAllocScore::getScore() const { |
| 62 | double Ret = 0.0; |
| 63 | Ret += CopyWeight * copyCounts(); |
| 64 | Ret += LoadWeight * loadCounts(); |
| 65 | Ret += StoreWeight * storeCounts(); |
| 66 | Ret += (LoadWeight + StoreWeight) * loadStoreCounts(); |
| 67 | Ret += CheapRematWeight * cheapRematCounts(); |
| 68 | Ret += ExpensiveRematWeight * expensiveRematCounts(); |
| 69 | |
| 70 | return Ret; |
| 71 | } |
| 72 | |
| 73 | RegAllocScore |
| 74 | llvm::calculateRegAllocScore(const MachineFunction &MF, |
| 75 | const MachineBlockFrequencyInfo &MBFI) { |
| 76 | return calculateRegAllocScore( |
| 77 | MF, |
| 78 | GetBBFreq: [&](const MachineBasicBlock &MBB) { |
| 79 | return MBFI.getBlockFreqRelativeToEntryBlock(MBB: &MBB); |
| 80 | }, |
| 81 | IsTriviallyRematerializable: [&](const MachineInstr &MI) { |
| 82 | return MF.getSubtarget().getInstrInfo()->isTriviallyReMaterializable( |
| 83 | MI); |
| 84 | }); |
| 85 | } |
| 86 | |
| 87 | RegAllocScore llvm::calculateRegAllocScore( |
| 88 | const MachineFunction &MF, |
| 89 | llvm::function_ref<double(const MachineBasicBlock &)> GetBBFreq, |
| 90 | llvm::function_ref<bool(const MachineInstr &)> |
| 91 | IsTriviallyRematerializable) { |
| 92 | RegAllocScore Total; |
| 93 | |
| 94 | for (const MachineBasicBlock &MBB : MF) { |
| 95 | double BlockFreqRelativeToEntrypoint = GetBBFreq(MBB); |
| 96 | RegAllocScore MBBScore; |
| 97 | |
| 98 | for (const MachineInstr &MI : MBB) { |
| 99 | if (MI.isDebugInstr() || MI.isKill() || MI.isInlineAsm()) { |
| 100 | continue; |
| 101 | } |
| 102 | if (MI.isCopy()) { |
| 103 | MBBScore.onCopy(Freq: BlockFreqRelativeToEntrypoint); |
| 104 | } else if (IsTriviallyRematerializable(MI)) { |
| 105 | if (MI.getDesc().isAsCheapAsAMove()) { |
| 106 | MBBScore.onCheapRemat(Freq: BlockFreqRelativeToEntrypoint); |
| 107 | } else { |
| 108 | MBBScore.onExpensiveRemat(Freq: BlockFreqRelativeToEntrypoint); |
| 109 | } |
| 110 | } else if (MI.mayLoad() && MI.mayStore()) { |
| 111 | MBBScore.onLoadStore(Freq: BlockFreqRelativeToEntrypoint); |
| 112 | } else if (MI.mayLoad()) { |
| 113 | MBBScore.onLoad(Freq: BlockFreqRelativeToEntrypoint); |
| 114 | } else if (MI.mayStore()) { |
| 115 | MBBScore.onStore(Freq: BlockFreqRelativeToEntrypoint); |
| 116 | } |
| 117 | } |
| 118 | Total += MBBScore; |
| 119 | } |
| 120 | return Total; |
| 121 | } |
| 122 | |