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