| //===- RegAllocPriorityAdvisor.cpp - live ranges priority advisor ---------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // Implementation of the default priority advisor and of the Analysis pass. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/CodeGen/RegAllocPriorityAdvisor.h" | |
| #include "RegAllocGreedy.h" | |
| #include "llvm/CodeGen/MachineFunction.h" | |
| #include "llvm/CodeGen/VirtRegMap.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/InitializePasses.h" | |
| #include "llvm/Pass.h" | |
| using namespace llvm; | |
| static cl::opt<RegAllocPriorityAdvisorProvider::AdvisorMode> Mode( | |
| "regalloc-enable-priority-advisor", cl::Hidden, | |
| cl::init(RegAllocPriorityAdvisorProvider::AdvisorMode::Default), | |
| cl::desc("Enable regalloc advisor mode"), | |
| cl::values( | |
| clEnumValN(RegAllocPriorityAdvisorProvider::AdvisorMode::Default, | |
| "default", "Default"), | |
| clEnumValN(RegAllocPriorityAdvisorProvider::AdvisorMode::Release, | |
| "release", "precompiled"), | |
| clEnumValN(RegAllocPriorityAdvisorProvider::AdvisorMode::Development, | |
| "development", "for training"), | |
| clEnumValN( | |
| RegAllocPriorityAdvisorProvider::AdvisorMode::Dummy, "dummy", | |
| "prioritize low virtual register numbers for test and debug"))); | |
| char RegAllocPriorityAdvisorAnalysisLegacy::ID = 0; | |
| INITIALIZE_PASS(RegAllocPriorityAdvisorAnalysisLegacy, "regalloc-priority", | |
| "Regalloc priority policy", false, true) | |
| namespace { | |
| class DefaultPriorityAdvisorProvider final | |
| : public RegAllocPriorityAdvisorProvider { | |
| public: | |
| DefaultPriorityAdvisorProvider(bool NotAsRequested, LLVMContext &Ctx) | |
| : RegAllocPriorityAdvisorProvider(AdvisorMode::Default) { | |
| if (NotAsRequested) | |
| Ctx.emitError("Requested regalloc priority advisor analysis " | |
| "could not be created. Using default"); | |
| } | |
| // support for isa<> and dyn_cast. | |
| static bool classof(const RegAllocPriorityAdvisorProvider *R) { | |
| return R->getAdvisorMode() == AdvisorMode::Default; | |
| } | |
| std::unique_ptr<RegAllocPriorityAdvisor> | |
| getAdvisor(const MachineFunction &MF, const RAGreedy &RA, | |
| SlotIndexes &SI) override { | |
| return std::make_unique<DefaultPriorityAdvisor>(MF, RA, &SI); | |
| } | |
| }; | |
| class DummyPriorityAdvisorProvider final | |
| : public RegAllocPriorityAdvisorProvider { | |
| public: | |
| DummyPriorityAdvisorProvider() | |
| : RegAllocPriorityAdvisorProvider(AdvisorMode::Dummy) {} | |
| static bool classof(const RegAllocPriorityAdvisorProvider *R) { | |
| return R->getAdvisorMode() == AdvisorMode::Dummy; | |
| } | |
| std::unique_ptr<RegAllocPriorityAdvisor> | |
| getAdvisor(const MachineFunction &MF, const RAGreedy &RA, | |
| SlotIndexes &SI) override { | |
| return std::make_unique<DummyPriorityAdvisor>(MF, RA, &SI); | |
| } | |
| }; | |
| class DefaultPriorityAdvisorAnalysisLegacy final | |
| : public RegAllocPriorityAdvisorAnalysisLegacy { | |
| public: | |
| DefaultPriorityAdvisorAnalysisLegacy(bool NotAsRequested) | |
| : RegAllocPriorityAdvisorAnalysisLegacy(AdvisorMode::Default), | |
| NotAsRequested(NotAsRequested) {} | |
| // support for isa<> and dyn_cast. | |
| static bool classof(const RegAllocPriorityAdvisorAnalysisLegacy *R) { | |
| return R->getAdvisorMode() == AdvisorMode::Default; | |
| } | |
| private: | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| AU.addRequired<SlotIndexesWrapperPass>(); | |
| RegAllocPriorityAdvisorAnalysisLegacy::getAnalysisUsage(AU); | |
| } | |
| bool doInitialization(Module &M) override { | |
| Provider.reset( | |
| new DefaultPriorityAdvisorProvider(NotAsRequested, M.getContext())); | |
| return false; | |
| } | |
| const bool NotAsRequested; | |
| }; | |
| class DummyPriorityAdvisorAnalysis final | |
| : public RegAllocPriorityAdvisorAnalysisLegacy { | |
| public: | |
| using RegAllocPriorityAdvisorAnalysisLegacy::AdvisorMode; | |
| DummyPriorityAdvisorAnalysis() | |
| : RegAllocPriorityAdvisorAnalysisLegacy(AdvisorMode::Dummy) {} | |
| // support for isa<> and dyn_cast. | |
| static bool classof(const RegAllocPriorityAdvisorAnalysisLegacy *R) { | |
| return R->getAdvisorMode() == AdvisorMode::Dummy; | |
| } | |
| private: | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| AU.addRequired<SlotIndexesWrapperPass>(); | |
| RegAllocPriorityAdvisorAnalysisLegacy::getAnalysisUsage(AU); | |
| } | |
| bool doInitialization(Module &M) override { | |
| Provider.reset(new DummyPriorityAdvisorProvider()); | |
| return false; | |
| } | |
| }; | |
| } // namespace | |
| void RegAllocPriorityAdvisorAnalysis::initializeProvider(LLVMContext &Ctx) { | |
| if (Provider) | |
| return; | |
| switch (Mode) { | |
| case RegAllocPriorityAdvisorProvider::AdvisorMode::Dummy: | |
| Provider.reset(new DummyPriorityAdvisorProvider()); | |
| return; | |
| case RegAllocPriorityAdvisorProvider::AdvisorMode::Default: | |
| Provider.reset( | |
| new DefaultPriorityAdvisorProvider(/*NotAsRequested=*/false, Ctx)); | |
| return; | |
| case RegAllocPriorityAdvisorProvider::AdvisorMode::Development: | |
| #if defined(LLVM_HAVE_TFLITE) | |
| Provider.reset(createDevelopmentModePriorityAdvisorProvider(Ctx)); | |
| #endif | |
| break; | |
| case RegAllocPriorityAdvisorProvider::AdvisorMode::Release: | |
| Provider.reset(createReleaseModePriorityAdvisorProvider()); | |
| break; | |
| } | |
| // The requested advisor may not be supported by this build. | |
| if (!Provider) | |
| Provider.reset( | |
| new DefaultPriorityAdvisorProvider(/*NotAsRequested=*/true, Ctx)); | |
| } | |
| AnalysisKey RegAllocPriorityAdvisorAnalysis::Key; | |
| RegAllocPriorityAdvisorAnalysis::Result | |
| RegAllocPriorityAdvisorAnalysis::run(MachineFunction &MF, | |
| MachineFunctionAnalysisManager &MFAM) { | |
| // Lazily initialize the provider. | |
| initializeProvider(MF.getFunction().getContext()); | |
| // The requiring analysis will construct the advisor. | |
| return Result{Provider.get()}; | |
| } | |
| template <> | |
| Pass *llvm::callDefaultCtor<RegAllocPriorityAdvisorAnalysisLegacy>() { | |
| Pass *Ret = nullptr; | |
| switch (Mode) { | |
| case RegAllocPriorityAdvisorProvider::AdvisorMode::Default: | |
| Ret = new DefaultPriorityAdvisorAnalysisLegacy(/*NotAsRequested*/ false); | |
| break; | |
| case RegAllocPriorityAdvisorProvider::AdvisorMode::Development: | |
| #if defined(LLVM_HAVE_TFLITE) | |
| Ret = createDevelopmentModePriorityAdvisorAnalysis(); | |
| #endif | |
| break; | |
| case RegAllocPriorityAdvisorProvider::AdvisorMode::Release: | |
| Ret = createReleaseModePriorityAdvisorAnalysis(); | |
| break; | |
| case RegAllocPriorityAdvisorProvider::AdvisorMode::Dummy: | |
| Ret = new DummyPriorityAdvisorAnalysis(); | |
| break; | |
| } | |
| if (Ret) | |
| return Ret; | |
| return new DefaultPriorityAdvisorAnalysisLegacy(/*NotAsRequested*/ true); | |
| } | |
| StringRef RegAllocPriorityAdvisorAnalysisLegacy::getPassName() const { | |
| switch (getAdvisorMode()) { | |
| case AdvisorMode::Default: | |
| return "Default Regalloc Priority Advisor"; | |
| case AdvisorMode::Release: | |
| return "Release mode Regalloc Priority Advisor"; | |
| case AdvisorMode::Development: | |
| return "Development mode Regalloc Priority Advisor"; | |
| case AdvisorMode::Dummy: | |
| return "Dummy Regalloc Priority Advisor"; | |
| } | |
| llvm_unreachable("Unknown advisor kind"); | |
| } | |
| RegAllocPriorityAdvisor::RegAllocPriorityAdvisor(const MachineFunction &MF, | |
| const RAGreedy &RA, | |
| SlotIndexes *const Indexes) | |
| : RA(RA), LIS(RA.getLiveIntervals()), VRM(RA.getVirtRegMap()), | |
| MRI(&VRM->getRegInfo()), TRI(MF.getSubtarget().getRegisterInfo()), | |
| RegClassInfo(RA.getRegClassInfo()), Indexes(Indexes), | |
| RegClassPriorityTrumpsGlobalness( | |
| RA.getRegClassPriorityTrumpsGlobalness()), | |
| ReverseLocalAssignment(RA.getReverseLocalAssignment()) {} |