xref: /llvm-project/llvm/lib/CodeGen/RegAllocEvictionAdvisor.cpp (revision 131d73ed3483f2ad43a2c7c0834522c0150936bb)
109103807SMircea Trofin //===- RegAllocEvictionAdvisor.cpp - eviction advisor ---------------------===//
209103807SMircea Trofin //
309103807SMircea Trofin // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409103807SMircea Trofin // See https://llvm.org/LICENSE.txt for license information.
509103807SMircea Trofin // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609103807SMircea Trofin //
709103807SMircea Trofin //===----------------------------------------------------------------------===//
809103807SMircea Trofin //
909103807SMircea Trofin // Implementation of the default eviction advisor and of the Analysis pass.
1009103807SMircea Trofin //
1109103807SMircea Trofin //===----------------------------------------------------------------------===//
1209103807SMircea Trofin 
1309103807SMircea Trofin #include "RegAllocEvictionAdvisor.h"
14989f1c72Sserge-sans-paille #include "AllocationOrder.h"
15e1212691SMircea Trofin #include "RegAllocGreedy.h"
16989f1c72Sserge-sans-paille #include "llvm/CodeGen/LiveRegMatrix.h"
1709103807SMircea Trofin #include "llvm/CodeGen/MachineFunction.h"
1809103807SMircea Trofin #include "llvm/CodeGen/RegisterClassInfo.h"
1909103807SMircea Trofin #include "llvm/CodeGen/VirtRegMap.h"
204169338eSNikita Popov #include "llvm/IR/Module.h"
2109103807SMircea Trofin #include "llvm/InitializePasses.h"
2209103807SMircea Trofin #include "llvm/Pass.h"
2309103807SMircea Trofin #include "llvm/Support/CommandLine.h"
2409103807SMircea Trofin #include "llvm/Support/ErrorHandling.h"
2509103807SMircea Trofin #include "llvm/Target/TargetMachine.h"
2609103807SMircea Trofin 
2709103807SMircea Trofin using namespace llvm;
2809103807SMircea Trofin 
2909103807SMircea Trofin static cl::opt<RegAllocEvictionAdvisorAnalysis::AdvisorMode> Mode(
30557efc9aSFangrui Song     "regalloc-enable-advisor", cl::Hidden,
3109103807SMircea Trofin     cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default),
3209103807SMircea Trofin     cl::desc("Enable regalloc advisor mode"),
3309103807SMircea Trofin     cl::values(
3409103807SMircea Trofin         clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default,
3509103807SMircea Trofin                    "default", "Default"),
3609103807SMircea Trofin         clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release,
3709103807SMircea Trofin                    "release", "precompiled"),
3809103807SMircea Trofin         clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development,
3909103807SMircea Trofin                    "development", "for training")));
4009103807SMircea Trofin 
4109103807SMircea Trofin static cl::opt<bool> EnableLocalReassignment(
4209103807SMircea Trofin     "enable-local-reassign", cl::Hidden,
4309103807SMircea Trofin     cl::desc("Local reassignment can yield better allocation decisions, but "
4409103807SMircea Trofin              "may be compile time intensive"),
4509103807SMircea Trofin     cl::init(false));
4609103807SMircea Trofin 
471e692113SFangrui Song namespace llvm {
48ed2deab5SMircea Trofin cl::opt<unsigned> EvictInterferenceCutoff(
49ed2deab5SMircea Trofin     "regalloc-eviction-max-interference-cutoff", cl::Hidden,
50ed2deab5SMircea Trofin     cl::desc("Number of interferences after which we declare "
51ed2deab5SMircea Trofin              "an interference unevictable and bail out. This "
52ed2deab5SMircea Trofin              "is a compilation cost-saving consideration. To "
53ed2deab5SMircea Trofin              "disable, pass a very large number."),
54ed2deab5SMircea Trofin     cl::init(10));
551e692113SFangrui Song }
56ed2deab5SMircea Trofin 
5709103807SMircea Trofin #define DEBUG_TYPE "regalloc"
58f29256a6SMircea Trofin #ifdef LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL
59f29256a6SMircea Trofin #define LLVM_HAVE_TF_AOT
60f29256a6SMircea Trofin #endif
6109103807SMircea Trofin 
6209103807SMircea Trofin char RegAllocEvictionAdvisorAnalysis::ID = 0;
6309103807SMircea Trofin INITIALIZE_PASS(RegAllocEvictionAdvisorAnalysis, "regalloc-evict",
6409103807SMircea Trofin                 "Regalloc eviction policy", false, true)
6509103807SMircea Trofin 
6609103807SMircea Trofin namespace {
6709103807SMircea Trofin class DefaultEvictionAdvisorAnalysis final
6809103807SMircea Trofin     : public RegAllocEvictionAdvisorAnalysis {
6909103807SMircea Trofin public:
7009103807SMircea Trofin   DefaultEvictionAdvisorAnalysis(bool NotAsRequested)
7109103807SMircea Trofin       : RegAllocEvictionAdvisorAnalysis(AdvisorMode::Default),
7209103807SMircea Trofin         NotAsRequested(NotAsRequested) {}
7309103807SMircea Trofin 
7409103807SMircea Trofin   // support for isa<> and dyn_cast.
7509103807SMircea Trofin   static bool classof(const RegAllocEvictionAdvisorAnalysis *R) {
7609103807SMircea Trofin     return R->getAdvisorMode() == AdvisorMode::Default;
7709103807SMircea Trofin   }
7809103807SMircea Trofin 
7909103807SMircea Trofin private:
8009103807SMircea Trofin   std::unique_ptr<RegAllocEvictionAdvisor>
8179b98f0aSMircea Trofin   getAdvisor(const MachineFunction &MF, const RAGreedy &RA) override {
82e1212691SMircea Trofin     return std::make_unique<DefaultEvictionAdvisor>(MF, RA);
8309103807SMircea Trofin   }
8409103807SMircea Trofin   bool doInitialization(Module &M) override {
8509103807SMircea Trofin     if (NotAsRequested)
8609103807SMircea Trofin       M.getContext().emitError("Requested regalloc eviction advisor analysis "
87b7669ed9SAdityaK                                "could not be created. Using default");
8809103807SMircea Trofin     return RegAllocEvictionAdvisorAnalysis::doInitialization(M);
8909103807SMircea Trofin   }
9009103807SMircea Trofin   const bool NotAsRequested;
9109103807SMircea Trofin };
9209103807SMircea Trofin } // namespace
9309103807SMircea Trofin 
9409103807SMircea Trofin template <> Pass *llvm::callDefaultCtor<RegAllocEvictionAdvisorAnalysis>() {
9509103807SMircea Trofin   Pass *Ret = nullptr;
9609103807SMircea Trofin   switch (Mode) {
9709103807SMircea Trofin   case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default:
9809103807SMircea Trofin     Ret = new DefaultEvictionAdvisorAnalysis(/*NotAsRequested*/ false);
9909103807SMircea Trofin     break;
10009103807SMircea Trofin   case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development:
101edc83a15SKazu Hirata #if defined(LLVM_HAVE_TFLITE)
102e67430ccSMircea Trofin     Ret = createDevelopmentModeAdvisor();
103e67430ccSMircea Trofin #endif
10409103807SMircea Trofin     break;
10509103807SMircea Trofin   case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release:
106e67430ccSMircea Trofin     Ret = createReleaseModeAdvisor();
10709103807SMircea Trofin     break;
10809103807SMircea Trofin   }
10909103807SMircea Trofin   if (Ret)
11009103807SMircea Trofin     return Ret;
11109103807SMircea Trofin   return new DefaultEvictionAdvisorAnalysis(/*NotAsRequested*/ true);
11209103807SMircea Trofin }
11309103807SMircea Trofin 
11409103807SMircea Trofin StringRef RegAllocEvictionAdvisorAnalysis::getPassName() const {
11509103807SMircea Trofin   switch (getAdvisorMode()) {
11609103807SMircea Trofin   case AdvisorMode::Default:
11709103807SMircea Trofin     return "Default Regalloc Eviction Advisor";
11809103807SMircea Trofin   case AdvisorMode::Release:
11909103807SMircea Trofin     return "Release mode Regalloc Eviction Advisor";
12009103807SMircea Trofin   case AdvisorMode::Development:
12109103807SMircea Trofin     return "Development mode Regalloc Eviction Advisor";
12209103807SMircea Trofin   }
12309103807SMircea Trofin   llvm_unreachable("Unknown advisor kind");
12409103807SMircea Trofin }
12509103807SMircea Trofin 
12679b98f0aSMircea Trofin RegAllocEvictionAdvisor::RegAllocEvictionAdvisor(const MachineFunction &MF,
127e1212691SMircea Trofin                                                  const RAGreedy &RA)
128e1212691SMircea Trofin     : MF(MF), RA(RA), Matrix(RA.getInterferenceMatrix()),
129e1212691SMircea Trofin       LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()),
130e1212691SMircea Trofin       MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()),
131e1212691SMircea Trofin       RegClassInfo(RA.getRegClassInfo()), RegCosts(TRI->getRegisterCosts(MF)),
13209103807SMircea Trofin       EnableLocalReassign(EnableLocalReassignment ||
13309103807SMircea Trofin                           MF.getSubtarget().enableRALocalReassignment(
13409103807SMircea Trofin                               MF.getTarget().getOptLevel())) {}
13522d3bbdfSMircea Trofin 
13622d3bbdfSMircea Trofin /// shouldEvict - determine if A should evict the assigned live range B. The
13722d3bbdfSMircea Trofin /// eviction policy defined by this function together with the allocation order
13822d3bbdfSMircea Trofin /// defined by enqueue() decides which registers ultimately end up being split
13922d3bbdfSMircea Trofin /// and spilled.
14022d3bbdfSMircea Trofin ///
14122d3bbdfSMircea Trofin /// Cascade numbers are used to prevent infinite loops if this function is a
14222d3bbdfSMircea Trofin /// cyclic relation.
14322d3bbdfSMircea Trofin ///
14422d3bbdfSMircea Trofin /// @param A          The live range to be assigned.
14522d3bbdfSMircea Trofin /// @param IsHint     True when A is about to be assigned to its preferred
14622d3bbdfSMircea Trofin ///                   register.
14722d3bbdfSMircea Trofin /// @param B          The live range to be evicted.
14822d3bbdfSMircea Trofin /// @param BreaksHint True when B is already assigned to its preferred register.
149592f52deSMircea Trofin bool DefaultEvictionAdvisor::shouldEvict(const LiveInterval &A, bool IsHint,
150592f52deSMircea Trofin                                          const LiveInterval &B,
15122d3bbdfSMircea Trofin                                          bool BreaksHint) const {
15222d3bbdfSMircea Trofin   bool CanSplit = RA.getExtraInfo().getStage(B) < RS_Spill;
15322d3bbdfSMircea Trofin 
15422d3bbdfSMircea Trofin   // Be fairly aggressive about following hints as long as the evictee can be
15522d3bbdfSMircea Trofin   // split.
15622d3bbdfSMircea Trofin   if (CanSplit && IsHint && !BreaksHint)
15722d3bbdfSMircea Trofin     return true;
15822d3bbdfSMircea Trofin 
15922d3bbdfSMircea Trofin   if (A.weight() > B.weight()) {
160*131d73edSCraig Topper     LLVM_DEBUG(dbgs() << "should evict: " << B << '\n');
16122d3bbdfSMircea Trofin     return true;
16222d3bbdfSMircea Trofin   }
16322d3bbdfSMircea Trofin   return false;
16422d3bbdfSMircea Trofin }
16522d3bbdfSMircea Trofin 
16622d3bbdfSMircea Trofin /// canEvictHintInterference - return true if the interference for VirtReg
16722d3bbdfSMircea Trofin /// on the PhysReg, which is VirtReg's hint, can be evicted in favor of VirtReg.
16822d3bbdfSMircea Trofin bool DefaultEvictionAdvisor::canEvictHintInterference(
169592f52deSMircea Trofin     const LiveInterval &VirtReg, MCRegister PhysReg,
17022d3bbdfSMircea Trofin     const SmallVirtRegSet &FixedRegisters) const {
17122d3bbdfSMircea Trofin   EvictionCost MaxCost;
17222d3bbdfSMircea Trofin   MaxCost.setBrokenHints(1);
17322d3bbdfSMircea Trofin   return canEvictInterferenceBasedOnCost(VirtReg, PhysReg, true, MaxCost,
17422d3bbdfSMircea Trofin                                          FixedRegisters);
17522d3bbdfSMircea Trofin }
17622d3bbdfSMircea Trofin 
17722d3bbdfSMircea Trofin /// canEvictInterferenceBasedOnCost - Return true if all interferences between
17822d3bbdfSMircea Trofin /// VirtReg and PhysReg can be evicted.
17922d3bbdfSMircea Trofin ///
18022d3bbdfSMircea Trofin /// @param VirtReg Live range that is about to be assigned.
18122d3bbdfSMircea Trofin /// @param PhysReg Desired register for assignment.
18222d3bbdfSMircea Trofin /// @param IsHint  True when PhysReg is VirtReg's preferred register.
18322d3bbdfSMircea Trofin /// @param MaxCost Only look for cheaper candidates and update with new cost
18422d3bbdfSMircea Trofin ///                when returning true.
18522d3bbdfSMircea Trofin /// @returns True when interference can be evicted cheaper than MaxCost.
18622d3bbdfSMircea Trofin bool DefaultEvictionAdvisor::canEvictInterferenceBasedOnCost(
187592f52deSMircea Trofin     const LiveInterval &VirtReg, MCRegister PhysReg, bool IsHint,
18822d3bbdfSMircea Trofin     EvictionCost &MaxCost, const SmallVirtRegSet &FixedRegisters) const {
18922d3bbdfSMircea Trofin   // It is only possible to evict virtual register interference.
19022d3bbdfSMircea Trofin   if (Matrix->checkInterference(VirtReg, PhysReg) > LiveRegMatrix::IK_VirtReg)
19122d3bbdfSMircea Trofin     return false;
19222d3bbdfSMircea Trofin 
19322d3bbdfSMircea Trofin   bool IsLocal = VirtReg.empty() || LIS->intervalIsInOneMBB(VirtReg);
19422d3bbdfSMircea Trofin 
19522d3bbdfSMircea Trofin   // Find VirtReg's cascade number. This will be unassigned if VirtReg was never
19622d3bbdfSMircea Trofin   // involved in an eviction before. If a cascade number was assigned, deny
19722d3bbdfSMircea Trofin   // evicting anything with the same or a newer cascade number. This prevents
19822d3bbdfSMircea Trofin   // infinite eviction loops.
19922d3bbdfSMircea Trofin   //
20022d3bbdfSMircea Trofin   // This works out so a register without a cascade number is allowed to evict
20122d3bbdfSMircea Trofin   // anything, and it can be evicted by anything.
20222d3bbdfSMircea Trofin   unsigned Cascade = RA.getExtraInfo().getCascadeOrCurrentNext(VirtReg.reg());
20322d3bbdfSMircea Trofin 
20422d3bbdfSMircea Trofin   EvictionCost Cost;
205aa2d0fbcSSergei Barannikov   for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
206aa2d0fbcSSergei Barannikov     LiveIntervalUnion::Query &Q = Matrix->query(VirtReg, Unit);
20722d3bbdfSMircea Trofin     // If there is 10 or more interferences, chances are one is heavier.
208ed2deab5SMircea Trofin     const auto &Interferences = Q.interferingVRegs(EvictInterferenceCutoff);
209ed2deab5SMircea Trofin     if (Interferences.size() >= EvictInterferenceCutoff)
21022d3bbdfSMircea Trofin       return false;
21122d3bbdfSMircea Trofin 
21222d3bbdfSMircea Trofin     // Check if any interfering live range is heavier than MaxWeight.
213592f52deSMircea Trofin     for (const LiveInterval *Intf : reverse(Interferences)) {
214e72ca520SCraig Topper       assert(Intf->reg().isVirtual() &&
21522d3bbdfSMircea Trofin              "Only expecting virtual register interference from query");
21622d3bbdfSMircea Trofin 
21722d3bbdfSMircea Trofin       // Do not allow eviction of a virtual register if we are in the middle
21822d3bbdfSMircea Trofin       // of last-chance recoloring and this virtual register is one that we
21922d3bbdfSMircea Trofin       // have scavenged a physical register for.
22022d3bbdfSMircea Trofin       if (FixedRegisters.count(Intf->reg()))
22122d3bbdfSMircea Trofin         return false;
22222d3bbdfSMircea Trofin 
22322d3bbdfSMircea Trofin       // Never evict spill products. They cannot split or spill.
22422d3bbdfSMircea Trofin       if (RA.getExtraInfo().getStage(*Intf) == RS_Done)
22522d3bbdfSMircea Trofin         return false;
22622d3bbdfSMircea Trofin       // Once a live range becomes small enough, it is urgent that we find a
22722d3bbdfSMircea Trofin       // register for it. This is indicated by an infinite spill weight. These
22822d3bbdfSMircea Trofin       // urgent live ranges get to evict almost anything.
22922d3bbdfSMircea Trofin       //
23022d3bbdfSMircea Trofin       // Also allow urgent evictions of unspillable ranges from a strictly
23122d3bbdfSMircea Trofin       // larger allocation order.
23222d3bbdfSMircea Trofin       bool Urgent =
23322d3bbdfSMircea Trofin           !VirtReg.isSpillable() &&
23422d3bbdfSMircea Trofin           (Intf->isSpillable() ||
23522d3bbdfSMircea Trofin            RegClassInfo.getNumAllocatableRegs(MRI->getRegClass(VirtReg.reg())) <
23622d3bbdfSMircea Trofin                RegClassInfo.getNumAllocatableRegs(
23722d3bbdfSMircea Trofin                    MRI->getRegClass(Intf->reg())));
23822d3bbdfSMircea Trofin       // Only evict older cascades or live ranges without a cascade.
23922d3bbdfSMircea Trofin       unsigned IntfCascade = RA.getExtraInfo().getCascade(Intf->reg());
240d4b1be20SMatt Arsenault       if (Cascade == IntfCascade)
241d4b1be20SMatt Arsenault         return false;
242d4b1be20SMatt Arsenault 
243d4b1be20SMatt Arsenault       if (Cascade < IntfCascade) {
24422d3bbdfSMircea Trofin         if (!Urgent)
24522d3bbdfSMircea Trofin           return false;
24622d3bbdfSMircea Trofin         // We permit breaking cascades for urgent evictions. It should be the
24722d3bbdfSMircea Trofin         // last resort, though, so make it really expensive.
24822d3bbdfSMircea Trofin         Cost.BrokenHints += 10;
24922d3bbdfSMircea Trofin       }
25022d3bbdfSMircea Trofin       // Would this break a satisfied hint?
25122d3bbdfSMircea Trofin       bool BreaksHint = VRM->hasPreferredPhys(Intf->reg());
25222d3bbdfSMircea Trofin       // Update eviction cost.
25322d3bbdfSMircea Trofin       Cost.BrokenHints += BreaksHint;
25422d3bbdfSMircea Trofin       Cost.MaxWeight = std::max(Cost.MaxWeight, Intf->weight());
25522d3bbdfSMircea Trofin       // Abort if this would be too expensive.
25622d3bbdfSMircea Trofin       if (!(Cost < MaxCost))
25722d3bbdfSMircea Trofin         return false;
25822d3bbdfSMircea Trofin       if (Urgent)
25922d3bbdfSMircea Trofin         continue;
26022d3bbdfSMircea Trofin       // Apply the eviction policy for non-urgent evictions.
26122d3bbdfSMircea Trofin       if (!shouldEvict(VirtReg, IsHint, *Intf, BreaksHint))
26222d3bbdfSMircea Trofin         return false;
26322d3bbdfSMircea Trofin       // If !MaxCost.isMax(), then we're just looking for a cheap register.
26422d3bbdfSMircea Trofin       // Evicting another local live range in this case could lead to suboptimal
26522d3bbdfSMircea Trofin       // coloring.
26622d3bbdfSMircea Trofin       if (!MaxCost.isMax() && IsLocal && LIS->intervalIsInOneMBB(*Intf) &&
26722d3bbdfSMircea Trofin           (!EnableLocalReassign || !canReassign(*Intf, PhysReg))) {
26822d3bbdfSMircea Trofin         return false;
26922d3bbdfSMircea Trofin       }
27022d3bbdfSMircea Trofin     }
27122d3bbdfSMircea Trofin   }
27222d3bbdfSMircea Trofin   MaxCost = Cost;
27322d3bbdfSMircea Trofin   return true;
27422d3bbdfSMircea Trofin }
27522d3bbdfSMircea Trofin 
27622d3bbdfSMircea Trofin MCRegister DefaultEvictionAdvisor::tryFindEvictionCandidate(
277592f52deSMircea Trofin     const LiveInterval &VirtReg, const AllocationOrder &Order,
27822d3bbdfSMircea Trofin     uint8_t CostPerUseLimit, const SmallVirtRegSet &FixedRegisters) const {
27922d3bbdfSMircea Trofin   // Keep track of the cheapest interference seen so far.
28022d3bbdfSMircea Trofin   EvictionCost BestCost;
28122d3bbdfSMircea Trofin   BestCost.setMax();
28222d3bbdfSMircea Trofin   MCRegister BestPhys;
28322d3bbdfSMircea Trofin   auto MaybeOrderLimit = getOrderLimit(VirtReg, Order, CostPerUseLimit);
28422d3bbdfSMircea Trofin   if (!MaybeOrderLimit)
28522d3bbdfSMircea Trofin     return MCRegister::NoRegister;
28622d3bbdfSMircea Trofin   unsigned OrderLimit = *MaybeOrderLimit;
28722d3bbdfSMircea Trofin 
28822d3bbdfSMircea Trofin   // When we are just looking for a reduced cost per use, don't break any
28922d3bbdfSMircea Trofin   // hints, and only evict smaller spill weights.
29022d3bbdfSMircea Trofin   if (CostPerUseLimit < uint8_t(~0u)) {
29122d3bbdfSMircea Trofin     BestCost.BrokenHints = 0;
29222d3bbdfSMircea Trofin     BestCost.MaxWeight = VirtReg.weight();
29322d3bbdfSMircea Trofin   }
29422d3bbdfSMircea Trofin 
29522d3bbdfSMircea Trofin   for (auto I = Order.begin(), E = Order.getOrderLimitEnd(OrderLimit); I != E;
29622d3bbdfSMircea Trofin        ++I) {
29722d3bbdfSMircea Trofin     MCRegister PhysReg = *I;
29822d3bbdfSMircea Trofin     assert(PhysReg);
29922d3bbdfSMircea Trofin     if (!canAllocatePhysReg(CostPerUseLimit, PhysReg) ||
30022d3bbdfSMircea Trofin         !canEvictInterferenceBasedOnCost(VirtReg, PhysReg, false, BestCost,
30122d3bbdfSMircea Trofin                                          FixedRegisters))
30222d3bbdfSMircea Trofin       continue;
30322d3bbdfSMircea Trofin 
30422d3bbdfSMircea Trofin     // Best so far.
30522d3bbdfSMircea Trofin     BestPhys = PhysReg;
30622d3bbdfSMircea Trofin 
30722d3bbdfSMircea Trofin     // Stop if the hint can be used.
30822d3bbdfSMircea Trofin     if (I.isHint())
30922d3bbdfSMircea Trofin       break;
31022d3bbdfSMircea Trofin   }
31122d3bbdfSMircea Trofin   return BestPhys;
31222d3bbdfSMircea Trofin }
313