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