xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/RegAllocEvictionAdvisor.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10eae32dcSDimitry Andric //===- RegAllocEvictionAdvisor.cpp - eviction advisor ---------------------===//
20eae32dcSDimitry Andric //
30eae32dcSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40eae32dcSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50eae32dcSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60eae32dcSDimitry Andric //
70eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
80eae32dcSDimitry Andric //
90eae32dcSDimitry Andric // Implementation of the default eviction advisor and of the Analysis pass.
100eae32dcSDimitry Andric //
110eae32dcSDimitry Andric //===----------------------------------------------------------------------===//
120eae32dcSDimitry Andric 
130eae32dcSDimitry Andric #include "RegAllocEvictionAdvisor.h"
1481ad6265SDimitry Andric #include "AllocationOrder.h"
1504eeddc0SDimitry Andric #include "RegAllocGreedy.h"
1681ad6265SDimitry Andric #include "llvm/CodeGen/LiveRegMatrix.h"
170eae32dcSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
180eae32dcSDimitry Andric #include "llvm/CodeGen/RegisterClassInfo.h"
190eae32dcSDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
20*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h"
210eae32dcSDimitry Andric #include "llvm/InitializePasses.h"
220eae32dcSDimitry Andric #include "llvm/Pass.h"
230eae32dcSDimitry Andric #include "llvm/Support/CommandLine.h"
240eae32dcSDimitry Andric #include "llvm/Support/ErrorHandling.h"
250eae32dcSDimitry Andric #include "llvm/Target/TargetMachine.h"
260eae32dcSDimitry Andric 
270eae32dcSDimitry Andric using namespace llvm;
280eae32dcSDimitry Andric 
290eae32dcSDimitry Andric static cl::opt<RegAllocEvictionAdvisorAnalysis::AdvisorMode> Mode(
3081ad6265SDimitry Andric     "regalloc-enable-advisor", cl::Hidden,
310eae32dcSDimitry Andric     cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default),
320eae32dcSDimitry Andric     cl::desc("Enable regalloc advisor mode"),
330eae32dcSDimitry Andric     cl::values(
340eae32dcSDimitry Andric         clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default,
350eae32dcSDimitry Andric                    "default", "Default"),
360eae32dcSDimitry Andric         clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release,
370eae32dcSDimitry Andric                    "release", "precompiled"),
380eae32dcSDimitry Andric         clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development,
390eae32dcSDimitry Andric                    "development", "for training")));
400eae32dcSDimitry Andric 
410eae32dcSDimitry Andric static cl::opt<bool> EnableLocalReassignment(
420eae32dcSDimitry Andric     "enable-local-reassign", cl::Hidden,
430eae32dcSDimitry Andric     cl::desc("Local reassignment can yield better allocation decisions, but "
440eae32dcSDimitry Andric              "may be compile time intensive"),
450eae32dcSDimitry Andric     cl::init(false));
460eae32dcSDimitry Andric 
4706c3fb27SDimitry Andric namespace llvm {
4881ad6265SDimitry Andric cl::opt<unsigned> EvictInterferenceCutoff(
4981ad6265SDimitry Andric     "regalloc-eviction-max-interference-cutoff", cl::Hidden,
5081ad6265SDimitry Andric     cl::desc("Number of interferences after which we declare "
5181ad6265SDimitry Andric              "an interference unevictable and bail out. This "
5281ad6265SDimitry Andric              "is a compilation cost-saving consideration. To "
5381ad6265SDimitry Andric              "disable, pass a very large number."),
5481ad6265SDimitry Andric     cl::init(10));
5506c3fb27SDimitry Andric }
5681ad6265SDimitry Andric 
570eae32dcSDimitry Andric #define DEBUG_TYPE "regalloc"
5804eeddc0SDimitry Andric #ifdef LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL
5904eeddc0SDimitry Andric #define LLVM_HAVE_TF_AOT
6004eeddc0SDimitry Andric #endif
610eae32dcSDimitry Andric 
620eae32dcSDimitry Andric char RegAllocEvictionAdvisorAnalysis::ID = 0;
630eae32dcSDimitry Andric INITIALIZE_PASS(RegAllocEvictionAdvisorAnalysis, "regalloc-evict",
640eae32dcSDimitry Andric                 "Regalloc eviction policy", false, true)
650eae32dcSDimitry Andric 
660eae32dcSDimitry Andric namespace {
670eae32dcSDimitry Andric class DefaultEvictionAdvisorAnalysis final
680eae32dcSDimitry Andric     : public RegAllocEvictionAdvisorAnalysis {
690eae32dcSDimitry Andric public:
700eae32dcSDimitry Andric   DefaultEvictionAdvisorAnalysis(bool NotAsRequested)
710eae32dcSDimitry Andric       : RegAllocEvictionAdvisorAnalysis(AdvisorMode::Default),
720eae32dcSDimitry Andric         NotAsRequested(NotAsRequested) {}
730eae32dcSDimitry Andric 
740eae32dcSDimitry Andric   // support for isa<> and dyn_cast.
750eae32dcSDimitry Andric   static bool classof(const RegAllocEvictionAdvisorAnalysis *R) {
760eae32dcSDimitry Andric     return R->getAdvisorMode() == AdvisorMode::Default;
770eae32dcSDimitry Andric   }
780eae32dcSDimitry Andric 
790eae32dcSDimitry Andric private:
800eae32dcSDimitry Andric   std::unique_ptr<RegAllocEvictionAdvisor>
8181ad6265SDimitry Andric   getAdvisor(const MachineFunction &MF, const RAGreedy &RA) override {
8204eeddc0SDimitry Andric     return std::make_unique<DefaultEvictionAdvisor>(MF, RA);
830eae32dcSDimitry Andric   }
840eae32dcSDimitry Andric   bool doInitialization(Module &M) override {
850eae32dcSDimitry Andric     if (NotAsRequested)
860eae32dcSDimitry Andric       M.getContext().emitError("Requested regalloc eviction advisor analysis "
875f757f3fSDimitry Andric                                "could not be created. Using default");
880eae32dcSDimitry Andric     return RegAllocEvictionAdvisorAnalysis::doInitialization(M);
890eae32dcSDimitry Andric   }
900eae32dcSDimitry Andric   const bool NotAsRequested;
910eae32dcSDimitry Andric };
920eae32dcSDimitry Andric } // namespace
930eae32dcSDimitry Andric 
940eae32dcSDimitry Andric template <> Pass *llvm::callDefaultCtor<RegAllocEvictionAdvisorAnalysis>() {
950eae32dcSDimitry Andric   Pass *Ret = nullptr;
960eae32dcSDimitry Andric   switch (Mode) {
970eae32dcSDimitry Andric   case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default:
980eae32dcSDimitry Andric     Ret = new DefaultEvictionAdvisorAnalysis(/*NotAsRequested*/ false);
990eae32dcSDimitry Andric     break;
1000eae32dcSDimitry Andric   case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development:
101bdd1243dSDimitry Andric #if defined(LLVM_HAVE_TFLITE)
10204eeddc0SDimitry Andric     Ret = createDevelopmentModeAdvisor();
10304eeddc0SDimitry Andric #endif
1040eae32dcSDimitry Andric     break;
1050eae32dcSDimitry Andric   case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release:
10604eeddc0SDimitry Andric     Ret = createReleaseModeAdvisor();
1070eae32dcSDimitry Andric     break;
1080eae32dcSDimitry Andric   }
1090eae32dcSDimitry Andric   if (Ret)
1100eae32dcSDimitry Andric     return Ret;
1110eae32dcSDimitry Andric   return new DefaultEvictionAdvisorAnalysis(/*NotAsRequested*/ true);
1120eae32dcSDimitry Andric }
1130eae32dcSDimitry Andric 
1140eae32dcSDimitry Andric StringRef RegAllocEvictionAdvisorAnalysis::getPassName() const {
1150eae32dcSDimitry Andric   switch (getAdvisorMode()) {
1160eae32dcSDimitry Andric   case AdvisorMode::Default:
1170eae32dcSDimitry Andric     return "Default Regalloc Eviction Advisor";
1180eae32dcSDimitry Andric   case AdvisorMode::Release:
1190eae32dcSDimitry Andric     return "Release mode Regalloc Eviction Advisor";
1200eae32dcSDimitry Andric   case AdvisorMode::Development:
1210eae32dcSDimitry Andric     return "Development mode Regalloc Eviction Advisor";
1220eae32dcSDimitry Andric   }
1230eae32dcSDimitry Andric   llvm_unreachable("Unknown advisor kind");
1240eae32dcSDimitry Andric }
1250eae32dcSDimitry Andric 
12681ad6265SDimitry Andric RegAllocEvictionAdvisor::RegAllocEvictionAdvisor(const MachineFunction &MF,
12704eeddc0SDimitry Andric                                                  const RAGreedy &RA)
12804eeddc0SDimitry Andric     : MF(MF), RA(RA), Matrix(RA.getInterferenceMatrix()),
12904eeddc0SDimitry Andric       LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()),
13004eeddc0SDimitry Andric       MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()),
13104eeddc0SDimitry Andric       RegClassInfo(RA.getRegClassInfo()), RegCosts(TRI->getRegisterCosts(MF)),
1320eae32dcSDimitry Andric       EnableLocalReassign(EnableLocalReassignment ||
1330eae32dcSDimitry Andric                           MF.getSubtarget().enableRALocalReassignment(
1340eae32dcSDimitry Andric                               MF.getTarget().getOptLevel())) {}
1351fd87a68SDimitry Andric 
1361fd87a68SDimitry Andric /// shouldEvict - determine if A should evict the assigned live range B. The
1371fd87a68SDimitry Andric /// eviction policy defined by this function together with the allocation order
1381fd87a68SDimitry Andric /// defined by enqueue() decides which registers ultimately end up being split
1391fd87a68SDimitry Andric /// and spilled.
1401fd87a68SDimitry Andric ///
1411fd87a68SDimitry Andric /// Cascade numbers are used to prevent infinite loops if this function is a
1421fd87a68SDimitry Andric /// cyclic relation.
1431fd87a68SDimitry Andric ///
1441fd87a68SDimitry Andric /// @param A          The live range to be assigned.
1451fd87a68SDimitry Andric /// @param IsHint     True when A is about to be assigned to its preferred
1461fd87a68SDimitry Andric ///                   register.
1471fd87a68SDimitry Andric /// @param B          The live range to be evicted.
1481fd87a68SDimitry Andric /// @param BreaksHint True when B is already assigned to its preferred register.
14981ad6265SDimitry Andric bool DefaultEvictionAdvisor::shouldEvict(const LiveInterval &A, bool IsHint,
15081ad6265SDimitry Andric                                          const LiveInterval &B,
1511fd87a68SDimitry Andric                                          bool BreaksHint) const {
1521fd87a68SDimitry Andric   bool CanSplit = RA.getExtraInfo().getStage(B) < RS_Spill;
1531fd87a68SDimitry Andric 
1541fd87a68SDimitry Andric   // Be fairly aggressive about following hints as long as the evictee can be
1551fd87a68SDimitry Andric   // split.
1561fd87a68SDimitry Andric   if (CanSplit && IsHint && !BreaksHint)
1571fd87a68SDimitry Andric     return true;
1581fd87a68SDimitry Andric 
1591fd87a68SDimitry Andric   if (A.weight() > B.weight()) {
1601fd87a68SDimitry Andric     LLVM_DEBUG(dbgs() << "should evict: " << B << " w= " << B.weight() << '\n');
1611fd87a68SDimitry Andric     return true;
1621fd87a68SDimitry Andric   }
1631fd87a68SDimitry Andric   return false;
1641fd87a68SDimitry Andric }
1651fd87a68SDimitry Andric 
1661fd87a68SDimitry Andric /// canEvictHintInterference - return true if the interference for VirtReg
1671fd87a68SDimitry Andric /// on the PhysReg, which is VirtReg's hint, can be evicted in favor of VirtReg.
1681fd87a68SDimitry Andric bool DefaultEvictionAdvisor::canEvictHintInterference(
16981ad6265SDimitry Andric     const LiveInterval &VirtReg, MCRegister PhysReg,
1701fd87a68SDimitry Andric     const SmallVirtRegSet &FixedRegisters) const {
1711fd87a68SDimitry Andric   EvictionCost MaxCost;
1721fd87a68SDimitry Andric   MaxCost.setBrokenHints(1);
1731fd87a68SDimitry Andric   return canEvictInterferenceBasedOnCost(VirtReg, PhysReg, true, MaxCost,
1741fd87a68SDimitry Andric                                          FixedRegisters);
1751fd87a68SDimitry Andric }
1761fd87a68SDimitry Andric 
1771fd87a68SDimitry Andric /// canEvictInterferenceBasedOnCost - Return true if all interferences between
1781fd87a68SDimitry Andric /// VirtReg and PhysReg can be evicted.
1791fd87a68SDimitry Andric ///
1801fd87a68SDimitry Andric /// @param VirtReg Live range that is about to be assigned.
1811fd87a68SDimitry Andric /// @param PhysReg Desired register for assignment.
1821fd87a68SDimitry Andric /// @param IsHint  True when PhysReg is VirtReg's preferred register.
1831fd87a68SDimitry Andric /// @param MaxCost Only look for cheaper candidates and update with new cost
1841fd87a68SDimitry Andric ///                when returning true.
1851fd87a68SDimitry Andric /// @returns True when interference can be evicted cheaper than MaxCost.
1861fd87a68SDimitry Andric bool DefaultEvictionAdvisor::canEvictInterferenceBasedOnCost(
18781ad6265SDimitry Andric     const LiveInterval &VirtReg, MCRegister PhysReg, bool IsHint,
1881fd87a68SDimitry Andric     EvictionCost &MaxCost, const SmallVirtRegSet &FixedRegisters) const {
1891fd87a68SDimitry Andric   // It is only possible to evict virtual register interference.
1901fd87a68SDimitry Andric   if (Matrix->checkInterference(VirtReg, PhysReg) > LiveRegMatrix::IK_VirtReg)
1911fd87a68SDimitry Andric     return false;
1921fd87a68SDimitry Andric 
1931fd87a68SDimitry Andric   bool IsLocal = VirtReg.empty() || LIS->intervalIsInOneMBB(VirtReg);
1941fd87a68SDimitry Andric 
1951fd87a68SDimitry Andric   // Find VirtReg's cascade number. This will be unassigned if VirtReg was never
1961fd87a68SDimitry Andric   // involved in an eviction before. If a cascade number was assigned, deny
1971fd87a68SDimitry Andric   // evicting anything with the same or a newer cascade number. This prevents
1981fd87a68SDimitry Andric   // infinite eviction loops.
1991fd87a68SDimitry Andric   //
2001fd87a68SDimitry Andric   // This works out so a register without a cascade number is allowed to evict
2011fd87a68SDimitry Andric   // anything, and it can be evicted by anything.
2021fd87a68SDimitry Andric   unsigned Cascade = RA.getExtraInfo().getCascadeOrCurrentNext(VirtReg.reg());
2031fd87a68SDimitry Andric 
2041fd87a68SDimitry Andric   EvictionCost Cost;
20506c3fb27SDimitry Andric   for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
20606c3fb27SDimitry Andric     LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit);
2071fd87a68SDimitry Andric     // If there is 10 or more interferences, chances are one is heavier.
20881ad6265SDimitry Andric     const auto &Interferences = Q.interferingVRegs(EvictInterferenceCutoff);
20981ad6265SDimitry Andric     if (Interferences.size() >= EvictInterferenceCutoff)
2101fd87a68SDimitry Andric       return false;
2111fd87a68SDimitry Andric 
2121fd87a68SDimitry Andric     // Check if any interfering live range is heavier than MaxWeight.
21381ad6265SDimitry Andric     for (const LiveInterval *Intf : reverse(Interferences)) {
214bdd1243dSDimitry Andric       assert(Intf->reg().isVirtual() &&
2151fd87a68SDimitry Andric              "Only expecting virtual register interference from query");
2161fd87a68SDimitry Andric 
2171fd87a68SDimitry Andric       // Do not allow eviction of a virtual register if we are in the middle
2181fd87a68SDimitry Andric       // of last-chance recoloring and this virtual register is one that we
2191fd87a68SDimitry Andric       // have scavenged a physical register for.
2201fd87a68SDimitry Andric       if (FixedRegisters.count(Intf->reg()))
2211fd87a68SDimitry Andric         return false;
2221fd87a68SDimitry Andric 
2231fd87a68SDimitry Andric       // Never evict spill products. They cannot split or spill.
2241fd87a68SDimitry Andric       if (RA.getExtraInfo().getStage(*Intf) == RS_Done)
2251fd87a68SDimitry Andric         return false;
2261fd87a68SDimitry Andric       // Once a live range becomes small enough, it is urgent that we find a
2271fd87a68SDimitry Andric       // register for it. This is indicated by an infinite spill weight. These
2281fd87a68SDimitry Andric       // urgent live ranges get to evict almost anything.
2291fd87a68SDimitry Andric       //
2301fd87a68SDimitry Andric       // Also allow urgent evictions of unspillable ranges from a strictly
2311fd87a68SDimitry Andric       // larger allocation order.
2321fd87a68SDimitry Andric       bool Urgent =
2331fd87a68SDimitry Andric           !VirtReg.isSpillable() &&
2341fd87a68SDimitry Andric           (Intf->isSpillable() ||
2351fd87a68SDimitry Andric            RegClassInfo.getNumAllocatableRegs(MRI->getRegClass(VirtReg.reg())) <
2361fd87a68SDimitry Andric                RegClassInfo.getNumAllocatableRegs(
2371fd87a68SDimitry Andric                    MRI->getRegClass(Intf->reg())));
2381fd87a68SDimitry Andric       // Only evict older cascades or live ranges without a cascade.
2391fd87a68SDimitry Andric       unsigned IntfCascade = RA.getExtraInfo().getCascade(Intf->reg());
24081ad6265SDimitry Andric       if (Cascade == IntfCascade)
24181ad6265SDimitry Andric         return false;
24281ad6265SDimitry Andric 
24381ad6265SDimitry Andric       if (Cascade < IntfCascade) {
2441fd87a68SDimitry Andric         if (!Urgent)
2451fd87a68SDimitry Andric           return false;
2461fd87a68SDimitry Andric         // We permit breaking cascades for urgent evictions. It should be the
2471fd87a68SDimitry Andric         // last resort, though, so make it really expensive.
2481fd87a68SDimitry Andric         Cost.BrokenHints += 10;
2491fd87a68SDimitry Andric       }
2501fd87a68SDimitry Andric       // Would this break a satisfied hint?
2511fd87a68SDimitry Andric       bool BreaksHint = VRM->hasPreferredPhys(Intf->reg());
2521fd87a68SDimitry Andric       // Update eviction cost.
2531fd87a68SDimitry Andric       Cost.BrokenHints += BreaksHint;
2541fd87a68SDimitry Andric       Cost.MaxWeight = std::max(Cost.MaxWeight, Intf->weight());
2551fd87a68SDimitry Andric       // Abort if this would be too expensive.
2561fd87a68SDimitry Andric       if (!(Cost < MaxCost))
2571fd87a68SDimitry Andric         return false;
2581fd87a68SDimitry Andric       if (Urgent)
2591fd87a68SDimitry Andric         continue;
2601fd87a68SDimitry Andric       // Apply the eviction policy for non-urgent evictions.
2611fd87a68SDimitry Andric       if (!shouldEvict(VirtReg, IsHint, *Intf, BreaksHint))
2621fd87a68SDimitry Andric         return false;
2631fd87a68SDimitry Andric       // If !MaxCost.isMax(), then we're just looking for a cheap register.
2641fd87a68SDimitry Andric       // Evicting another local live range in this case could lead to suboptimal
2651fd87a68SDimitry Andric       // coloring.
2661fd87a68SDimitry Andric       if (!MaxCost.isMax() && IsLocal && LIS->intervalIsInOneMBB(*Intf) &&
2671fd87a68SDimitry Andric           (!EnableLocalReassign || !canReassign(*Intf, PhysReg))) {
2681fd87a68SDimitry Andric         return false;
2691fd87a68SDimitry Andric       }
2701fd87a68SDimitry Andric     }
2711fd87a68SDimitry Andric   }
2721fd87a68SDimitry Andric   MaxCost = Cost;
2731fd87a68SDimitry Andric   return true;
2741fd87a68SDimitry Andric }
2751fd87a68SDimitry Andric 
2761fd87a68SDimitry Andric MCRegister DefaultEvictionAdvisor::tryFindEvictionCandidate(
27781ad6265SDimitry Andric     const LiveInterval &VirtReg, const AllocationOrder &Order,
2781fd87a68SDimitry Andric     uint8_t CostPerUseLimit, const SmallVirtRegSet &FixedRegisters) const {
2791fd87a68SDimitry Andric   // Keep track of the cheapest interference seen so far.
2801fd87a68SDimitry Andric   EvictionCost BestCost;
2811fd87a68SDimitry Andric   BestCost.setMax();
2821fd87a68SDimitry Andric   MCRegister BestPhys;
2831fd87a68SDimitry Andric   auto MaybeOrderLimit = getOrderLimit(VirtReg, Order, CostPerUseLimit);
2841fd87a68SDimitry Andric   if (!MaybeOrderLimit)
2851fd87a68SDimitry Andric     return MCRegister::NoRegister;
2861fd87a68SDimitry Andric   unsigned OrderLimit = *MaybeOrderLimit;
2871fd87a68SDimitry Andric 
2881fd87a68SDimitry Andric   // When we are just looking for a reduced cost per use, don't break any
2891fd87a68SDimitry Andric   // hints, and only evict smaller spill weights.
2901fd87a68SDimitry Andric   if (CostPerUseLimit < uint8_t(~0u)) {
2911fd87a68SDimitry Andric     BestCost.BrokenHints = 0;
2921fd87a68SDimitry Andric     BestCost.MaxWeight = VirtReg.weight();
2931fd87a68SDimitry Andric   }
2941fd87a68SDimitry Andric 
2951fd87a68SDimitry Andric   for (auto I = Order.begin(), E = Order.getOrderLimitEnd(OrderLimit); I != E;
2961fd87a68SDimitry Andric        ++I) {
2971fd87a68SDimitry Andric     MCRegister PhysReg = *I;
2981fd87a68SDimitry Andric     assert(PhysReg);
2991fd87a68SDimitry Andric     if (!canAllocatePhysReg(CostPerUseLimit, PhysReg) ||
3001fd87a68SDimitry Andric         !canEvictInterferenceBasedOnCost(VirtReg, PhysReg, false, BestCost,
3011fd87a68SDimitry Andric                                          FixedRegisters))
3021fd87a68SDimitry Andric       continue;
3031fd87a68SDimitry Andric 
3041fd87a68SDimitry Andric     // Best so far.
3051fd87a68SDimitry Andric     BestPhys = PhysReg;
3061fd87a68SDimitry Andric 
3071fd87a68SDimitry Andric     // Stop if the hint can be used.
3081fd87a68SDimitry Andric     if (I.isHint())
3091fd87a68SDimitry Andric       break;
3101fd87a68SDimitry Andric   }
3111fd87a68SDimitry Andric   return BestPhys;
3121fd87a68SDimitry Andric }
313