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