LLVM 24.0.0git
MLRegAllocEvictAdvisor.cpp
Go to the documentation of this file.
1//===- MLRegAllocEvictAdvisor.cpp - ML eviction advisor -------------------===//
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//
9// Implementation of the ML eviction advisor and reward injection pass
10//
11//===----------------------------------------------------------------------===//
12
13#include "AllocationOrder.h"
14#include "RegAllocGreedy.h"
18#if defined(LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL) || defined(LLVM_HAVE_TFLITE)
21#endif
32#include "llvm/CodeGen/Passes.h"
35#include "llvm/IR/Module.h"
37#include "llvm/Pass.h"
40
41#include <bitset>
42#include <cmath>
43#include <memory>
44
45using namespace llvm;
46
47#define DEBUG_TYPE "ml-regalloc"
48
49// Generated header in release (AOT) mode
50#if defined(LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL)
51#include "RegAllocEvictModel.h"
52using CompiledModelType = RegAllocEvictModel;
53#else
55#endif
56
58#include "llvm/CodeGen/RegAllocEvictModels.h"
59
62#define MLGO_MODEL(CLASS_NAME, CLI_FLAG) CLASS_NAME,
63#include "llvm/CodeGen/RegAllocEvictModels.def"
64};
65
67 "regalloc-mlgo-model",
68 llvm::cl::desc("Select the MLGO model to execute for register allocation:"),
71 "Use standard heuristic")
72#define MLGO_MODEL(CLASS_NAME, CLI_FLAG) \
73 , clEnumValN(MLGORegAllocModelChoice::CLASS_NAME, CLI_FLAG, \
74 "Use the " CLI_FLAG " MLGO model")
75#include "llvm/CodeGen/RegAllocEvictModels.def"
76 ));
77
78static std::unique_ptr<MLModelRunner>
80 const std::vector<TensorSpec> &InputFeatures) {
83 return nullptr;
84#define MLGO_MODEL(CLASS_NAME, CLI_FLAG) \
85 case MLGORegAllocModelChoice::CLASS_NAME: \
86 return std::make_unique<EmitCModelRunner<CLASS_NAME>>(Ctx, InputFeatures);
87#include "llvm/CodeGen/RegAllocEvictModels.def"
88 }
89 llvm_unreachable("Unknown MLGO model type!");
90}
91
93 "regalloc-evict-interactive-channel-base", cl::Hidden,
95 "Base file path for the interactive mode. The incoming filename should "
96 "have the name <regalloc-evict-interactive-channel-base>.in, while the "
97 "outgoing name should be "
98 "<regalloc-evict-interactive-channel-base>.out"));
99
101 "mlregalloc-max-eviction-count", cl::Hidden,
102 cl::desc("The maximum number of times a live range can be "
103 "evicted before preventing it from being evicted"),
104 cl::init(100));
105
107 "mlregalloc-num-allocatable-regs", cl::Hidden,
108 cl::desc("The number of eviction candidates the model sees. The model has "
109 "one more column, for the live range seeking allocation"),
110 cl::init(32));
111
112// Options that only make sense in development mode
113#ifdef LLVM_HAVE_TFLITE
114#include "RegAllocScore.h"
116
117static cl::opt<std::string> TrainingLog(
118 "regalloc-training-log", cl::Hidden,
119 cl::desc("Training log for the register allocator eviction model"));
120
121static cl::opt<std::string> ModelUnderTraining(
122 "regalloc-model", cl::Hidden,
123 cl::desc("The model being trained for register allocation eviction"));
124
125#endif // #ifdef LLVM_HAVE_TFLITE
126
127/// The score injection pass.
128/// This pass calculates the score for a function and inserts it in the log, but
129/// this happens only in development mode. It's a no-op otherwise.
130namespace llvm {
132} // namespace llvm
133
134namespace {
135class RegAllocScoring : public MachineFunctionPass {
136public:
137 static char ID;
138
139 RegAllocScoring() : MachineFunctionPass(ID) {}
140
141 ~RegAllocScoring() override = default;
142
143 StringRef getPassName() const override {
144 return "Register Allocation Pass Scoring";
145 }
146
147 /// RegAllocReward analysis usage.
148 void getAnalysisUsage(AnalysisUsage &AU) const override {
149 AU.setPreservesAll();
150 AU.addRequired<RegAllocEvictionAdvisorAnalysisLegacy>();
151 AU.addRequired<RegAllocPriorityAdvisorAnalysisLegacy>();
152 AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
154 }
155
156 /// Performs this pass
157 bool runOnMachineFunction(MachineFunction &) override;
158};
159} // namespace
160
161char RegAllocScoring::ID = 0;
163 return new RegAllocScoring();
164}
165
166INITIALIZE_PASS(RegAllocScoring, "regallocscoringpass",
167 "Register Allocation Scoring Pass", false, false)
168
169// ===================================
170// Common ML Advisor declarations
171// ===================================
172namespace {
173// --------------
174// Features table
175// --------------
176// For each interfering live range (incl. the candidate) we collect a number of
177// features. However, because the features are of different types (and because
178// of ML best practices), we organize the tensors per feature, not per
179// candidate. Each such tensor has a scalar value corresponding to the
180// interferring live range at that position, in the order in AllocationOrder.
181// The last position corresponds to the virt reg seeking allocation.
182// Exception to all that is the progression feature, which is just a scalar (see
183// its documentation for details).
184// Note on naming: the "_by_max" are normalized using the largest value of that
185// tensor, as observed in the current decision making stage (i.e. for the
186// current call to the advisor's tryFindEvictionCandidate)
187//
188// The feature list format: type, name, shape, documentation.
189// Note: we can really just use int64 and float, hence the modeling of some
190// bools as int64 values.
191#define RA_EVICT_FEATURES_LIST(M) \
192 M(int64_t, mask, PerLiveRangeShape, \
193 "boolean values, 0 for unavailable candidates (i.e. if a position is 0, " \
194 "it " \
195 "can't be evicted)") \
196 M(int64_t, is_free, PerLiveRangeShape, \
197 "boolean values, 1 if this phys reg is actually free (no interferences)") \
198 M(float, nr_urgent, PerLiveRangeShape, \
199 "number of 'urgent' intervals, normalized. Urgent are those that are OK " \
200 "to break cascades") \
201 M(float, nr_broken_hints, PerLiveRangeShape, \
202 "if this position were evicted, how many broken hints would there be") \
203 M(int64_t, is_hint, PerLiveRangeShape, \
204 "is this a preferred phys reg for the candidate") \
205 M(int64_t, is_local, PerLiveRangeShape, \
206 "is this live range local to a basic block") \
207 M(float, nr_rematerializable, PerLiveRangeShape, \
208 "nr rematerializable ranges") \
209 M(float, nr_defs_and_uses, PerLiveRangeShape, \
210 "bb freq - weighed nr defs and uses") \
211 M(float, weighed_reads_by_max, PerLiveRangeShape, \
212 "bb freq - weighed nr of reads, normalized") \
213 M(float, weighed_writes_by_max, PerLiveRangeShape, \
214 "bb feq - weighed nr of writes, normalized") \
215 M(float, weighed_read_writes_by_max, PerLiveRangeShape, \
216 "bb freq - weighed nr of uses that are both read and writes, normalized") \
217 M(float, weighed_indvars_by_max, PerLiveRangeShape, \
218 "bb freq - weighed nr of uses that are indvars, normalized") \
219 M(float, hint_weights_by_max, PerLiveRangeShape, \
220 "bb freq - weighed nr of uses that are hints, normalized") \
221 M(float, start_bb_freq_by_max, PerLiveRangeShape, \
222 "the freq in the start block, normalized") \
223 M(float, end_bb_freq_by_max, PerLiveRangeShape, \
224 "freq of end block, normalized") \
225 M(float, hottest_bb_freq_by_max, PerLiveRangeShape, \
226 "hottest BB freq, normalized") \
227 M(float, liverange_size, PerLiveRangeShape, \
228 "size (instr index diff) of the LR") \
229 M(float, use_def_density, PerLiveRangeShape, \
230 "the max weight, as computed by the manual heuristic") \
231 M(int64_t, max_stage, PerLiveRangeShape, \
232 "largest stage of an interval in this LR") \
233 M(int64_t, min_stage, PerLiveRangeShape, \
234 "lowest stage of an interval in this LR") \
235 M(float, progress, {1}, "ratio of current queue size to initial size")
236
237// The model learns to pick one of the mask == 1 interferences. This is the
238// name of the output tensor. The contract with the model is that the output
239// will be guaranteed to be to a mask == 1 position. Using a macro here to
240// avoid 'not used' warnings (and keep cond compilation to a minimum)
241#define DecisionName "index_to_evict"
242static const TensorSpec DecisionSpec =
244
245// Named features index.
246enum FeatureIDs {
247#define _FEATURE_IDX_SIMPLE(_, name, __, ___) name
248#define _FEATURE_IDX(A, B, C, D) _FEATURE_IDX_SIMPLE(A, B, C, D),
250#undef _FEATURE_IDX
251#undef _FEATURE_IDX_SIMPLE
252};
253
254// The ML advisor will typically have a sparse input to the evaluator, because
255// various phys regs won't be available. It's easier (maintenance-wise) to
256// bulk-reset the state of the evaluator each time we are about to use it
257// again.
258void resetInputs(MLModelRunner &Runner, ArrayRef<TensorSpec> InputFeatures) {
259 for (auto [I, Spec] : enumerate(InputFeatures))
260 std::memset(Runner.getTensorUntyped(I), 0, Spec.getTotalTensorBufferSize());
261}
262
263// Per-live interval components that get aggregated into the feature values
264// that will be passed to the evaluator.
265struct LIFeatureComponents {
266 double R = 0;
267 double W = 0;
268 double RW = 0;
269 double IndVarUpdates = 0;
270 double HintWeights = 0.0;
271 int64_t NumDefsAndUses = 0;
272 float HottestBlockFreq = 0.0;
273 bool IsRemat = false;
274};
275
276// Inline capacity hint only, the real width comes from NumAllocatableRegs.
277static constexpr unsigned MaxColumnsCapacityHint = 40;
278
279using CandidateRegList =
280 SmallVector<std::pair<MCRegister, bool>, MaxColumnsCapacityHint>;
281using FeaturesListNormalizer =
283
284/// The ML evictor (commonalities between release and development mode)
285class MLEvictAdvisor : public RegAllocEvictionAdvisor {
286public:
287 MLEvictAdvisor(const MachineFunction &MF, const RAGreedy &RA,
289 const MachineBlockFrequencyInfo &MBFI,
290 const MachineLoopInfo &Loops);
291
292protected:
293 const RegAllocEvictionAdvisor &getDefaultAdvisor() const {
294 return static_cast<const RegAllocEvictionAdvisor &>(DefaultAdvisor);
295 }
296
297 // By convention the last column holds the virt reg seeking allocation.
299 const size_t NumColumns;
300 const size_t CandidateVirtRegPos = NumColumns - 1;
301
302 // The assumption is that if the Runner could not be constructed, we emit-ed
303 // error, and we shouldn't be asking for it here.
304 const MLModelRunner &getRunner() const { return *Runner; }
305
306 /// This just calls Evaluate on the Runner, but in the development mode
307 /// case, if we're just capturing the log of the default advisor, it needs
308 /// to call the latter instead, so we need to pass all the necessary
309 /// parameters for it. In the development case, it will also log.
310 virtual int64_t
311 tryFindEvictionCandidatePosition(const LiveInterval &VirtReg,
312 const AllocationOrder &Order,
313 unsigned OrderLimit, uint8_t CostPerUseLimit,
314 const SmallVirtRegSet &FixedRegisters) const;
315
316 /// Load the features of the given VirtReg (allocated or not) at column Pos,
317 /// but if that can't be evicted, return false instead.
318 bool
319 loadInterferenceFeatures(const LiveInterval &VirtReg, MCRegister PhysReg,
320 bool IsHint, const SmallVirtRegSet &FixedRegisters,
321 llvm::SmallVectorImpl<float> &Largest, size_t Pos,
322 SmallVectorImpl<LRStartEndInfo> &LRPosInfo) const;
323
324private:
325 static float getInitialQueueSize(const MachineFunction &MF);
326
328 const LiveInterval &VirtReg, const AllocationOrder &Order,
329 uint8_t CostPerUseLimit,
330 const SmallVirtRegSet &FixedRegisters) const override;
331
332 void extractFeatures(const SmallVectorImpl<const LiveInterval *> &Intervals,
333 llvm::SmallVectorImpl<float> &Largest, size_t Pos,
334 int64_t IsHint, int64_t LocalIntfsCount, float NumUrgent,
335 SmallVectorImpl<LRStartEndInfo> &LRPosInfo) const;
336
337 // Point-in-time: we didn't learn this, so we always delegate to the
338 // default.
340 const LiveInterval &VirtReg, MCRegister PhysReg,
341 const SmallVirtRegSet &FixedRegisters) const override {
342 return getDefaultAdvisor().canEvictHintInterference(VirtReg, PhysReg,
343 FixedRegisters);
344 }
345
346 const LIFeatureComponents &
347 getLIFeatureComponents(const LiveInterval &LI) const;
348
349 // Hold on to a default advisor for:
350 // 1) the implementation of canEvictHintInterference, because we didn't
351 // learn that nuance yet; 2) for bootstrapping (logging) in the development
352 // mode case.
353 const DefaultEvictionAdvisor DefaultAdvisor;
354 MLModelRunner *const Runner;
355 const MachineBlockFrequencyInfo &MBFI;
356 const MachineLoopInfo &Loops;
357
358 // Indices of those features we don't want to normalize.
359 // This could be static and shared, but its initialization is non-trivial.
360 std::bitset<FeatureIDs::FeatureCount> DoNotNormalize;
361 const float InitialQSize;
362
363 using RegID = unsigned;
364 mutable DenseMap<RegID, LIFeatureComponents> CachedFeatures;
365
366 mutable DenseMap<unsigned, unsigned> VirtRegEvictionCounts;
367
368 void onEviction(Register RegBeingEvicted) const {
369 // If we cannot find the virtual register in the map, we just assume it has
370 // not been evicted before and thus has a value of zero (which is what the
371 // subscript operator returns by default).
372 ++VirtRegEvictionCounts[RegBeingEvicted.id()];
373 }
374
375 unsigned getEvictionCount(Register Reg) const {
376 auto EvictionCountIt = VirtRegEvictionCounts.find(Reg.id());
377 if (EvictionCountIt != VirtRegEvictionCounts.end())
378 return EvictionCountIt->second;
379 return 0;
380 }
381};
382
383#define _DECL_FEATURES(type, name, shape, _) \
384 TensorSpec::createSpec<type>(#name, shape),
385
386// ===================================
387// Release (AOT) - specifics
388// ===================================
389/// Common provider for legacy and new pass managers.
390class ReleaseModeEvictionAdvisorProvider final
392public:
393 ReleaseModeEvictionAdvisorProvider(LLVMContext &Ctx)
394 : RegAllocEvictionAdvisorProvider(AdvisorMode::Release, Ctx) {
395 const std::vector<int64_t> PerLiveRangeShape{1, NumAllocatableRegs + 1};
400 }
401 // support for isa<> and dyn_cast.
402 static bool classof(const RegAllocEvictionAdvisorProvider *R) {
403 return R->getAdvisorMode() == AdvisorMode::Release;
404 }
405
406 std::unique_ptr<RegAllocEvictionAdvisor>
407 getAdvisor(const MachineFunction &MF, const RAGreedy &RA,
409 assert(MBFI && Loops &&
410 "Invalid provider state: must have analysis available");
411 if (!Runner)
412 return std::make_unique<DefaultEvictionAdvisor>(MF, RA);
413 return std::make_unique<MLEvictAdvisor>(MF, RA, Runner.get(), InputFeatures,
414 *MBFI, *Loops);
415 }
416
417private:
418 std::vector<TensorSpec> InputFeatures;
419 std::unique_ptr<MLModelRunner> Runner;
420};
421
422class ReleaseModeEvictionAdvisorAnalysisLegacy final
424public:
425 ReleaseModeEvictionAdvisorAnalysisLegacy()
426 : RegAllocEvictionAdvisorAnalysisLegacy(AdvisorMode::Release) {}
427
428 void logRewardIfNeeded(const MachineFunction &MF,
429 llvm::function_ref<float()> GetReward) override {
430 // No-op in release mode
431 }
432
433 bool doInitialization(Module &M) override {
434 Provider =
435 std::make_unique<ReleaseModeEvictionAdvisorProvider>(M.getContext());
436 return false;
437 }
438
439 static bool classof(const RegAllocEvictionAdvisorAnalysisLegacy *R) {
440 return R->getAdvisorMode() == AdvisorMode::Release;
441 }
442
443 void getAnalysisUsage(AnalysisUsage &AU) const override {
446 }
447};
448
449// ===================================
450// Development mode-specifics
451// ===================================
452//
453// Features we log
454#ifdef LLVM_HAVE_TFLITE
455static const TensorSpec Reward = TensorSpec::createSpec<float>("reward", {1});
456
457// Features we bind on the model. The tensor names have a prefix, and we also
458// need to include some tensors that are expected to be present by the
459// training algo.
460// TODO: can we just get rid of these?
461#define _DECL_TRAIN_FEATURES(type, name, shape, _) \
462 TensorSpec::createSpec<type>(std::string("action_") + #name, shape),
463
464class DevelopmentModeEvictAdvisor : public MLEvictAdvisor {
465public:
466 DevelopmentModeEvictAdvisor(const MachineFunction &MF, const RAGreedy &RA,
467 MLModelRunner *Runner,
469 const MachineBlockFrequencyInfo &MBFI,
470 const MachineLoopInfo &Loops, Logger *Log)
471 : MLEvictAdvisor(MF, RA, Runner, InputFeatures, MBFI, Loops), Log(Log) {}
472
473private:
474 int64_t tryFindEvictionCandidatePosition(
475 const LiveInterval &VirtReg, const AllocationOrder &Order,
476 unsigned OrderLimit, uint8_t CostPerUseLimit,
477 const SmallVirtRegSet &FixedRegisters) const override;
478
479 Logger *const Log;
480};
481
482class DevelopmentModeEvictionAdvisorProvider final
484public:
485 DevelopmentModeEvictionAdvisorProvider(LLVMContext &Ctx)
486 : RegAllocEvictionAdvisorProvider(AdvisorMode::Development, Ctx) {
487 // Picked up by RA_EVICT_FEATURES_LIST.
488 const std::vector<int64_t> PerLiveRangeShape{1, NumAllocatableRegs + 1};
490 TrainingInputFeatures = {
491 RA_EVICT_FEATURES_LIST(_DECL_TRAIN_FEATURES)
492 TensorSpec::createSpec<float>("action_discount", {1}),
493 TensorSpec::createSpec<int32_t>("action_step_type", {1}),
494 TensorSpec::createSpec<float>("action_reward", {1})};
495 if (ModelUnderTraining.empty() && TrainingLog.empty()) {
496 Ctx.emitError("Regalloc development mode should be requested with at "
497 "least logging enabled and/or a training model");
498 return;
499 }
500 if (ModelUnderTraining.empty())
501 Runner = std::make_unique<NoInferenceModelRunner>(Ctx, InputFeatures);
502 else
503 Runner = ModelUnderTrainingRunner::createAndEnsureValid(
504 Ctx, ModelUnderTraining, DecisionName, TrainingInputFeatures);
505 if (!Runner) {
506 Ctx.emitError("Regalloc: could not set up the model runner");
507 return;
508 }
509 if (TrainingLog.empty())
510 return;
511 std::error_code EC;
512 auto OS = std::make_unique<raw_fd_ostream>(TrainingLog, EC);
513 if (EC) {
514 Ctx.emitError(EC.message() + ":" + TrainingLog);
515 return;
516 }
517 std::vector<TensorSpec> LFS = InputFeatures;
518 if (auto *MUTR = dyn_cast<ModelUnderTrainingRunner>(Runner.get()))
519 append_range(LFS, MUTR->extraOutputsForLoggingSpecs());
520 // We always log the output; in particular, if we're not evaluating, we
521 // don't have an output spec json file. That's why we handle the
522 // 'normal' output separately.
523 LFS.push_back(DecisionSpec);
524
525 Log = std::make_unique<Logger>(std::move(OS), LFS, Reward,
526 /*IncludeReward*/ true);
527 return;
528 }
529
530 // support for isa<> and dyn_cast.
531 static bool classof(const RegAllocEvictionAdvisorProvider *R) {
532 return R->getAdvisorMode() == AdvisorMode::Development;
533 }
534
535 void logRewardIfNeeded(const MachineFunction &MF,
536 llvm::function_ref<float()> GetReward) override {
537 if (!Log)
538 return;
539 std::string Ctx = getContextName(MF);
540 if (!Log->hasAnyObservationForContext(Ctx))
541 return;
542 // The function pass manager would run all the function passes for a
543 // function, so we assume the last context belongs to this function. If
544 // this invariant ever changes, we can implement at that time switching
545 // contexts. At this point, it'd be an error
546 if (Log->currentContext() != Ctx) {
548 "The training log context shouldn't have had changed.");
549 }
550 if (Log->hasObservationInProgress())
551 Log->logReward<float>(GetReward());
552 }
553
554 std::unique_ptr<RegAllocEvictionAdvisor>
555 getAdvisor(const MachineFunction &MF, const RAGreedy &RA,
557 if (!Runner)
558 return nullptr;
559 if (Log && LastFunctionNumber != MF.getFunctionNumber()) {
560 LastFunctionNumber = MF.getFunctionNumber();
561 Log->switchContext(getContextName(MF));
562 }
563 assert(MBFI && Loops &&
564 "Invalid provider state: must have analysis available");
565 return std::make_unique<DevelopmentModeEvictAdvisor>(
566 MF, RA, Runner.get(), InputFeatures, *MBFI, *Loops, Log.get());
567 }
568
569private:
570 std::vector<TensorSpec> InputFeatures;
571 std::vector<TensorSpec> TrainingInputFeatures;
572
573 std::unique_ptr<MLModelRunner> Runner;
574 std::unique_ptr<Logger> Log;
575 std::optional<unsigned> LastFunctionNumber;
576
577 static std::string getContextName(const MachineFunction &MF) {
579 }
580};
581
582class DevelopmentModeEvictionAdvisorAnalysisLegacy final
584public:
585 DevelopmentModeEvictionAdvisorAnalysisLegacy()
586 : RegAllocEvictionAdvisorAnalysisLegacy(AdvisorMode::Development) {}
587
588 bool doInitialization(Module &M) override {
589 Provider = std::make_unique<DevelopmentModeEvictionAdvisorProvider>(
590 M.getContext());
591 return false;
592 }
593
594 void logRewardIfNeeded(const MachineFunction &MF,
595 llvm::function_ref<float()> GetReward) override {
596 Provider->logRewardIfNeeded(MF, GetReward);
597 }
598
599 // support for isa<> and dyn_cast.
600 static bool classof(const RegAllocEvictionAdvisorAnalysisLegacy *R) {
601 return R->getAdvisorMode() == AdvisorMode::Development;
602 }
603
604 void getAnalysisUsage(AnalysisUsage &AU) const override {
607 }
608};
609
610#endif // #ifdef LLVM_HAVE_TFLITE
611} // namespace
612
613float MLEvictAdvisor::getInitialQueueSize(const MachineFunction &MF) {
614 auto &MRI = MF.getRegInfo();
615 unsigned NumUsedRegs = 0;
616 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
618 if (!MRI.reg_nodbg_empty(Reg))
619 ++NumUsedRegs;
620 }
621 return static_cast<float>(NumUsedRegs);
622}
623
624MLEvictAdvisor::MLEvictAdvisor(const MachineFunction &MF, const RAGreedy &RA,
625 MLModelRunner *Runner,
627 const MachineBlockFrequencyInfo &MBFI,
628 const MachineLoopInfo &Loops)
630 NumColumns(NumAllocatableRegs + 1), DefaultAdvisor(MF, RA),
631 Runner(std::move(Runner)), MBFI(MBFI), Loops(Loops),
632 InitialQSize(MLEvictAdvisor::getInitialQueueSize(MF)) {
633 assert(this->Runner);
634 Runner->switchContext(MF.getName());
635 DoNotNormalize.set(FeatureIDs::mask);
636 DoNotNormalize.set(FeatureIDs::is_free);
637 DoNotNormalize.set(FeatureIDs::is_hint);
638 DoNotNormalize.set(FeatureIDs::is_local);
639 DoNotNormalize.set(FeatureIDs::min_stage);
640 DoNotNormalize.set(FeatureIDs::max_stage);
641 DoNotNormalize.set(FeatureIDs::progress);
642}
643
644int64_t MLEvictAdvisor::tryFindEvictionCandidatePosition(
645 const LiveInterval &, const AllocationOrder &, unsigned, uint8_t,
646 const SmallVirtRegSet &) const {
647 int64_t Ret = Runner->evaluate<int64_t>();
648 assert(Ret >= 0);
649 assert(static_cast<size_t>(Ret) <= CandidateVirtRegPos);
650 return Ret;
651}
652
653bool MLEvictAdvisor::loadInterferenceFeatures(
654 const LiveInterval &VirtReg, MCRegister PhysReg, bool IsHint,
655 const SmallVirtRegSet &FixedRegisters,
656 llvm::SmallVectorImpl<float> &Largest, size_t Pos,
657 llvm::SmallVectorImpl<LRStartEndInfo> &LRPosInfo) const {
658 // It is only possible to evict virtual register interference.
659 if (Matrix->checkInterference(VirtReg, PhysReg) > LiveRegMatrix::IK_VirtReg) {
660 // leave unavailable
661 return false;
662 }
663
664 const bool IsLocal = LIS->intervalIsInOneMBB(VirtReg);
665 int64_t LocalIntfs = 0;
666 float NumUrgent = 0.0f;
667
668 // The cascade tracking is the same as in the default advisor
669 unsigned Cascade = RA.getExtraInfo().getCascadeOrCurrentNext(VirtReg.reg());
670
672 InterferingIntervals;
673 for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
674 LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit);
675 // Different from the default heuristic, we don't make any assumptions
676 // about what having more than 10 results in the query may mean.
677 const auto &IFIntervals = Q.interferingVRegs(EvictInterferenceCutoff);
678 if (IFIntervals.empty() && InterferingIntervals.empty())
679 continue;
680 if (IFIntervals.size() >= EvictInterferenceCutoff)
681 return false;
682 InterferingIntervals.append(IFIntervals.begin(), IFIntervals.end());
683 for (const LiveInterval *Intf : reverse(IFIntervals)) {
684 assert(Intf->reg().isVirtual() &&
685 "Only expecting virtual register interference from query");
686 // This is the same set of legality checks as in the default case: don't
687 // try to evict fixed regs or 'done' ones. Also don't break cascades,
688 // except in the urgent case, with the same nuances used in the default
689 // heuristic.
690 // We could try sharing this between the advisors, but it may end up
691 // more complex than it is right now.
692 if (FixedRegisters.count(Intf->reg()))
693 return false;
694 if (RA.getExtraInfo().getStage(*Intf) == RS_Done)
695 return false;
696 bool Urgent =
697 !VirtReg.isSpillable() &&
698 (Intf->isSpillable() ||
699 RegClassInfo.getNumAllocatableRegs(MRI->getRegClass(VirtReg.reg())) <
700 RegClassInfo.getNumAllocatableRegs(
701 MRI->getRegClass(Intf->reg())));
702
703 unsigned IntfCascade = RA.getExtraInfo().getCascade(Intf->reg());
704 // There is a potential that the model could be adversarial and
705 // continually evict live ranges over and over again, leading to a
706 // large amount of compile time being spent in regalloc. If we hit the
707 // threshold, prevent the range from being evicted. We still let the
708 // range through if it is urgent as we are required to produce an
709 // eviction if the candidate is not spillable.
710 // The cap should not apply when the default advisor decides.
711 if (!isa<NoInferenceModelRunner>(Runner) &&
712 getEvictionCount(Intf->reg()) > MaxEvictionCount && !Urgent)
713 return false;
714
715 // Only evict older cascades or live ranges without a cascade.
716 if (Cascade <= IntfCascade) {
717 if (!Urgent)
718 return false;
719 ++NumUrgent;
720 }
721
722 LocalIntfs += (IsLocal && LIS->intervalIsInOneMBB(*Intf) &&
723 (!EnableLocalReassign || !canReassign(*Intf, PhysReg)));
724 }
725 }
726 // OK, so if we made it this far, this LR is an eviction candidate, load its
727 // features.
728 extractFeatures(InterferingIntervals, Largest, Pos, IsHint, LocalIntfs,
729 NumUrgent, LRPosInfo);
730 return true;
731}
732
733MCRegister MLEvictAdvisor::tryFindEvictionCandidate(
734 const LiveInterval &VirtReg, const AllocationOrder &Order,
735 uint8_t CostPerUseLimit, const SmallVirtRegSet &FixedRegisters) const {
736 auto MaybeOrderLimit = getOrderLimit(VirtReg, Order, CostPerUseLimit);
737 if (!MaybeOrderLimit)
739 unsigned OrderLimit = *MaybeOrderLimit;
740
741 // The heuristic sets initial costs such as, if CostPerUseLimit is
742 // max<uint8_t>, then any of the costs of the legally-evictable intervals
743 // would be lower. When that happens, one of those will be selected.
744 // Therefore, we allow the candidate be selected, unless the candidate is
745 // unspillable, in which case it would be incorrect to not find a register
746 // for it.
747 const bool MustFindEviction =
748 (!VirtReg.isSpillable() && CostPerUseLimit == static_cast<uint8_t>(~0u));
749 // Number of available candidates - if 0, no need to continue.
750 size_t Available = 0;
751 // Make sure we don't have leftover partial state from an attempt where we
752 // had no available candidates and bailed out early.
753 resetInputs(*Runner, InputFeatures);
754
755 // Track the index->register mapping because AllocationOrder doesn't do that
756 // and we'd have to scan it.
757 // Also track their mask, to write asserts/debug.
758 CandidateRegList Regs(NumColumns, {0, false});
759
760 // Track the largest value of features seen during this eviction session. We
761 // only normalize (some of) the float features, but it's just simpler to
762 // dimension 'Largest' to all the features, especially since we have the
763 // 'DoNotNormalize' list.
764 FeaturesListNormalizer Largest(FeatureIDs::FeatureCount, 0.0);
765
766 // Same overal idea as in the default eviction policy - we visit the values
767 // of AllocationOrder one at a time. If it's not legally available, we mask
768 // off the corresponding feature column (==do nothing because we already
769 // reset all the features to 0) Use Pos to capture the column we load
770 // features at - in AllocationOrder order.
771 size_t Pos = 0;
773 for (auto I = Order.begin(), E = Order.getOrderLimitEnd(OrderLimit); I != E;
774 ++I, ++Pos) {
775 if (Pos == CandidateVirtRegPos)
776 reportFatalUsageError("Regalloc: the allocation order is longer than "
777 "-mlregalloc-num-allocatable-regs=" +
779 MCRegister PhysReg = *I;
780 assert(!Regs[Pos].second);
781 assert(PhysReg);
782 if (!canAllocatePhysReg(CostPerUseLimit, PhysReg)) {
783 continue;
784 }
785 if (loadInterferenceFeatures(VirtReg, PhysReg, I.isHint(), FixedRegisters,
786 Largest, Pos, LRPosInfo)) {
787 ++Available;
788 Regs[Pos] = std::make_pair(PhysReg, true);
789 }
790 }
791 if (Available == 0) {
792 // Nothing to decide, nothing to learn.
793 assert(!MustFindEviction);
795 }
796 const size_t ValidPosLimit = Pos;
797 // If we must find eviction, the candidate should be masked out of the
798 // decision making process.
799 Regs[CandidateVirtRegPos].second = !MustFindEviction;
800 if (!MustFindEviction)
801 extractFeatures(SmallVector<const LiveInterval *, 1>(1, &VirtReg), Largest,
802 CandidateVirtRegPos, /*IsHint*/ 0,
803 /*LocalIntfsCount*/ 0,
804 /*NumUrgent*/ 0.0, LRPosInfo);
805 assert(InitialQSize > 0.0 && "We couldn't have gotten here if we had "
806 "nothing to allocate initially.");
807 // Normalize the features.
808 for (auto &V : Largest)
809 V = V ? V : 1.0;
811 ++FeatureIndex) {
812 if (DoNotNormalize.test(FeatureIndex))
813 continue;
814 for (size_t Pos = 0; Pos < NumColumns; ++Pos) {
815 float &V = Runner->getTensor<float>(FeatureIndex)[Pos];
816 V = std::isinf(V) ? 1.0f : V / Largest[FeatureIndex];
817 }
818 }
819 *Runner->getTensor<float>(FeatureIDs::progress) =
820 static_cast<float>(RA.getQueueSize()) / InitialQSize;
821
822 // Get a decision.
823 size_t CandidatePos = tryFindEvictionCandidatePosition(
824 VirtReg, Order, OrderLimit, CostPerUseLimit, FixedRegisters);
825 // The contract with the ML side is that CandidatePos is mask == 1 (i.e.
826 // Regs[CandidatePos].second)
827 assert(Regs[CandidatePos].second);
828 if (CandidatePos == CandidateVirtRegPos) {
829 onEviction(VirtReg.reg());
830 assert(!MustFindEviction);
832 }
833 assert(CandidatePos < ValidPosLimit);
834 (void)ValidPosLimit;
835
836 // Update information about how many times the virtual registers being
837 // evicted have been evicted so that we can prevent the model from evicting
838 // the same ranges continually and eating compile time.
839 for (MCRegUnit Unit : TRI->regunits(Regs[CandidatePos].first)) {
840 LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit);
841 const auto &IFIntervals = Q.interferingVRegs(EvictInterferenceCutoff);
842 for (const LiveInterval *Intf : reverse(IFIntervals)) {
843 onEviction(Intf->reg());
844 }
845 }
846
847 return Regs[CandidatePos].first;
848}
849
850const LIFeatureComponents &
851MLEvictAdvisor::getLIFeatureComponents(const LiveInterval &LI) const {
852 RegID ID = LI.reg().id();
853 LIFeatureComponents Empty;
854 auto I = CachedFeatures.insert(std::make_pair(ID, Empty));
855 LIFeatureComponents &Ret = I.first->getSecond();
856 if (!I.second)
857 return Ret;
858
861
863 I = MRI->reg_instr_nodbg_begin(LI.reg()),
864 E = MRI->reg_instr_nodbg_end();
865 I != E;) {
866 MachineInstr *MI = &*(I++);
867
868 ++Ret.NumDefsAndUses;
869 if (!Visited.insert(MI).second)
870 continue;
871
872 if (MI->isIdentityCopy() || MI->isImplicitDef())
873 continue;
874
875 bool Reads, Writes;
876 std::tie(Reads, Writes) = MI->readsWritesVirtualRegister(LI.reg());
877
878 float Freq = MBFI.getBlockFreqRelativeToEntryBlock(MI->getParent());
879 Ret.HottestBlockFreq = std::max(Freq, Ret.HottestBlockFreq);
880
881 Ret.R += (Reads && !Writes) * Freq;
882 Ret.W += (!Reads && Writes) * Freq;
883 Ret.RW += (Reads && Writes) * Freq;
884
885 auto *MBB = MI->getParent();
886 auto *Loop = Loops.getLoopFor(MBB);
887 bool IsExiting = Loop ? Loop->isLoopExiting(MBB) : false;
888
889 if (Writes && IsExiting && LIS->isLiveOutOfMBB(LI, MBB))
890 Ret.IndVarUpdates += Freq;
891
892 if (MI->isCopy() && VirtRegAuxInfo::copyHint(MI, LI.reg(), TRI, *MRI))
893 Ret.HintWeights += Freq;
894 }
896 LI, *LIS, *VRM, *MRI, *MF.getSubtarget().getInstrInfo());
897 return Ret;
898}
899
900// Overall, this currently mimics what we do for weight calculation, but instead
901// of accummulating the various features, we keep them separate.
902void MLEvictAdvisor::extractFeatures(
904 llvm::SmallVectorImpl<float> &Largest, size_t Pos, int64_t IsHint,
905 int64_t LocalIntfsCount, float NumUrgent,
906 SmallVectorImpl<LRStartEndInfo> &LRPosInfo) const {
907 int64_t NumDefsAndUses = 0;
908 int64_t NumBrokenHints = 0;
909 double R = 0.0;
910 double W = 0.0;
911 double RW = 0.0;
912 double IndVarUpdates = 0.0;
913 double HintWeights = 0.0;
914 float StartBBFreq = 0.0;
915 float EndBBFreq = 0.0;
916 float HottestBlockFreq = 0.0;
917 int32_t NumRematerializable = 0;
918 float TotalWeight = 0.0;
919
920 SlotIndex EndSI = LIS->getSlotIndexes()->getZeroIndex();
921 SlotIndex StartSI = LIS->getSlotIndexes()->getLastIndex();
922 int64_t MaxStage = 0;
923 int64_t MinStage =
924 Intervals.empty() ? 0 : std::numeric_limits<int64_t>::max();
925
926 for (const auto *L : Intervals) {
927 const LiveInterval &LI = *L;
928 MaxStage = std::max<int64_t>(
929 MaxStage, static_cast<int64_t>(RA.getExtraInfo().getStage(LI)));
930 MinStage = std::min<int64_t>(
931 MinStage, static_cast<int64_t>(RA.getExtraInfo().getStage(LI)));
932
933 TotalWeight = std::max(TotalWeight, LI.weight());
934
935 if (LI.beginIndex() < StartSI)
936 StartSI = LI.beginIndex();
937
938 if (LI.endIndex() > EndSI)
939 EndSI = LI.endIndex();
940 const LIFeatureComponents &LIFC = getLIFeatureComponents(LI);
941 NumBrokenHints += VRM->hasPreferredPhys(LI.reg());
942
943 NumDefsAndUses += LIFC.NumDefsAndUses;
944 HottestBlockFreq = std::max(HottestBlockFreq, LIFC.HottestBlockFreq);
945 R += LIFC.R;
946 W += LIFC.W;
947 RW += LIFC.RW;
948
949 IndVarUpdates += LIFC.IndVarUpdates;
950
951 HintWeights += LIFC.HintWeights;
952 NumRematerializable += LIFC.IsRemat;
953 }
954 size_t Size = 0;
955 if (!Intervals.empty()) {
956 StartBBFreq =
957 MBFI.getBlockFreqRelativeToEntryBlock(LIS->getMBBFromIndex(StartSI));
958 if (EndSI >= LIS->getSlotIndexes()->getLastIndex())
959 EndSI = LIS->getSlotIndexes()->getLastIndex().getPrevIndex();
960 EndBBFreq =
961 MBFI.getBlockFreqRelativeToEntryBlock(LIS->getMBBFromIndex(EndSI));
962 Size = StartSI.distance(EndSI);
963 }
964 // Set the features at the column 'Pos'.
965#define SET(ID, TYPE, VAL) \
966 do { \
967 Runner->getTensor<TYPE>(FeatureIDs::ID)[Pos] = static_cast<TYPE>(VAL); \
968 float F = static_cast<float>(VAL); \
969 if (!DoNotNormalize.test(FeatureIDs::ID) && !std::isinf(F)) \
970 Largest[FeatureIDs::ID] = std::max(Largest[FeatureIDs::ID], F); \
971 } while (false)
972 SET(mask, int64_t, 1);
973 SET(is_free, int64_t, Intervals.empty());
974 SET(nr_urgent, float, NumUrgent);
975 SET(nr_broken_hints, float, NumBrokenHints);
976 SET(is_hint, int64_t, IsHint);
977 SET(is_local, int64_t, LocalIntfsCount);
978 SET(nr_rematerializable, float, NumRematerializable);
979 SET(nr_defs_and_uses, float, NumDefsAndUses);
980 SET(weighed_reads_by_max, float, R);
981 SET(weighed_writes_by_max, float, W);
982 SET(weighed_read_writes_by_max, float, RW);
983 SET(weighed_indvars_by_max, float, IndVarUpdates);
984 SET(hint_weights_by_max, float, HintWeights);
985 SET(start_bb_freq_by_max, float, StartBBFreq);
986 SET(end_bb_freq_by_max, float, EndBBFreq);
987 SET(hottest_bb_freq_by_max, float, HottestBlockFreq);
988 SET(liverange_size, float, Size);
989 SET(use_def_density, float, TotalWeight);
990 SET(max_stage, int64_t, MaxStage);
991 SET(min_stage, int64_t, MinStage);
992#undef SET
993}
994
995// Development mode-specific implementations
996#ifdef LLVM_HAVE_TFLITE
997
1000 return new DevelopmentModeEvictionAdvisorAnalysisLegacy();
1001}
1002
1003int64_t DevelopmentModeEvictAdvisor::tryFindEvictionCandidatePosition(
1004 const LiveInterval &VirtReg, const AllocationOrder &Order,
1005 unsigned OrderLimit, uint8_t CostPerUseLimit,
1006 const SmallVirtRegSet &FixedRegisters) const {
1007 int64_t Ret = 0;
1008 if (isa<ModelUnderTrainingRunner>(getRunner())) {
1009 Ret = MLEvictAdvisor::tryFindEvictionCandidatePosition(
1010 VirtReg, Order, OrderLimit, CostPerUseLimit, FixedRegisters);
1011 } else {
1012 MCRegister PhysReg = getDefaultAdvisor().tryFindEvictionCandidate(
1013 VirtReg, Order, CostPerUseLimit, FixedRegisters);
1014 // Find the index of the selected PhysReg. We need it for logging,
1015 // otherwise this is wasted cycles (but so would starting development mode
1016 // without a model nor logging)
1017 if (!PhysReg)
1018 Ret = CandidateVirtRegPos;
1019 else
1020 for (auto I = Order.begin(), E = Order.getOrderLimitEnd(OrderLimit);
1021 I != E; ++I, ++Ret)
1022 if (*I == PhysReg)
1023 break;
1024 }
1025 if (TrainingLog.empty())
1026 return Ret;
1027 // TODO(mtrofin): when we support optional rewards, this can go away. In the
1028 // meantime, we log the "pretend" reward (0) for the previous observation
1029 // before starting a new one.
1030 if (Log->hasObservationInProgress())
1031 Log->logReward<float>(0.0);
1032
1033 Log->startObservation();
1034 size_t CurrentFeature = 0;
1036 for (; CurrentFeature < FeatureCount; ++CurrentFeature) {
1037 Log->logTensorValue(CurrentFeature,
1038 reinterpret_cast<const char *>(
1039 getRunner().getTensorUntyped(CurrentFeature)));
1040 }
1041 if (auto *MUTR = dyn_cast<ModelUnderTrainingRunner>(&getRunner()))
1042 for (size_t I = 0; I < MUTR->extraOutputsForLoggingSpecs().size();
1043 ++I, ++CurrentFeature)
1044 Log->logTensorValue(
1045 CurrentFeature,
1046 reinterpret_cast<const char *>(MUTR->getUntypedExtraOutputValue(I)));
1047 // The output is right after the features and the extra outputs
1048 Log->logTensorValue(CurrentFeature, reinterpret_cast<const char *>(&Ret));
1049 Log->endObservation();
1050 return Ret;
1051}
1052
1053bool RegAllocScoring::runOnMachineFunction(MachineFunction &MF) {
1054 std::optional<float> CachedReward;
1055 auto GetReward = [&]() {
1056 if (!CachedReward)
1057 CachedReward = static_cast<float>(
1059 MF, getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI())
1060 .getScore());
1061 return *CachedReward;
1062 };
1063
1064 getAnalysis<RegAllocEvictionAdvisorAnalysisLegacy>().logRewardIfNeeded(
1065 MF, GetReward);
1066 getAnalysis<RegAllocPriorityAdvisorAnalysisLegacy>().logRewardIfNeeded(
1067 MF, GetReward);
1068 return false;
1069}
1070#endif // #ifdef LLVM_HAVE_TFLITE
1071
1072RegAllocEvictionAdvisorProvider *
1076 ? new ReleaseModeEvictionAdvisorProvider(Ctx)
1077 : nullptr;
1078}
1079
1082#if defined(LLVM_HAVE_TFLITE)
1083 return new DevelopmentModeEvictionAdvisorProvider(Ctx);
1084#endif
1085 return nullptr;
1086}
1087
1092 ? new ReleaseModeEvictionAdvisorAnalysisLegacy()
1093 : nullptr;
1094}
1095
1096// In all cases except development mode, we don't need scoring.
1097#if !defined(LLVM_HAVE_TFLITE)
1098bool RegAllocScoring::runOnMachineFunction(MachineFunction &) { return false; }
1099#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static constexpr unsigned long long mask(BlockVerifier::State S)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
@ Default
This file implements a model runner wrapping an EmitC compiled ML model.
@ Available
We know the block is fully available. This is a fixpoint.
Definition GVN.cpp:1232
Hexagon Hardware Loops
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
Live Register Matrix
#define I(x, y, z)
Definition MD5.cpp:57
This file provides helper functions for creating MLModelRunners and checking model validity in releas...
NoopSavedModelImpl CompiledModelType
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 llvm::cl::opt< MLGORegAllocModelChoice > SelectedMLGORegAllocModel("regalloc-mlgo-model", llvm::cl::desc("Select the MLGO model to execute for register allocation:"), llvm::cl::init(MLGORegAllocModelChoice::Default), llvm::cl::values(clEnumValN(MLGORegAllocModelChoice::Default, "default", "Use standard heuristic") #define MLGO_MODEL(CLASS_NAME, CLI_FLAG) \ \‍))
static std::unique_ptr< MLModelRunner > createMLGORegAllocModelRunner(LLVMContext &Ctx, const std::vector< TensorSpec > &InputFeatures)
#define MLGO_MODEL(CLASS_NAME, CLI_FLAG)
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 SET(ID, TYPE, VAL)
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"))
static cl::opt< unsigned > NumAllocatableRegs("mlregalloc-num-allocatable-regs", cl::Hidden, cl::desc("The number of eviction candidates the model sees. The model has " "one more column, for the live range seeking allocation"), cl::init(32))
#define _FEATURE_IDX(A, B, C, D)
#define _DECL_FEATURES(type, name, shape, _)
#define DecisionName
Register Reg
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
SI optimize exec mask operations pre RA
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
Iterator getOrderLimitEnd(unsigned OrderLimit) const
Iterator begin() const
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:767
iterator end()
Definition DenseMap.h:687
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:356
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI 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.
float weight() const
Register reg() const
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.
Definition LoopInfo.h:40
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
static constexpr unsigned NoRegister
Definition MCRegister.h:60
MLModelRunner interface: abstraction of a mechanism for evaluating a ML model.
virtual void switchContext(StringRef Name)
void * getTensorUntyped(size_t Index)
T * getTensor(I FeatureID)
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.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
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_instr_iterator< true, true, true, true > reg_instr_nodbg_iterator
reg_instr_nodbg_iterator/reg_instr_nodbg_begin/reg_instr_nodbg_end - Walk all defs and uses of the sp...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A mock class satisfying the interface expected by ReleaseModeModelRunner for its TGen parameter.
virtual bool doInitialization(Module &)
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
Definition Pass.h:128
ImmutableAnalysis abstraction for fetching the Eviction Advisor.
virtual void logRewardIfNeeded(const MachineFunction &MF, function_ref< float()> GetReward)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Common provider for legacy and new pass managers.
virtual std::unique_ptr< RegAllocEvictionAdvisor > getAdvisor(const MachineFunction &MF, const RAGreedy &RA, MachineBlockFrequencyInfo *MBFI, MachineLoopInfo *Loops)=0
virtual void logRewardIfNeeded(const MachineFunction &MF, llvm::function_ref< float()> GetReward)
RegAllocEvictionAdvisorProvider(AdvisorMode Mode, LLVMContext &Ctx)
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.
LLVM_ABI_FOR_TEST double getScore() const
Wrapper class representing virtual and physical registers.
Definition Register.h:20
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
Definition Register.h:72
constexpr unsigned id() const
Definition Register.h:100
SlotIndex - An opaque wrapper around machine indexes.
Definition SlotIndexes.h:66
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.
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
Definition SmallSet.h:176
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.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
static TensorSpec createSpec(const std::string &Name, const std::vector< int64_t > &Shape, int Port=0)
Definition TensorSpec.h:65
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static LLVM_ABI bool isRematerializable(const LiveInterval &LI, const LiveIntervals &LIS, const VirtRegMap &VRM, const MachineRegisterInfo &MRI, const TargetInstrInfo &TII)
Determine if all values in LI are rematerializable.
static LLVM_ABI Register copyHint(const MachineInstr *MI, Register Reg, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI)
Return the preferred allocation register for reg, given a COPY instruction.
An efficient, type-erasing, non-owning reference to a callable.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
SmallSet< Register, 16 > SmallVirtRegSet
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI RegAllocEvictionAdvisorAnalysisLegacy * createReleaseModeAdvisorAnalysisLegacy()
LLVM_ABI RegAllocEvictionAdvisorProvider * createDevelopmentModeAdvisorProvider(LLVMContext &Ctx)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
static const TensorSpec DecisionSpec
RegAllocScore calculateRegAllocScore(const MachineFunction &MF, const MachineBlockFrequencyInfo &MBFI)
Calculate a score.
bool isReleaseModelValid(StringRef InteractiveChannelBaseName, const cl::opt< EnumType, ExternalStorage, ParserClass > &SelectedModel, EnumType DefaultModelVal=EnumType::Default)
Helper to check if a release-mode ML advisor has a valid model to execute.
Definition MLGOUtils.h:35
LLVM_ABI RegAllocEvictionAdvisorAnalysisLegacy * createDevelopmentModeAdvisorAnalysisLegacy()
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
std::unique_ptr< MLModelRunner > createReleaseModeModelRunner(LLVMContext &Ctx, const std::vector< TensorSpec > &InputFeatures, StringRef DecisionName, const std::string &InteractiveChannelBaseName, const TensorSpec &InteractiveDecisionSpec, CreateEmitCFunc &&CreateEmitCModelRunner, const EmbeddedModelRunnerOptions &Options={})
Helper to construct the appropriate MLModelRunner in release mode:
Definition MLGOUtils.h:61
static const std::vector< TensorSpec > InputFeatures
@ RS_Done
There is nothing more we can do to this live range.
std::string getLoggerContextName(StringRef Name, unsigned Number)
Context name for Name.
LLVM_ABI FunctionPass * createRegAllocScoringPass()
When learning an eviction policy, extract score(reward) information, otherwise this does nothing.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
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.
Definition STLExtras.h:1933
LLVM_ABI RegAllocEvictionAdvisorProvider * createReleaseModeAdvisorProvider(LLVMContext &Ctx)
static const std::vector< int64_t > PerLiveRangeShape
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878