LLVM: lib/CodeGen/MLRegAllocEvictAdvisor.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
19#if defined(LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL) || defined(LLVM_HAVE_TFLITE)
23#endif
41
42#include
43#include
44#include
45
46using namespace llvm;
47
48#define DEBUG_TYPE "ml-regalloc"
49
50
51#if defined(LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL)
52#include "RegAllocEvictModel.h"
54#else
56#endif
57
59 "regalloc-evict-interactive-channel-base", cl::Hidden,
61 "Base file path for the interactive mode. The incoming filename should "
62 "have the name .in, while the "
63 "outgoing name should be "
64 ".out"));
65
68 cl::desc("The maximum number of times a live range can be "
69 "evicted before preventing it from being evicted"),
71
72
73#ifdef LLVM_HAVE_TFLITE
76
79 cl::desc("Training log for the register allocator eviction model"));
80
83 cl::desc("The model being trained for register allocation eviction"));
84
86 "regalloc-enable-development-features", cl::Hidden,
87 cl::desc("Whether or not to enable features under development for the ML "
88 "regalloc advisor"));
89
90#else
92#endif
93
94
95
96
97namespace llvm {
99
101public:
103
106 }
107
109
111 return "Register Allocation Pass Scoring";
112 }
113
114
121 }
122
123
125};
126
129
130}
131
133 "Register Allocation Scoring Pass", false, false)
134
135
136
137
138namespace {
139
140
141static const int OpcodeValueCutoff = 17716;
142
143
144
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165#define RA_EVICT_FEATURES_LIST(M) \
166 M(int64_t, mask, PerLiveRangeShape, \
167 "boolean values, 0 for unavailable candidates (i.e. if a position is 0, " \
168 "it " \
169 "can't be evicted)") \
170 M(int64_t, is_free, PerLiveRangeShape, \
171 "boolean values, 1 if this phys reg is actually free (no interferences)") \
172 M(float, nr_urgent, PerLiveRangeShape, \
173 "number of 'urgent' intervals, normalized. Urgent are those that are OK " \
174 "to break cascades") \
175 M(float, nr_broken_hints, PerLiveRangeShape, \
176 "if this position were evicted, how many broken hints would there be") \
177 M(int64_t, is_hint, PerLiveRangeShape, \
178 "is this a preferred phys reg for the candidate") \
179 M(int64_t, is_local, PerLiveRangeShape, \
180 "is this live range local to a basic block") \
181 M(float, nr_rematerializable, PerLiveRangeShape, \
182 "nr rematerializable ranges") \
183 M(float, nr_defs_and_uses, PerLiveRangeShape, \
184 "bb freq - weighed nr defs and uses") \
185 M(float, weighed_reads_by_max, PerLiveRangeShape, \
186 "bb freq - weighed nr of reads, normalized") \
187 M(float, weighed_writes_by_max, PerLiveRangeShape, \
188 "bb feq - weighed nr of writes, normalized") \
189 M(float, weighed_read_writes_by_max, PerLiveRangeShape, \
190 "bb freq - weighed nr of uses that are both read and writes, normalized") \
191 M(float, weighed_indvars_by_max, PerLiveRangeShape, \
192 "bb freq - weighed nr of uses that are indvars, normalized") \
193 M(float, hint_weights_by_max, PerLiveRangeShape, \
194 "bb freq - weighed nr of uses that are hints, normalized") \
195 M(float, start_bb_freq_by_max, PerLiveRangeShape, \
196 "the freq in the start block, normalized") \
197 M(float, end_bb_freq_by_max, PerLiveRangeShape, \
198 "freq of end block, normalized") \
199 M(float, hottest_bb_freq_by_max, PerLiveRangeShape, \
200 "hottest BB freq, normalized") \
201 M(float, liverange_size, PerLiveRangeShape, \
202 "size (instr index diff) of the LR") \
203 M(float, use_def_density, PerLiveRangeShape, \
204 "the max weight, as computed by the manual heuristic") \
205 M(int64_t, max_stage, PerLiveRangeShape, \
206 "largest stage of an interval in this LR") \
207 M(int64_t, min_stage, PerLiveRangeShape, \
208 "lowest stage of an interval in this LR") \
209 M(float, progress, {1}, "ratio of current queue size to initial size")
210
211#ifdef LLVM_HAVE_TFLITE
212#define RA_EVICT_FIRST_DEVELOPMENT_FEATURE(M) \
213 M(int64_t, instructions, InstructionsShape, \
214 "Opcodes of the instructions covered by the eviction problem")
215
216#define RA_EVICT_REST_DEVELOPMENT_FEATURES(M) \
217 M(int64_t, instructions_mapping, InstructionsMappingShape, \
218 "A binary matrix mapping LRs to instruction opcodes") \
219 M(float, mbb_frequencies, MBBFrequencyShape, \
220 "A vector of machine basic block frequencies") \
221 M(int64_t, mbb_mapping, InstructionsShape, \
222 "A vector of indices mapping instructions to MBBs")
223#else
224#define RA_EVICT_FIRST_DEVELOPMENT_FEATURE(M)
225#define RA_EVICT_REST_DEVELOPMENT_FEATURES(M)
226#endif
227
228
229
230
231
232#define DecisionName "index_to_evict"
234 TensorSpec::createSpec<int64_t>(DecisionName, {1});
235
236
238#define _FEATURE_IDX_SIMPLE(_, name, __, ___) name
239#define _FEATURE_IDX(A, B, C, D) _FEATURE_IDX_SIMPLE(A, B, C, D),
241#ifdef LLVM_HAVE_TFLITE
243#else
245#endif
247#undef _FEATURE_IDX
248#undef _FEATURE_IDX_SIMPLE
249};
250
251
252
253
254
255template size_t getTotalSize(const std::vector<int64_t> &Shape) {
256 size_t Ret = sizeof(T);
257 for (const auto V : Shape)
258 Ret *= V;
259 return Ret;
260}
261
263#define _RESET(TYPE, NAME, SHAPE, __) \
264 std::memset(Runner.getTensorUntyped(FeatureIDs::NAME), 0, \
265 getTotalSize(SHAPE));
270#undef _RESET
271 }
272}
273
274
275
276struct LIFeatureComponents {
277 double R = 0;
278 double W = 0;
279 double RW = 0;
280 double IndVarUpdates = 0;
281 double HintWeights = 0.0;
282 int64_t NumDefsAndUses = 0;
283 float HottestBlockFreq = 0.0;
284 bool IsRemat = false;
285};
286
287using CandidateRegList =
289using FeaturesListNormalizer =
291
292
294public:
298
299protected:
302 }
303
304
305
306 const MLModelRunner &getRunner() const { return *Runner; }
307
308
309
310
311
312 virtual int64_t
313 tryFindEvictionCandidatePosition(const LiveInterval &VirtReg,
315 unsigned OrderLimit, uint8_t CostPerUseLimit,
317
318
319
320 bool
325
326private:
327 static float getInitialQueueSize(const MachineFunction &MF);
328
333
336 int64_t IsHint, int64_t LocalIntfsCount, float NumUrgent,
338
339
340
344 return getDefaultAdvisor().canEvictHintInterference(VirtReg, PhysReg,
345 FixedRegisters);
346 }
347
348 const LIFeatureComponents &
349 getLIFeatureComponents(const LiveInterval &LI) const;
350
351
352
353
354
359
360
361
362 std::bitsetFeatureIDs::FeatureCount DoNotNormalize;
363 const float InitialQSize;
364
367};
368
369#define _DECL_FEATURES(type, name, shape, _) \
370 TensorSpec::createSpec(#name, shape),
371
372
373
374
375class ReleaseModeEvictionAdvisorAnalysis final
377public:
378 ReleaseModeEvictionAdvisorAnalysis()
384 } else {
386 }
387 }
388
391 }
392
393private:
395
400 }
401
402 std::unique_ptr
404 if (!Runner) {
406 Runner = std::make_unique<ReleaseModeModelRunner>(
408 else
409 Runner = std::make_unique(
413 }
414 return std::make_unique(
415 MF, RA, Runner.get(),
416 getAnalysis().getMBFI(),
417 getAnalysis().getLI());
418 }
419 std::unique_ptr Runner;
420};
421
422
423
424
425
426
427#ifdef LLVM_HAVE_TFLITE
428static const TensorSpec Reward = TensorSpec::createSpec("reward", {1});
429
430
431
432
433
434#define _DECL_TRAIN_FEATURES(type, name, shape, _) \
435 TensorSpec::createSpec(std::string("action_") + #name, shape),
436
437class DevelopmentModeEvictAdvisor : public MLEvictAdvisor {
438public:
443 : MLEvictAdvisor(MF, RA, Runner, MBFI, Loops), Log(Log) {}
444
445private:
446 int64_t tryFindEvictionCandidatePosition(
448 unsigned OrderLimit, uint8_t CostPerUseLimit,
450
452};
453
454class DevelopmentModeEvictionAdvisorAnalysis final
456public:
457 DevelopmentModeEvictionAdvisorAnalysis()
463 TrainingInputFeatures = {
467 TensorSpec::createSpec("action_discount", {1}),
468 TensorSpec::createSpec<int32_t>("action_step_type", {1}),
469 TensorSpec::createSpec("action_reward", {1})};
470 } else {
472 TrainingInputFeatures = {
474 TensorSpec::createSpec("action_discount", {1}),
475 TensorSpec::createSpec<int32_t>("action_step_type", {1}),
476 TensorSpec::createSpec("action_reward", {1})};
477 }
478 }
479
482 }
483
486 if (!Log || !Log->hasAnyObservationForContext(MF.getName()))
487 return;
488
489
490
491
492 if (Log->currentContext() != MF.getName()) {
494 "The training log context shouldn't have had changed.");
495 }
496 if (Log->hasObservationInProgress())
497 Log->logReward<float>(GetReward());
498 }
499
500private:
502 std::vector TrainingInputFeatures;
503
508 }
509
512 if (ModelUnderTraining.empty() && TrainingLog.empty()) {
513 Ctx.emitError("Regalloc development mode should be requested with at "
514 "least logging enabled and/or a training model");
515 return false;
516 }
517 if (ModelUnderTraining.empty())
518 Runner = std::make_unique(Ctx, InputFeatures);
519 else
520 Runner = ModelUnderTrainingRunner::createAndEnsureValid(
521 Ctx, ModelUnderTraining, DecisionName, TrainingInputFeatures);
522 if (!Runner) {
523 Ctx.emitError("Regalloc: could not set up the model runner");
524 return false;
525 }
526 if (TrainingLog.empty())
527 return false;
528 std::error_code EC;
529 auto OS = std::make_unique<raw_fd_ostream>(TrainingLog, EC);
530 if (EC) {
531 M.getContext().emitError(EC.message() + ":" + TrainingLog);
532 return false;
533 }
535 if (auto *MUTR = dyn_cast(Runner.get()))
536 append_range(LFS, MUTR->extraOutputsForLoggingSpecs());
537
538
539
541
542 Log = std::make_unique(std::move(OS), LFS, Reward,
543 true);
544 return false;
545 }
546
547 std::unique_ptr
549 if (!Runner)
550 return nullptr;
551 if (Log)
552 Log->switchContext(MF.getName());
553 return std::make_unique(
554 MF, RA, Runner.get(),
555 getAnalysis().getMBFI(),
556 getAnalysis().getLI(), Log.get());
557 }
558
559 std::unique_ptr Runner;
560 std::unique_ptr Log;
561};
562
563#endif
564}
565
566float MLEvictAdvisor::getInitialQueueSize(const MachineFunction &MF) {
568 unsigned NumUsedRegs = 0;
569 for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
571 if (.reg_nodbg_empty(Reg))
572 ++NumUsedRegs;
573 }
574 return static_cast<float>(NumUsedRegs);
575}
576
583 InitialQSize(MLEvictAdvisor::getInitialQueueSize(MF)) {
584 assert(this->Runner);
586 DoNotNormalize.set(FeatureIDs::mask);
587 DoNotNormalize.set(FeatureIDs::is_free);
588 DoNotNormalize.set(FeatureIDs::is_hint);
589 DoNotNormalize.set(FeatureIDs::is_local);
590 DoNotNormalize.set(FeatureIDs::min_stage);
591 DoNotNormalize.set(FeatureIDs::max_stage);
592 DoNotNormalize.set(FeatureIDs::progress);
593}
594
595int64_t MLEvictAdvisor::tryFindEvictionCandidatePosition(
598 int64_t Ret = Runner->evaluate<int64_t>();
601 return Ret;
602}
603
604bool MLEvictAdvisor::loadInterferenceFeatures(
609
611
612 return false;
613 }
614
615 const bool IsLocal = LIS->intervalIsInOneMBB(VirtReg);
616 int64_t LocalIntfs = 0;
617 float NumUrgent = 0.0f;
618
619
620 unsigned Cascade = RA.getExtraInfo().getCascadeOrCurrentNext(VirtReg.reg());
621
623 for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
625
626
628 if (IFIntervals.empty() && InterferingIntervals.empty())
629 continue;
631 return false;
632 InterferingIntervals.append(IFIntervals.begin(), IFIntervals.end());
634 assert(Intf->reg().isVirtual() &&
635 "Only expecting virtual register interference from query");
636
637
638
639
640
641
642 if (FixedRegisters.count(Intf->reg()))
643 return false;
644 if (RA.getExtraInfo().getStage(*Intf) == RS_Done)
645 return false;
646 bool Urgent =
648 (Intf->isSpillable() ||
649 RegClassInfo.getNumAllocatableRegs(MRI->getRegClass(VirtReg.reg())) <
650 RegClassInfo.getNumAllocatableRegs(
651 MRI->getRegClass(Intf->reg())));
652
653 unsigned IntfCascade = RA.getExtraInfo().getCascade(Intf->reg());
654
655
656
657
658
659
660 if (IntfCascade >= MaxCascade && !Urgent)
661 return false;
662
663
664 if (Cascade <= IntfCascade) {
665 if (!Urgent)
666 return false;
667 ++NumUrgent;
668 }
669
670 LocalIntfs += (IsLocal && LIS->intervalIsInOneMBB(*Intf) &&
671 (!EnableLocalReassign || !canReassign(*Intf, PhysReg)));
672 }
673 }
674
675
676 extractFeatures(InterferingIntervals, Largest, Pos, IsHint, LocalIntfs,
677 NumUrgent, LRPosInfo);
678 return true;
679}
680
681MCRegister MLEvictAdvisor::tryFindEvictionCandidate(
684 auto MaybeOrderLimit = getOrderLimit(VirtReg, Order, CostPerUseLimit);
685 if (!MaybeOrderLimit)
687 unsigned OrderLimit = *MaybeOrderLimit;
688
689
690
691
692
693
694
695 const bool MustFindEviction =
696 (!VirtReg.isSpillable() && CostPerUseLimit == static_cast<uint8_t>(~0u));
697
699
700
701 resetInputs(*Runner);
702
703
704
705
706 CandidateRegList Regs;
707 Regs.fill({0, false});
708
709
710
711
712
713 FeaturesListNormalizer Largest(FeatureIDs::FeatureCount, 0.0);
714
715
716
717
718
719
720 size_t Pos = 0;
723 ++I, ++Pos) {
725 assert(!Regs[Pos].second);
727 if (!canAllocatePhysReg(CostPerUseLimit, PhysReg)) {
728 continue;
729 }
730 if (loadInterferenceFeatures(VirtReg, PhysReg, I.isHint(), FixedRegisters,
731 Largest, Pos, LRPosInfo)) {
733 Regs[Pos] = std::make_pair(PhysReg, true);
734 }
735 }
737
738 assert(!MustFindEviction);
740 }
741 const size_t ValidPosLimit = Pos;
742
743
745 if (!MustFindEviction)
748 0,
749 0.0, LRPosInfo);
750 assert(InitialQSize > 0.0 && "We couldn't have gotten here if we had "
751 "nothing to allocate initially.");
752#ifdef LLVM_HAVE_TFLITE
755 LRPosInfo, Runner,
756 [this](SlotIndex InputIndex) -> int {
757 auto *CurrentMachineInstruction =
758 LIS->getInstructionFromIndex(InputIndex);
759 if (!CurrentMachineInstruction) {
760 return -1;
761 }
762 return CurrentMachineInstruction->getOpcode();
763 },
764 [this](SlotIndex InputIndex) -> float {
765 auto *CurrentMachineInstruction =
766 LIS->getInstructionFromIndex(InputIndex);
768 CurrentMachineInstruction->getParent());
769 },
771 auto *CurrentMachineInstruction =
772 LIS->getInstructionFromIndex(InputIndex);
773 return CurrentMachineInstruction->getParent();
774 },
775 FeatureIDs::instructions, FeatureIDs::instructions_mapping,
776 FeatureIDs::mbb_frequencies, FeatureIDs::mbb_mapping,
777 LIS->getSlotIndexes()->getLastIndex());
778 }
779#endif
780
781 for (auto &V : Largest)
786 continue;
789 }
790 }
791 *Runner->getTensor<float>(FeatureIDs::progress) =
792 static_cast<float>(RA.getQueueSize()) / InitialQSize;
793
794
795 size_t CandidatePos = tryFindEvictionCandidatePosition(
796 VirtReg, Order, OrderLimit, CostPerUseLimit, FixedRegisters);
797
798
799 assert(Regs[CandidatePos].second);
801 assert(!MustFindEviction);
803 }
804 assert(CandidatePos < ValidPosLimit);
805 (void)ValidPosLimit;
806 return Regs[CandidatePos].first;
807}
808
809const LIFeatureComponents &
810MLEvictAdvisor::getLIFeatureComponents(const LiveInterval &LI) const {
812 LIFeatureComponents Empty;
813 auto I = CachedFeatures.insert(std::make_pair(ID, Empty));
814 LIFeatureComponents &Ret = I.first->getSecond();
815 if (.second)
816 return Ret;
817
820
822 I = MRI->reg_instr_nodbg_begin(LI.reg()),
823 E = MRI->reg_instr_nodbg_end();
824 I != E;) {
826
827 ++Ret.NumDefsAndUses;
828 if (!Visited.insert(MI).second)
829 continue;
830
831 if (MI->isIdentityCopy() || MI->isImplicitDef())
832 continue;
833
835 std::tie(Reads, Writes) = MI->readsWritesVirtualRegister(LI.reg());
836
838 Ret.HottestBlockFreq = std::max(Freq, Ret.HottestBlockFreq);
839
840 Ret.R += (Reads && ) * Freq;
841 Ret.W += (!Reads && Writes) * Freq;
842 Ret.RW += (Reads && Writes) * Freq;
843
844 auto *MBB = MI->getParent();
847
848 if (Writes && IsExiting && LIS->isLiveOutOfMBB(LI, MBB))
849 Ret.IndVarUpdates += Freq;
850
852 Ret.HintWeights += Freq;
853 }
856 return Ret;
857}
858
859
860
861void MLEvictAdvisor::extractFeatures(
864 int64_t LocalIntfsCount, float NumUrgent,
866 int64_t NumDefsAndUses = 0;
867 int64_t NumBrokenHints = 0;
868 double R = 0.0;
869 double W = 0.0;
870 double RW = 0.0;
871 double IndVarUpdates = 0.0;
872 double HintWeights = 0.0;
873 float StartBBFreq = 0.0;
874 float EndBBFreq = 0.0;
875 float HottestBlockFreq = 0.0;
876 int32_t NumRematerializable = 0;
877 float TotalWeight = 0.0;
878
879 SlotIndex EndSI = LIS->getSlotIndexes()->getZeroIndex();
880 SlotIndex StartSI = LIS->getSlotIndexes()->getLastIndex();
881 int64_t MaxStage = 0;
882 int64_t MinStage =
883 Intervals.empty() ? 0 : std::numeric_limits<int64_t>::max();
884
885 for (const auto *L : Intervals) {
887 MaxStage = std::max<int64_t>(
888 MaxStage, static_cast<int64_t>(RA.getExtraInfo().getStage(LI)));
889 MinStage = std::min<int64_t>(
890 MinStage, static_cast<int64_t>(RA.getExtraInfo().getStage(LI)));
891
892 TotalWeight = std::max(TotalWeight, LI.weight());
893
896
899 const LIFeatureComponents &LIFC = getLIFeatureComponents(LI);
900 NumBrokenHints += VRM->hasPreferredPhys(LI.reg());
901
902 NumDefsAndUses += LIFC.NumDefsAndUses;
903 HottestBlockFreq = std::max(HottestBlockFreq, LIFC.HottestBlockFreq);
904 R += LIFC.R;
905 W += LIFC.W;
906 RW += LIFC.RW;
907
908 IndVarUpdates += LIFC.IndVarUpdates;
909
910 HintWeights += LIFC.HintWeights;
911 NumRematerializable += LIFC.IsRemat;
912
914 for (auto CurrentSegment : LI) {
916 LRStartEndInfo{CurrentSegment.start, CurrentSegment.end, Pos});
917 }
918 }
919 }
920 size_t Size = 0;
921 if (!Intervals.empty()) {
922 StartBBFreq =
924 if (EndSI >= LIS->getSlotIndexes()->getLastIndex())
925 EndSI = LIS->getSlotIndexes()->getLastIndex().getPrevIndex();
926 EndBBFreq =
929 }
930
931#define SET(ID, TYPE, VAL) \
932 do { \
933 Runner->getTensor(FeatureIDs::ID)[Pos] = static_cast(VAL); \
934 if (!DoNotNormalize.test(FeatureIDs::ID)) \
935 Largest[FeatureIDs::ID] = \
936 std::max(Largest[FeatureIDs::ID], static_cast(VAL)); \
937 } while (false)
938 SET(mask, int64_t, 1);
939 SET(is_free, int64_t, Intervals.empty());
940 SET(nr_urgent, float, NumUrgent);
941 SET(nr_broken_hints, float, NumBrokenHints);
942 SET(is_hint, int64_t, IsHint);
943 SET(is_local, int64_t, LocalIntfsCount);
944 SET(nr_rematerializable, float, NumRematerializable);
945 SET(nr_defs_and_uses, float, NumDefsAndUses);
946 SET(weighed_reads_by_max, float, R);
947 SET(weighed_writes_by_max, float, W);
948 SET(weighed_read_writes_by_max, float, RW);
949 SET(weighed_indvars_by_max, float, IndVarUpdates);
950 SET(hint_weights_by_max, float, HintWeights);
951 SET(start_bb_freq_by_max, float, StartBBFreq);
952 SET(end_bb_freq_by_max, float, EndBBFreq);
953 SET(hottest_bb_freq_by_max, float, HottestBlockFreq);
954 SET(liverange_size, float, Size);
955 SET(use_def_density, float, TotalWeight);
956 SET(max_stage, int64_t, MaxStage);
957 SET(min_stage, int64_t, MinStage);
958#undef SET
959}
960
966 const int InstructionsIndex, const int InstructionsMappingIndex,
967 const int MBBFreqIndex, const int MBBMappingIndex,
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984 std::sort(
985 LRPosInfo.begin(), LRPosInfo.end(),
987 size_t InstructionIndex = 0;
988 size_t CurrentSegmentIndex = 0;
989 SlotIndex CurrentIndex = LRPosInfo[0].Begin;
990 std::map<MachineBasicBlock *, size_t> VisitedMBBs;
991 size_t CurrentMBBIndex = 0;
992
993
994
995
996
997
998
999 while (true) {
1000
1001
1002
1003 while (CurrentIndex <= LRPosInfo[CurrentSegmentIndex].End &&
1005 int CurrentOpcode = GetOpcode(CurrentIndex);
1006
1007 if (CurrentOpcode == -1) {
1008
1009
1010 if (CurrentIndex >= LastIndex) {
1011 return;
1012 }
1014 continue;
1015 }
1016 MachineBasicBlock *CurrentMBBReference = GetMBBReference(CurrentIndex);
1017 if (VisitedMBBs.count(CurrentMBBReference) == 0) {
1018 VisitedMBBs[CurrentMBBReference] = CurrentMBBIndex;
1019 ++CurrentMBBIndex;
1020 }
1022 GetMBBFreq, CurrentMBBReference, RegallocRunner,
1023 MBBFreqIndex, MBBMappingIndex);
1024
1025 assert(LRPosInfo[CurrentSegmentIndex].Begin <= CurrentIndex);
1026 RegallocRunner->getTensor<int64_t>(InstructionsIndex)[InstructionIndex] =
1027 CurrentOpcode < OpcodeValueCutoff ? CurrentOpcode : 0;
1028
1029 auto CurrentSegmentPosition = LRPosInfo[CurrentSegmentIndex].Pos;
1030 RegallocRunner->getTensor<int64_t>(
1031 InstructionsMappingIndex)[CurrentSegmentPosition *
1033 InstructionIndex] = 1;
1034
1035
1036
1037
1038
1039
1040
1041
1042 size_t OverlapCheckCurrentSegment = CurrentSegmentIndex + 1;
1043 while (OverlapCheckCurrentSegment < LRPosInfo.size() &&
1044 LRPosInfo[OverlapCheckCurrentSegment].Begin <= CurrentIndex) {
1045 auto OverlapCurrentSegmentPosition =
1046 LRPosInfo[OverlapCheckCurrentSegment].Pos;
1047 if (LRPosInfo[OverlapCheckCurrentSegment].End >= CurrentIndex) {
1048 RegallocRunner->getTensor<int64_t>(
1049 InstructionsMappingIndex)[OverlapCurrentSegmentPosition *
1051 InstructionIndex] = 1;
1052 }
1053 ++OverlapCheckCurrentSegment;
1054 }
1055 ++InstructionIndex;
1056 if (CurrentIndex >= LastIndex) {
1057 return;
1058 }
1060 }
1061
1062
1063 if (CurrentSegmentIndex == LRPosInfo.size() - 1 ||
1065 break;
1066 }
1067
1068
1069
1070 if (LRPosInfo[CurrentSegmentIndex + 1].Begin >
1071 LRPosInfo[CurrentSegmentIndex].End) {
1072 CurrentIndex = LRPosInfo[CurrentSegmentIndex + 1].Begin;
1073 }
1074 ++CurrentSegmentIndex;
1075 }
1076}
1077
1079 const SlotIndex CurrentIndex, const size_t CurrentInstructionIndex,
1080 std::map<MachineBasicBlock *, size_t> &VisitedMBBs,
1083 const int MBBFreqIndex, const int MBBMappingIndex) {
1084 size_t CurrentMBBIndex = VisitedMBBs[CurrentMBBReference];
1085 float CurrentMBBFreq = GetMBBFreq(CurrentIndex);
1087 RegallocRunner->getTensor<float>(MBBFreqIndex)[CurrentMBBIndex] =
1088 CurrentMBBFreq;
1089 RegallocRunner->getTensor<int64_t>(
1090 MBBMappingIndex)[CurrentInstructionIndex] = CurrentMBBIndex;
1091 }
1092}
1093
1094
1095#ifdef LLVM_HAVE_TFLITE
1096
1098 return new DevelopmentModeEvictionAdvisorAnalysis();
1099}
1100
1101int64_t DevelopmentModeEvictAdvisor::tryFindEvictionCandidatePosition(
1103 unsigned OrderLimit, uint8_t CostPerUseLimit,
1105 int64_t Ret = 0;
1106 if (isa(getRunner())) {
1107 Ret = MLEvictAdvisor::tryFindEvictionCandidatePosition(
1108 VirtReg, Order, OrderLimit, CostPerUseLimit, FixedRegisters);
1109 } else {
1110 MCRegister PhysReg = getDefaultAdvisor().tryFindEvictionCandidate(
1111 VirtReg, Order, CostPerUseLimit, FixedRegisters);
1112
1113
1114
1115 if (!PhysReg)
1117 else
1120 if (*I == PhysReg)
1121 break;
1122 }
1123 if (TrainingLog.empty())
1124 return Ret;
1125
1126
1127
1128 if (Log->hasObservationInProgress())
1129 Log->logReward<float>(0.0);
1130
1131 Log->startObservation();
1132 size_t CurrentFeature = 0;
1134 ? FeatureIDs::FeaturesWithDevelopmentCount
1135 : FeatureIDs::FeatureCount;
1136 for (; CurrentFeature < FeatureCount; ++CurrentFeature) {
1137 Log->logTensorValue(CurrentFeature,
1138 reinterpret_cast<const char *>(
1139 getRunner().getTensorUntyped(CurrentFeature)));
1140 }
1141 if (auto *MUTR = dyn_cast(&getRunner()))
1142 for (size_t I = 0; I < MUTR->extraOutputsForLoggingSpecs().size();
1143 ++I, ++CurrentFeature)
1144 Log->logTensorValue(
1145 CurrentFeature,
1146 reinterpret_cast<const char *>(MUTR->getUntypedExtraOutputValue(I)));
1147
1148 Log->logTensorValue(CurrentFeature, reinterpret_cast<const char *>(&Ret));
1149 Log->endObservation();
1150 return Ret;
1151}
1152
1154 std::optional CachedReward;
1155 auto GetReward = [&]() {
1156 if (!CachedReward)
1157 CachedReward = static_cast<float>(
1159 MF, getAnalysis().getMBFI())
1161 return *CachedReward;
1162 };
1163
1164 getAnalysis().logRewardIfNeeded(MF,
1165 GetReward);
1166 getAnalysis().logRewardIfNeeded(MF,
1167 GetReward);
1168 return false;
1169}
1170#endif
1171
1173 return llvm::isEmbeddedModelEvaluatorValid() ||
1175 ? new ReleaseModeEvictionAdvisorAnalysis()
1176 : nullptr;
1177}
1178
1179
1180#if !defined(LLVM_HAVE_TFLITE)
1182#endif
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 .in, while the " "outgoing name should be .out"))
static const bool EnableDevelopmentFeatures
#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, __)
static cl::opt< unsigned > MaxCascade("mlregalloc-max-cascade", cl::Hidden, cl::desc("The maximum number of times a live range can be " "evicted before preventing it from being evicted"), cl::init(20))
#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 .in, while the " "outgoing name should be " ".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.
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.