19#if defined(LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL) || defined(LLVM_HAVE_TFLITE)
45#include <unordered_map>
49#define DEBUG_TYPE "ml-regalloc"
52#if defined(LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL)
53#include "RegAllocEvictModel.h"
60 "regalloc-evict-interactive-channel-base",
cl::Hidden,
62 "Base file path for the interactive mode. The incoming filename should "
63 "have the name <regalloc-evict-interactive-channel-base>.in, while the "
64 "outgoing name should be "
65 "<regalloc-evict-interactive-channel-base>.out"));
69 cl::desc(
"The maximum number of times a live range can be "
70 "evicted before preventing it from being evicted"),
74#ifdef LLVM_HAVE_TFLITE
80 cl::desc(
"Training log for the register allocator eviction model"));
84 cl::desc(
"The model being trained for register allocation eviction"));
87 "regalloc-enable-development-features",
cl::Hidden,
88 cl::desc(
"Whether or not to enable features under development for the ML "
112 return "Register Allocation Pass Scoring";
134 "Register Allocation Scoring Pass",
false,
false)
142static const int OpcodeValueCutoff = 17716;
166#define RA_EVICT_FEATURES_LIST(M) \
167 M(int64_t, mask, PerLiveRangeShape, \
168 "boolean values, 0 for unavailable candidates (i.e. if a position is 0, " \
170 "can't be evicted)") \
171 M(int64_t, is_free, PerLiveRangeShape, \
172 "boolean values, 1 if this phys reg is actually free (no interferences)") \
173 M(float, nr_urgent, PerLiveRangeShape, \
174 "number of 'urgent' intervals, normalized. Urgent are those that are OK " \
175 "to break cascades") \
176 M(float, nr_broken_hints, PerLiveRangeShape, \
177 "if this position were evicted, how many broken hints would there be") \
178 M(int64_t, is_hint, PerLiveRangeShape, \
179 "is this a preferred phys reg for the candidate") \
180 M(int64_t, is_local, PerLiveRangeShape, \
181 "is this live range local to a basic block") \
182 M(float, nr_rematerializable, PerLiveRangeShape, \
183 "nr rematerializable ranges") \
184 M(float, nr_defs_and_uses, PerLiveRangeShape, \
185 "bb freq - weighed nr defs and uses") \
186 M(float, weighed_reads_by_max, PerLiveRangeShape, \
187 "bb freq - weighed nr of reads, normalized") \
188 M(float, weighed_writes_by_max, PerLiveRangeShape, \
189 "bb feq - weighed nr of writes, normalized") \
190 M(float, weighed_read_writes_by_max, PerLiveRangeShape, \
191 "bb freq - weighed nr of uses that are both read and writes, normalized") \
192 M(float, weighed_indvars_by_max, PerLiveRangeShape, \
193 "bb freq - weighed nr of uses that are indvars, normalized") \
194 M(float, hint_weights_by_max, PerLiveRangeShape, \
195 "bb freq - weighed nr of uses that are hints, normalized") \
196 M(float, start_bb_freq_by_max, PerLiveRangeShape, \
197 "the freq in the start block, normalized") \
198 M(float, end_bb_freq_by_max, PerLiveRangeShape, \
199 "freq of end block, normalized") \
200 M(float, hottest_bb_freq_by_max, PerLiveRangeShape, \
201 "hottest BB freq, normalized") \
202 M(float, liverange_size, PerLiveRangeShape, \
203 "size (instr index diff) of the LR") \
204 M(float, use_def_density, PerLiveRangeShape, \
205 "the max weight, as computed by the manual heuristic") \
206 M(int64_t, max_stage, PerLiveRangeShape, \
207 "largest stage of an interval in this LR") \
208 M(int64_t, min_stage, PerLiveRangeShape, \
209 "lowest stage of an interval in this LR") \
210 M(float, progress, {1}, "ratio of current queue size to initial size")
212#ifdef LLVM_HAVE_TFLITE
213#define RA_EVICT_FIRST_DEVELOPMENT_FEATURE(M) \
214 M(int64_t, instructions, InstructionsShape, \
215 "Opcodes of the instructions covered by the eviction problem")
217#define RA_EVICT_REST_DEVELOPMENT_FEATURES(M) \
218 M(int64_t, instructions_mapping, InstructionsMappingShape, \
219 "A binary matrix mapping LRs to instruction opcodes") \
220 M(float, mbb_frequencies, MBBFrequencyShape, \
221 "A vector of machine basic block frequencies") \
222 M(int64_t, mbb_mapping, InstructionsShape, \
223 "A vector of indices mapping instructions to MBBs")
225#define RA_EVICT_FIRST_DEVELOPMENT_FEATURE(M)
226#define RA_EVICT_REST_DEVELOPMENT_FEATURES(M)
233#define DecisionName "index_to_evict"
239#define _FEATURE_IDX_SIMPLE(_, name, __, ___) name
240#define _FEATURE_IDX(A, B, C, D) _FEATURE_IDX_SIMPLE(A, B, C, D),
242#ifdef LLVM_HAVE_TFLITE
249#undef _FEATURE_IDX_SIMPLE
256template <
typename T>
size_t getTotalSize(
const std::vector<int64_t> &Shape) {
257 size_t Ret =
sizeof(
T);
258 for (
const auto V : Shape)
264#define _RESET(TYPE, NAME, SHAPE, __) \
265 std::memset(Runner.getTensorUntyped(FeatureIDs::NAME), 0, \
266 getTotalSize<TYPE>(SHAPE));
277struct LIFeatureComponents {
281 double IndVarUpdates = 0;
282 double HintWeights = 0.0;
283 int64_t NumDefsAndUses = 0;
284 float HottestBlockFreq = 0.0;
285 bool IsRemat =
false;
288using CandidateRegList =
290using FeaturesListNormalizer =
314 tryFindEvictionCandidatePosition(
const LiveInterval &VirtReg,
316 unsigned OrderLimit,
uint8_t CostPerUseLimit,
337 int64_t IsHint, int64_t LocalIntfsCount,
float NumUrgent,
345 return getDefaultAdvisor().canEvictHintInterference(VirtReg, PhysReg,
349 const LIFeatureComponents &
363 std::bitset<FeatureIDs::FeatureCount> DoNotNormalize;
364 const float InitialQSize;
369 mutable std::unordered_map<unsigned, unsigned> VirtRegEvictionCounts;
371 void onEviction(
Register RegBeingEvicted)
const {
375 ++VirtRegEvictionCounts[RegBeingEvicted.
id()];
379 auto EvictionCountIt = VirtRegEvictionCounts.
find(
Reg.id());
380 if (EvictionCountIt != VirtRegEvictionCounts.end())
381 return EvictionCountIt->second;
386#define _DECL_FEATURES(type, name, shape, _) \
387 TensorSpec::createSpec<type>(#name, shape),
392class ReleaseModeEvictionAdvisorAnalysis final
395 ReleaseModeEvictionAdvisorAnalysis()
419 std::unique_ptr<RegAllocEvictionAdvisor>
423 Runner = std::make_unique<ReleaseModeModelRunner<CompiledModelType>>(
426 Runner = std::make_unique<InteractiveModelRunner>(
431 return std::make_unique<MLEvictAdvisor>(
432 MF,
RA, Runner.get(),
433 getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI(),
434 getAnalysis<MachineLoopInfoWrapperPass>().getLI());
436 std::unique_ptr<MLModelRunner> Runner;
444#ifdef LLVM_HAVE_TFLITE
445static const TensorSpec Reward = TensorSpec::createSpec<float>(
"reward", {1});
451#define _DECL_TRAIN_FEATURES(type, name, shape, _) \
452 TensorSpec::createSpec<type>(std::string("action_") + #name, shape),
454class DevelopmentModeEvictAdvisor :
public MLEvictAdvisor {
460 : MLEvictAdvisor(MF,
RA, Runner, MBFI,
Loops), Log(Log) {}
463 int64_t tryFindEvictionCandidatePosition(
465 unsigned OrderLimit,
uint8_t CostPerUseLimit,
471class DevelopmentModeEvictionAdvisorAnalysis final
474 DevelopmentModeEvictionAdvisorAnalysis()
480 TrainingInputFeatures = {
484 TensorSpec::createSpec<float>(
"action_discount", {1}),
485 TensorSpec::createSpec<int32_t>(
"action_step_type", {1}),
486 TensorSpec::createSpec<float>(
"action_reward", {1})};
489 TrainingInputFeatures = {
491 TensorSpec::createSpec<float>(
"action_discount", {1}),
492 TensorSpec::createSpec<int32_t>(
"action_step_type", {1}),
493 TensorSpec::createSpec<float>(
"action_reward", {1})};
503 if (!Log || !Log->hasAnyObservationForContext(MF.
getName()))
509 if (Log->currentContext() != MF.
getName()) {
511 "The training log context shouldn't have had changed.");
513 if (Log->hasObservationInProgress())
514 Log->logReward<
float>(GetReward());
519 std::vector<TensorSpec> TrainingInputFeatures;
529 if (ModelUnderTraining.empty() && TrainingLog.empty()) {
530 Ctx.
emitError(
"Regalloc development mode should be requested with at "
531 "least logging enabled and/or a training model");
534 if (ModelUnderTraining.empty())
535 Runner = std::make_unique<NoInferenceModelRunner>(Ctx,
InputFeatures);
537 Runner = ModelUnderTrainingRunner::createAndEnsureValid(
538 Ctx, ModelUnderTraining,
DecisionName, TrainingInputFeatures);
540 Ctx.
emitError(
"Regalloc: could not set up the model runner");
543 if (TrainingLog.empty())
546 auto OS = std::make_unique<raw_fd_ostream>(TrainingLog, EC);
548 M.getContext().emitError(EC.message() +
":" + TrainingLog);
552 if (
auto *MUTR = dyn_cast<ModelUnderTrainingRunner>(Runner.get()))
559 Log = std::make_unique<Logger>(std::move(
OS), LFS, Reward,
564 std::unique_ptr<RegAllocEvictionAdvisor>
569 Log->switchContext(MF.
getName());
570 return std::make_unique<DevelopmentModeEvictAdvisor>(
571 MF,
RA, Runner.get(),
572 getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI(),
573 getAnalysis<MachineLoopInfoWrapperPass>().getLI(), Log.get());
576 std::unique_ptr<MLModelRunner> Runner;
577 std::unique_ptr<Logger> Log;
585 unsigned NumUsedRegs = 0;
586 for (
unsigned I = 0, E =
MRI.getNumVirtRegs();
I != E; ++
I) {
588 if (!
MRI.reg_nodbg_empty(Reg))
591 return static_cast<float>(NumUsedRegs);
600 InitialQSize(MLEvictAdvisor::getInitialQueueSize(MF)) {
603 DoNotNormalize.set(FeatureIDs::mask);
604 DoNotNormalize.set(FeatureIDs::is_free);
605 DoNotNormalize.set(FeatureIDs::is_hint);
606 DoNotNormalize.set(FeatureIDs::is_local);
607 DoNotNormalize.set(FeatureIDs::min_stage);
608 DoNotNormalize.set(FeatureIDs::max_stage);
609 DoNotNormalize.set(FeatureIDs::progress);
612int64_t MLEvictAdvisor::tryFindEvictionCandidatePosition(
621bool MLEvictAdvisor::loadInterferenceFeatures(
632 const bool IsLocal = LIS->intervalIsInOneMBB(VirtReg);
633 int64_t LocalIntfs = 0;
634 float NumUrgent = 0.0f;
637 unsigned Cascade =
RA.getExtraInfo().getCascadeOrCurrentNext(VirtReg.
reg());
645 if (IFIntervals.empty() && InterferingIntervals.
empty())
649 InterferingIntervals.
append(IFIntervals.begin(), IFIntervals.end());
651 assert(Intf->reg().isVirtual() &&
652 "Only expecting virtual register interference from query");
659 if (FixedRegisters.
count(Intf->reg()))
661 if (
RA.getExtraInfo().getStage(*Intf) ==
RS_Done)
665 (Intf->isSpillable() ||
666 RegClassInfo.getNumAllocatableRegs(
MRI->getRegClass(VirtReg.
reg())) <
667 RegClassInfo.getNumAllocatableRegs(
668 MRI->getRegClass(Intf->reg())));
670 unsigned IntfCascade =
RA.getExtraInfo().getCascade(Intf->reg());
681 if (Cascade <= IntfCascade) {
687 LocalIntfs += (IsLocal && LIS->intervalIsInOneMBB(*Intf) &&
688 (!EnableLocalReassign || !canReassign(*Intf, PhysReg)));
693 extractFeatures(InterferingIntervals, Largest, Pos, IsHint, LocalIntfs,
694 NumUrgent, LRPosInfo);
698MCRegister MLEvictAdvisor::tryFindEvictionCandidate(
701 auto MaybeOrderLimit = getOrderLimit(VirtReg, Order, CostPerUseLimit);
702 if (!MaybeOrderLimit)
704 unsigned OrderLimit = *MaybeOrderLimit;
712 const bool MustFindEviction =
718 resetInputs(*Runner);
723 CandidateRegList Regs;
724 Regs.fill({0,
false});
730 FeaturesListNormalizer Largest(FeatureIDs::FeatureCount, 0.0);
742 assert(!Regs[Pos].second);
744 if (!canAllocatePhysReg(CostPerUseLimit, PhysReg)) {
747 if (loadInterferenceFeatures(VirtReg, PhysReg,
I.isHint(), FixedRegisters,
748 Largest, Pos, LRPosInfo)) {
750 Regs[Pos] = std::make_pair(PhysReg,
true);
755 assert(!MustFindEviction);
758 const size_t ValidPosLimit = Pos;
762 if (!MustFindEviction)
767 assert(InitialQSize > 0.0 &&
"We couldn't have gotten here if we had "
768 "nothing to allocate initially.");
769#ifdef LLVM_HAVE_TFLITE
774 auto *CurrentMachineInstruction =
775 LIS->getInstructionFromIndex(InputIndex);
776 if (!CurrentMachineInstruction) {
779 return CurrentMachineInstruction->getOpcode();
782 auto *CurrentMachineInstruction =
783 LIS->getInstructionFromIndex(InputIndex);
785 CurrentMachineInstruction->getParent());
788 auto *CurrentMachineInstruction =
789 LIS->getInstructionFromIndex(InputIndex);
790 return CurrentMachineInstruction->
getParent();
792 FeatureIDs::instructions, FeatureIDs::instructions_mapping,
793 FeatureIDs::mbb_frequencies, FeatureIDs::mbb_mapping,
794 LIS->getSlotIndexes()->getLastIndex());
798 for (
auto &V : Largest)
808 *Runner->
getTensor<
float>(FeatureIDs::progress) =
809 static_cast<float>(
RA.getQueueSize()) / InitialQSize;
812 size_t CandidatePos = tryFindEvictionCandidatePosition(
813 VirtReg, Order, OrderLimit, CostPerUseLimit, FixedRegisters);
816 assert(Regs[CandidatePos].second);
818 assert(!MustFindEviction);
821 assert(CandidatePos < ValidPosLimit);
828 onEviction(VirtReg.
reg());
830 for (
MCRegUnit Unit :
TRI->regunits(Regs[CandidatePos].first)) {
834 onEviction(Intf->reg());
839 return Regs[CandidatePos].first;
842const LIFeatureComponents &
843MLEvictAdvisor::getLIFeatureComponents(
const LiveInterval &LI)
const {
845 LIFeatureComponents
Empty;
846 auto I = CachedFeatures.insert(std::make_pair(
ID, Empty));
847 LIFeatureComponents &
Ret =
I.first->getSecond();
855 I =
MRI->reg_instr_nodbg_begin(LI.
reg()),
856 E =
MRI->reg_instr_nodbg_end();
860 ++
Ret.NumDefsAndUses;
864 if (
MI->isIdentityCopy() ||
MI->isImplicitDef())
868 std::tie(Reads,
Writes) =
MI->readsWritesVirtualRegister(LI.
reg());
871 Ret.HottestBlockFreq = std::max(Freq,
Ret.HottestBlockFreq);
877 auto *
MBB =
MI->getParent();
881 if (
Writes && IsExiting && LIS->isLiveOutOfMBB(LI,
MBB))
882 Ret.IndVarUpdates += Freq;
885 Ret.HintWeights += Freq;
894void MLEvictAdvisor::extractFeatures(
897 int64_t LocalIntfsCount,
float NumUrgent,
899 int64_t NumDefsAndUses = 0;
900 int64_t NumBrokenHints = 0;
904 double IndVarUpdates = 0.0;
905 double HintWeights = 0.0;
906 float StartBBFreq = 0.0;
907 float EndBBFreq = 0.0;
908 float HottestBlockFreq = 0.0;
909 int32_t NumRematerializable = 0;
910 float TotalWeight = 0.0;
912 SlotIndex EndSI = LIS->getSlotIndexes()->getZeroIndex();
913 SlotIndex StartSI = LIS->getSlotIndexes()->getLastIndex();
914 int64_t MaxStage = 0;
916 Intervals.
empty() ? 0 : std::numeric_limits<int64_t>::max();
918 for (
const auto *L : Intervals) {
920 MaxStage = std::max<int64_t>(
921 MaxStage,
static_cast<int64_t
>(
RA.getExtraInfo().getStage(LI)));
922 MinStage = std::min<int64_t>(
923 MinStage,
static_cast<int64_t
>(
RA.getExtraInfo().getStage(LI)));
925 TotalWeight = std::max(TotalWeight, LI.
weight());
932 const LIFeatureComponents &LIFC = getLIFeatureComponents(LI);
933 NumBrokenHints += VRM->hasPreferredPhys(LI.
reg());
935 NumDefsAndUses += LIFC.NumDefsAndUses;
936 HottestBlockFreq = std::max(HottestBlockFreq, LIFC.HottestBlockFreq);
941 IndVarUpdates += LIFC.IndVarUpdates;
943 HintWeights += LIFC.HintWeights;
944 NumRematerializable += LIFC.IsRemat;
947 for (
auto CurrentSegment : LI) {
954 if (!Intervals.empty()) {
957 if (EndSI >= LIS->getSlotIndexes()->getLastIndex())
958 EndSI = LIS->getSlotIndexes()->getLastIndex().
getPrevIndex();
964#define SET(ID, TYPE, VAL) \
966 Runner->getTensor<TYPE>(FeatureIDs::ID)[Pos] = static_cast<TYPE>(VAL); \
967 if (!DoNotNormalize.test(FeatureIDs::ID)) \
968 Largest[FeatureIDs::ID] = \
969 std::max(Largest[FeatureIDs::ID], static_cast<float>(VAL)); \
971 SET(mask, int64_t, 1);
972 SET(is_free, int64_t, Intervals.empty());
973 SET(nr_urgent,
float, NumUrgent);
974 SET(nr_broken_hints,
float, NumBrokenHints);
975 SET(is_hint, int64_t, IsHint);
976 SET(is_local, int64_t, LocalIntfsCount);
977 SET(nr_rematerializable,
float, NumRematerializable);
978 SET(nr_defs_and_uses,
float, NumDefsAndUses);
979 SET(weighed_reads_by_max,
float, R);
980 SET(weighed_writes_by_max,
float, W);
981 SET(weighed_read_writes_by_max,
float, RW);
982 SET(weighed_indvars_by_max,
float, IndVarUpdates);
983 SET(hint_weights_by_max,
float, HintWeights);
984 SET(start_bb_freq_by_max,
float, StartBBFreq);
985 SET(end_bb_freq_by_max,
float, EndBBFreq);
986 SET(hottest_bb_freq_by_max,
float, HottestBlockFreq);
987 SET(liverange_size,
float,
Size);
988 SET(use_def_density,
float, TotalWeight);
989 SET(max_stage, int64_t, MaxStage);
990 SET(min_stage, int64_t, MinStage);
999 const int InstructionsIndex,
const int InstructionsMappingIndex,
1000 const int MBBFreqIndex,
const int MBBMappingIndex,
1018 LRPosInfo.
begin(), LRPosInfo.
end(),
1020 size_t InstructionIndex = 0;
1021 size_t CurrentSegmentIndex = 0;
1022 SlotIndex CurrentIndex = LRPosInfo[0].Begin;
1023 std::map<MachineBasicBlock *, size_t> VisitedMBBs;
1024 size_t CurrentMBBIndex = 0;
1036 while (CurrentIndex <= LRPosInfo[CurrentSegmentIndex].
End &&
1038 int CurrentOpcode = GetOpcode(CurrentIndex);
1040 if (CurrentOpcode == -1) {
1043 if (CurrentIndex >= LastIndex) {
1050 if (VisitedMBBs.count(CurrentMBBReference) == 0) {
1051 VisitedMBBs[CurrentMBBReference] = CurrentMBBIndex;
1055 GetMBBFreq, CurrentMBBReference, RegallocRunner,
1056 MBBFreqIndex, MBBMappingIndex);
1058 assert(LRPosInfo[CurrentSegmentIndex].Begin <= CurrentIndex);
1059 RegallocRunner->
getTensor<int64_t>(InstructionsIndex)[InstructionIndex] =
1060 CurrentOpcode < OpcodeValueCutoff ? CurrentOpcode : 0;
1062 auto CurrentSegmentPosition = LRPosInfo[CurrentSegmentIndex].Pos;
1064 InstructionsMappingIndex)[CurrentSegmentPosition *
1066 InstructionIndex] = 1;
1075 size_t OverlapCheckCurrentSegment = CurrentSegmentIndex + 1;
1076 while (OverlapCheckCurrentSegment < LRPosInfo.
size() &&
1077 LRPosInfo[OverlapCheckCurrentSegment].Begin <= CurrentIndex) {
1078 auto OverlapCurrentSegmentPosition =
1079 LRPosInfo[OverlapCheckCurrentSegment].Pos;
1080 if (LRPosInfo[OverlapCheckCurrentSegment].
End >= CurrentIndex) {
1082 InstructionsMappingIndex)[OverlapCurrentSegmentPosition *
1084 InstructionIndex] = 1;
1086 ++OverlapCheckCurrentSegment;
1089 if (CurrentIndex >= LastIndex) {
1096 if (CurrentSegmentIndex == LRPosInfo.
size() - 1 ||
1103 if (LRPosInfo[CurrentSegmentIndex + 1].Begin >
1104 LRPosInfo[CurrentSegmentIndex].
End) {
1105 CurrentIndex = LRPosInfo[CurrentSegmentIndex + 1].Begin;
1107 ++CurrentSegmentIndex;
1112 const SlotIndex CurrentIndex,
const size_t CurrentInstructionIndex,
1113 std::map<MachineBasicBlock *, size_t> &VisitedMBBs,
1116 const int MBBFreqIndex,
const int MBBMappingIndex) {
1117 size_t CurrentMBBIndex = VisitedMBBs[CurrentMBBReference];
1118 float CurrentMBBFreq = GetMBBFreq(CurrentIndex);
1120 RegallocRunner->
getTensor<
float>(MBBFreqIndex)[CurrentMBBIndex] =
1123 MBBMappingIndex)[CurrentInstructionIndex] = CurrentMBBIndex;
1128#ifdef LLVM_HAVE_TFLITE
1131 return new DevelopmentModeEvictionAdvisorAnalysis();
1134int64_t DevelopmentModeEvictAdvisor::tryFindEvictionCandidatePosition(
1136 unsigned OrderLimit,
uint8_t CostPerUseLimit,
1139 if (isa<ModelUnderTrainingRunner>(getRunner())) {
1140 Ret = MLEvictAdvisor::tryFindEvictionCandidatePosition(
1141 VirtReg, Order, OrderLimit, CostPerUseLimit, FixedRegisters);
1143 MCRegister PhysReg = getDefaultAdvisor().tryFindEvictionCandidate(
1144 VirtReg, Order, CostPerUseLimit, FixedRegisters);
1156 if (TrainingLog.empty())
1161 if (Log->hasObservationInProgress())
1162 Log->logReward<
float>(0.0);
1164 Log->startObservation();
1165 size_t CurrentFeature = 0;
1167 ? FeatureIDs::FeaturesWithDevelopmentCount
1168 : FeatureIDs::FeatureCount;
1169 for (; CurrentFeature <
FeatureCount; ++CurrentFeature) {
1170 Log->logTensorValue(CurrentFeature,
1171 reinterpret_cast<const char *
>(
1172 getRunner().getTensorUntyped(CurrentFeature)));
1174 if (
auto *MUTR = dyn_cast<ModelUnderTrainingRunner>(&getRunner()))
1175 for (
size_t I = 0;
I < MUTR->extraOutputsForLoggingSpecs().size();
1176 ++
I, ++CurrentFeature)
1177 Log->logTensorValue(
1179 reinterpret_cast<const char *
>(MUTR->getUntypedExtraOutputValue(
I)));
1181 Log->logTensorValue(CurrentFeature,
reinterpret_cast<const char *
>(&Ret));
1182 Log->endObservation();
1187 std::optional<float> CachedReward;
1188 auto GetReward = [&]() {
1190 CachedReward =
static_cast<float>(
1192 MF, getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI())
1194 return *CachedReward;
1197 getAnalysis<RegAllocEvictionAdvisorAnalysis>().logRewardIfNeeded(MF,
1199 getAnalysis<RegAllocPriorityAdvisorAnalysis>().logRewardIfNeeded(MF,
1206 return llvm::isEmbeddedModelEvaluatorValid<CompiledModelType>() ||
1208 ?
new ReleaseModeEvictionAdvisorAnalysis()
1213#if !defined(LLVM_HAVE_TFLITE)
unsigned const MachineRegisterInfo * MRI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
SmallVector< uint32_t, 0 > Writes
@ Available
We know the block is fully available. This is a fixpoint.
Module.h This file contains the declarations for the Module class.
static cl::opt< std::string > InteractiveChannelBaseName("inliner-interactive-channel-base", cl::Hidden, cl::desc("Base file path for the interactive mode. The incoming filename should " "have the name <inliner-interactive-channel-base>.in, while the " "outgoing name should be <inliner-interactive-channel-base>.out"))
static const bool EnableDevelopmentFeatures
static cl::opt< unsigned > MaxEvictionCount("mlregalloc-max-eviction-count", cl::Hidden, cl::desc("The maximum number of times a live range can be " "evicted before preventing it from being evicted"), cl::init(100))
#define RA_EVICT_FEATURES_LIST(M)
#define _FEATURE_IDX_SIMPLE(_, name, __, ___)
#define RA_EVICT_FIRST_DEVELOPMENT_FEATURE(M)
#define SET(ID, TYPE, VAL)
#define _RESET(TYPE, NAME, SHAPE, __)
#define RA_EVICT_REST_DEVELOPMENT_FEATURES(M)
static cl::opt< std::string > InteractiveChannelBaseName("regalloc-evict-interactive-channel-base", cl::Hidden, cl::desc("Base file path for the interactive mode. The incoming filename should " "have the name <regalloc-evict-interactive-channel-base>.in, while the " "outgoing name should be " "<regalloc-evict-interactive-channel-base>.out"))
#define _FEATURE_IDX(A, B, C, D)
#define _DECL_FEATURES(type, name, shape, _)
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SI optimize exec mask operations pre RA
Iterator getOrderLimitEnd(unsigned OrderLimit) const
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
iterator find(const_arg_type_t< KeyT > Val)
FunctionPass class - This class is used to implement most global optimizations.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
This is an important class for using LLVM in a threaded context.
void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
Query interferences between a single live virtual register and a live interval union.
const SmallVectorImpl< const LiveInterval * > & interferingVRegs(unsigned MaxInterferingRegs=std::numeric_limits< unsigned >::max())
LiveInterval - This class represents the liveness of a register, or stack slot.
bool isSpillable() const
isSpillable - Can this interval be spilled?
SlotIndex beginIndex() const
beginIndex - Return the lowest numbered slot covered.
SlotIndex endIndex() const
endNumber - return the maximum point of the range of the whole, exclusive.
@ IK_VirtReg
Virtual register interference.
Logging utility - given an ordered specification of features, and assuming a scalar reward,...
bool isLoopExiting(const BlockT *BB) const
True if terminator in the block can branch to another block that is outside of the current loop.
Represents a single loop in the control flow graph.
Wrapper class representing physical registers. Should be passed by value.
static constexpr unsigned NoRegister
MLModelRunner interface: abstraction of a mechanism for evaluating a ML model.
virtual void switchContext(StringRef Name)
T * getTensor(I FeatureID)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
double getBlockFreqRelativeToEntryBlock(const MachineBasicBlock *MBB) const
Compute the frequency of the block, relative to the entry block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
defusechain_iterator - This class provides iterator support for machine operands in the function that...
A Module instance is used to store all the information related to an LLVM module.
A mock class satisfying the interface expected by ReleaseModeModelRunner for its TGen parameter.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
ImmutableAnalysis abstraction for fetching the Eviction Advisor.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual std::unique_ptr< RegAllocEvictionAdvisor > getAdvisor(const MachineFunction &MF, const RAGreedy &RA)=0
Get an advisor for the given context (i.e. machine function, etc)
virtual void logRewardIfNeeded(const MachineFunction &MF, llvm::function_ref< float()> GetReward)
virtual bool canEvictHintInterference(const LiveInterval &VirtReg, MCRegister PhysReg, const SmallVirtRegSet &FixedRegisters) const =0
Find out if we can evict the live ranges occupying the given PhysReg, which is a hint (preferred regi...
virtual MCRegister tryFindEvictionCandidate(const LiveInterval &VirtReg, const AllocationOrder &Order, uint8_t CostPerUseLimit, const SmallVirtRegSet &FixedRegisters) const =0
Find a physical register that can be freed by evicting the FixedRegisters, or return NoRegister.
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
void getAnalysisUsage(AnalysisUsage &AU) const override
RegAllocReward analysis usage.
~RegAllocScoring() override=default
bool runOnMachineFunction(MachineFunction &) override
Performs this pass.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
constexpr unsigned id() const
SlotIndex - An opaque wrapper around machine indexes.
SlotIndex getNextIndex() const
Returns the next index.
int distance(SlotIndex other) const
Return the distance from this index to the given one.
SlotIndex getPrevIndex() const
Returns the previous index.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
static Register copyHint(const MachineInstr *MI, unsigned Reg, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI)
Return the preferred allocation register for reg, given a COPY instruction.
static bool isRematerializable(const LiveInterval &LI, const LiveIntervals &LIS, const VirtRegMap &VRM, const TargetInstrInfo &TII)
Determine if all values in LI are rematerializable.
An efficient, type-erasing, non-owning reference to a callable.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
static const int ModelMaxSupportedInstructionCount
static const int64_t ModelMaxSupportedMBBCount
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
void extractInstructionFeatures(llvm::SmallVectorImpl< LRStartEndInfo > &LRPosInfo, MLModelRunner *RegallocRunner, function_ref< int(SlotIndex)> GetOpcode, function_ref< float(SlotIndex)> GetMBBFreq, function_ref< MachineBasicBlock *(SlotIndex)> GetMBBReference, const int InstructionsIndex, const int InstructionsMappingIndex, const int MBBFreqIndex, const int MBBMappingIndex, const SlotIndex LastIndex)
static const TensorSpec DecisionSpec
RegAllocScore calculateRegAllocScore(const MachineFunction &MF, const MachineBlockFrequencyInfo &MBFI)
Calculate a score.
auto reverse(ContainerTy &&C)
const char *const DecisionName
static const std::vector< TensorSpec > InputFeatures
@ RS_Done
There is nothing more we can do to this live range.
FunctionPass * createRegAllocScoringPass()
When learning an eviction policy, extract score(reward) information, otherwise this does nothing.
void initializeRegAllocScoringPass(PassRegistry &)
RegAllocEvictionAdvisorAnalysis * createReleaseModeAdvisor()
RegAllocEvictionAdvisorAnalysis * createDevelopmentModeAdvisor()
cl::opt< unsigned > EvictInterferenceCutoff
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
void extractMBBFrequency(const SlotIndex CurrentIndex, const size_t CurrentInstructionIndex, std::map< MachineBasicBlock *, size_t > &VisitedMBBs, function_ref< float(SlotIndex)> GetMBBFreq, MachineBasicBlock *CurrentMBBReference, MLModelRunner *RegallocRunner, const int MBBFreqIndex, const int MBBMappingIndex)
static const int64_t NumberOfInterferences
static const std::vector< int64_t > PerLiveRangeShape
static const int64_t CandidateVirtRegPos
Implement std::hash so that hash_code can be used in STL containers.