xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/RegAllocEvictionAdvisor.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
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*04eeddc0SDimitry Andric #include "RegAllocGreedy.h"
150eae32dcSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
160eae32dcSDimitry Andric #include "llvm/CodeGen/RegisterClassInfo.h"
170eae32dcSDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
180eae32dcSDimitry Andric #include "llvm/InitializePasses.h"
190eae32dcSDimitry Andric #include "llvm/Pass.h"
200eae32dcSDimitry Andric #include "llvm/PassRegistry.h"
210eae32dcSDimitry Andric #include "llvm/Support/CommandLine.h"
220eae32dcSDimitry Andric #include "llvm/Support/ErrorHandling.h"
230eae32dcSDimitry Andric #include "llvm/Target/TargetMachine.h"
240eae32dcSDimitry Andric 
250eae32dcSDimitry Andric using namespace llvm;
260eae32dcSDimitry Andric 
270eae32dcSDimitry Andric static cl::opt<RegAllocEvictionAdvisorAnalysis::AdvisorMode> Mode(
280eae32dcSDimitry Andric     "regalloc-enable-advisor", cl::Hidden,
290eae32dcSDimitry Andric     cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default),
300eae32dcSDimitry Andric     cl::desc("Enable regalloc advisor mode"),
310eae32dcSDimitry Andric     cl::values(
320eae32dcSDimitry Andric         clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default,
330eae32dcSDimitry Andric                    "default", "Default"),
340eae32dcSDimitry Andric         clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release,
350eae32dcSDimitry Andric                    "release", "precompiled"),
360eae32dcSDimitry Andric         clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development,
370eae32dcSDimitry Andric                    "development", "for training")));
380eae32dcSDimitry Andric 
390eae32dcSDimitry Andric static cl::opt<bool> EnableLocalReassignment(
400eae32dcSDimitry Andric     "enable-local-reassign", cl::Hidden,
410eae32dcSDimitry Andric     cl::desc("Local reassignment can yield better allocation decisions, but "
420eae32dcSDimitry Andric              "may be compile time intensive"),
430eae32dcSDimitry Andric     cl::init(false));
440eae32dcSDimitry Andric 
450eae32dcSDimitry Andric #define DEBUG_TYPE "regalloc"
46*04eeddc0SDimitry Andric #ifdef LLVM_HAVE_TF_AOT_REGALLOCEVICTMODEL
47*04eeddc0SDimitry Andric #define LLVM_HAVE_TF_AOT
48*04eeddc0SDimitry Andric #endif
490eae32dcSDimitry Andric 
500eae32dcSDimitry Andric char RegAllocEvictionAdvisorAnalysis::ID = 0;
510eae32dcSDimitry Andric INITIALIZE_PASS(RegAllocEvictionAdvisorAnalysis, "regalloc-evict",
520eae32dcSDimitry Andric                 "Regalloc eviction policy", false, true)
530eae32dcSDimitry Andric 
540eae32dcSDimitry Andric namespace {
550eae32dcSDimitry Andric class DefaultEvictionAdvisorAnalysis final
560eae32dcSDimitry Andric     : public RegAllocEvictionAdvisorAnalysis {
570eae32dcSDimitry Andric public:
580eae32dcSDimitry Andric   DefaultEvictionAdvisorAnalysis(bool NotAsRequested)
590eae32dcSDimitry Andric       : RegAllocEvictionAdvisorAnalysis(AdvisorMode::Default),
600eae32dcSDimitry Andric         NotAsRequested(NotAsRequested) {}
610eae32dcSDimitry Andric 
620eae32dcSDimitry Andric   // support for isa<> and dyn_cast.
630eae32dcSDimitry Andric   static bool classof(const RegAllocEvictionAdvisorAnalysis *R) {
640eae32dcSDimitry Andric     return R->getAdvisorMode() == AdvisorMode::Default;
650eae32dcSDimitry Andric   }
660eae32dcSDimitry Andric 
670eae32dcSDimitry Andric private:
680eae32dcSDimitry Andric   std::unique_ptr<RegAllocEvictionAdvisor>
69*04eeddc0SDimitry Andric   getAdvisor(const MachineFunction &MF, const RAGreedy &RA) override {
70*04eeddc0SDimitry Andric     return std::make_unique<DefaultEvictionAdvisor>(MF, RA);
710eae32dcSDimitry Andric   }
720eae32dcSDimitry Andric   bool doInitialization(Module &M) override {
730eae32dcSDimitry Andric     if (NotAsRequested)
740eae32dcSDimitry Andric       M.getContext().emitError("Requested regalloc eviction advisor analysis "
750eae32dcSDimitry Andric                                "could be created. Using default");
760eae32dcSDimitry Andric     return RegAllocEvictionAdvisorAnalysis::doInitialization(M);
770eae32dcSDimitry Andric   }
780eae32dcSDimitry Andric   const bool NotAsRequested;
790eae32dcSDimitry Andric };
800eae32dcSDimitry Andric } // namespace
810eae32dcSDimitry Andric 
820eae32dcSDimitry Andric template <> Pass *llvm::callDefaultCtor<RegAllocEvictionAdvisorAnalysis>() {
830eae32dcSDimitry Andric   Pass *Ret = nullptr;
840eae32dcSDimitry Andric   switch (Mode) {
850eae32dcSDimitry Andric   case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default:
860eae32dcSDimitry Andric     Ret = new DefaultEvictionAdvisorAnalysis(/*NotAsRequested*/ false);
870eae32dcSDimitry Andric     break;
880eae32dcSDimitry Andric   case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development:
89*04eeddc0SDimitry Andric #if defined(LLVM_HAVE_TF_API)
90*04eeddc0SDimitry Andric     Ret = createDevelopmentModeAdvisor();
91*04eeddc0SDimitry Andric #endif
920eae32dcSDimitry Andric     break;
930eae32dcSDimitry Andric   case RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release:
94*04eeddc0SDimitry Andric #if defined(LLVM_HAVE_TF_AOT)
95*04eeddc0SDimitry Andric     Ret = createReleaseModeAdvisor();
96*04eeddc0SDimitry Andric #endif
970eae32dcSDimitry Andric     break;
980eae32dcSDimitry Andric   }
990eae32dcSDimitry Andric   if (Ret)
1000eae32dcSDimitry Andric     return Ret;
1010eae32dcSDimitry Andric   return new DefaultEvictionAdvisorAnalysis(/*NotAsRequested*/ true);
1020eae32dcSDimitry Andric }
1030eae32dcSDimitry Andric 
1040eae32dcSDimitry Andric StringRef RegAllocEvictionAdvisorAnalysis::getPassName() const {
1050eae32dcSDimitry Andric   switch (getAdvisorMode()) {
1060eae32dcSDimitry Andric   case AdvisorMode::Default:
1070eae32dcSDimitry Andric     return "Default Regalloc Eviction Advisor";
1080eae32dcSDimitry Andric   case AdvisorMode::Release:
1090eae32dcSDimitry Andric     return "Release mode Regalloc Eviction Advisor";
1100eae32dcSDimitry Andric   case AdvisorMode::Development:
1110eae32dcSDimitry Andric     return "Development mode Regalloc Eviction Advisor";
1120eae32dcSDimitry Andric   }
1130eae32dcSDimitry Andric   llvm_unreachable("Unknown advisor kind");
1140eae32dcSDimitry Andric }
1150eae32dcSDimitry Andric 
116*04eeddc0SDimitry Andric RegAllocEvictionAdvisor::RegAllocEvictionAdvisor(const MachineFunction &MF,
117*04eeddc0SDimitry Andric                                                  const RAGreedy &RA)
118*04eeddc0SDimitry Andric     : MF(MF), RA(RA), Matrix(RA.getInterferenceMatrix()),
119*04eeddc0SDimitry Andric       LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()),
120*04eeddc0SDimitry Andric       MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()),
121*04eeddc0SDimitry Andric       RegClassInfo(RA.getRegClassInfo()), RegCosts(TRI->getRegisterCosts(MF)),
1220eae32dcSDimitry Andric       EnableLocalReassign(EnableLocalReassignment ||
1230eae32dcSDimitry Andric                           MF.getSubtarget().enableRALocalReassignment(
1240eae32dcSDimitry Andric                               MF.getTarget().getOptLevel())) {}
125