10b57cec5SDimitry Andric //===- RegionPass.cpp - Region Pass and Region Pass Manager ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements RegionPass and RGPassManager. All region optimization
100b57cec5SDimitry Andric // and transformation passes are derived from RegionPass. RGPassManager is
110b57cec5SDimitry Andric // responsible for managing RegionPasses.
120b57cec5SDimitry Andric // Most of this code has been COPIED from LoopPass.cpp
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1581ad6265SDimitry Andric
160b57cec5SDimitry Andric #include "llvm/Analysis/RegionPass.h"
1781ad6265SDimitry Andric #include "llvm/Analysis/RegionInfo.h"
180b57cec5SDimitry Andric #include "llvm/IR/OptBisect.h"
190b57cec5SDimitry Andric #include "llvm/IR/PassTimingInfo.h"
204824e7fdSDimitry Andric #include "llvm/IR/PrintPasses.h"
210b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
220b57cec5SDimitry Andric #include "llvm/Support/Timer.h"
230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
2481ad6265SDimitry Andric
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric #define DEBUG_TYPE "regionpassmgr"
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
300b57cec5SDimitry Andric // RGPassManager
310b57cec5SDimitry Andric //
320b57cec5SDimitry Andric
330b57cec5SDimitry Andric char RGPassManager::ID = 0;
340b57cec5SDimitry Andric
RGPassManager()3504eeddc0SDimitry Andric RGPassManager::RGPassManager() : FunctionPass(ID) {
360b57cec5SDimitry Andric RI = nullptr;
370b57cec5SDimitry Andric CurrentRegion = nullptr;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric // Recurse through all subregions and all regions into RQ.
addRegionIntoQueue(Region & R,std::deque<Region * > & RQ)410b57cec5SDimitry Andric static void addRegionIntoQueue(Region &R, std::deque<Region *> &RQ) {
420b57cec5SDimitry Andric RQ.push_back(&R);
430b57cec5SDimitry Andric for (const auto &E : R)
440b57cec5SDimitry Andric addRegionIntoQueue(*E, RQ);
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric
470b57cec5SDimitry Andric /// Pass Manager itself does not invalidate any analysis info.
getAnalysisUsage(AnalysisUsage & Info) const480b57cec5SDimitry Andric void RGPassManager::getAnalysisUsage(AnalysisUsage &Info) const {
490b57cec5SDimitry Andric Info.addRequired<RegionInfoPass>();
500b57cec5SDimitry Andric Info.setPreservesAll();
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric /// run - Execute all of the passes scheduled for execution. Keep track of
540b57cec5SDimitry Andric /// whether any of the passes modifies the function, and if so, return true.
runOnFunction(Function & F)550b57cec5SDimitry Andric bool RGPassManager::runOnFunction(Function &F) {
560b57cec5SDimitry Andric RI = &getAnalysis<RegionInfoPass>().getRegionInfo();
570b57cec5SDimitry Andric bool Changed = false;
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric // Collect inherited analysis from Module level pass manager.
600b57cec5SDimitry Andric populateInheritedAnalysis(TPM->activeStack);
610b57cec5SDimitry Andric
620b57cec5SDimitry Andric addRegionIntoQueue(*RI->getTopLevelRegion(), RQ);
630b57cec5SDimitry Andric
640b57cec5SDimitry Andric if (RQ.empty()) // No regions, skip calling finalizers
650b57cec5SDimitry Andric return false;
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric // Initialization
680b57cec5SDimitry Andric for (Region *R : RQ) {
690b57cec5SDimitry Andric for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
700b57cec5SDimitry Andric RegionPass *RP = (RegionPass *)getContainedPass(Index);
710b57cec5SDimitry Andric Changed |= RP->doInitialization(R, *this);
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric // Walk Regions
760b57cec5SDimitry Andric while (!RQ.empty()) {
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric CurrentRegion = RQ.back();
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric // Run all passes on the current Region.
810b57cec5SDimitry Andric for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
820b57cec5SDimitry Andric RegionPass *P = (RegionPass*)getContainedPass(Index);
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric if (isPassDebuggingExecutionsOrMore()) {
850b57cec5SDimitry Andric dumpPassInfo(P, EXECUTION_MSG, ON_REGION_MSG,
860b57cec5SDimitry Andric CurrentRegion->getNameStr());
870b57cec5SDimitry Andric dumpRequiredSet(P);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric initializeAnalysisImpl(P);
910b57cec5SDimitry Andric
92e8d8bef9SDimitry Andric bool LocalChanged = false;
930b57cec5SDimitry Andric {
940b57cec5SDimitry Andric PassManagerPrettyStackEntry X(P, *CurrentRegion->getEntry());
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric TimeRegion PassTimer(getPassTimer(P));
97e8d8bef9SDimitry Andric #ifdef EXPENSIVE_CHECKS
9881ad6265SDimitry Andric uint64_t RefHash = P->structuralHash(F);
99e8d8bef9SDimitry Andric #endif
100e8d8bef9SDimitry Andric LocalChanged = P->runOnRegion(CurrentRegion, *this);
101e8d8bef9SDimitry Andric
102e8d8bef9SDimitry Andric #ifdef EXPENSIVE_CHECKS
10381ad6265SDimitry Andric if (!LocalChanged && (RefHash != P->structuralHash(F))) {
104e8d8bef9SDimitry Andric llvm::errs() << "Pass modifies its input and doesn't report it: "
105e8d8bef9SDimitry Andric << P->getPassName() << "\n";
106e8d8bef9SDimitry Andric llvm_unreachable("Pass modifies its input and doesn't report it");
107e8d8bef9SDimitry Andric }
108e8d8bef9SDimitry Andric #endif
109e8d8bef9SDimitry Andric
110e8d8bef9SDimitry Andric Changed |= LocalChanged;
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric
1130b57cec5SDimitry Andric if (isPassDebuggingExecutionsOrMore()) {
114e8d8bef9SDimitry Andric if (LocalChanged)
1150b57cec5SDimitry Andric dumpPassInfo(P, MODIFICATION_MSG, ON_REGION_MSG,
1160b57cec5SDimitry Andric CurrentRegion->getNameStr());
1170b57cec5SDimitry Andric dumpPreservedSet(P);
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric // Manually check that this region is still healthy. This is done
1210b57cec5SDimitry Andric // instead of relying on RegionInfo::verifyRegion since RegionInfo
1220b57cec5SDimitry Andric // is a function pass and it's really expensive to verify every
1230b57cec5SDimitry Andric // Region in the function every time. That level of checking can be
1240b57cec5SDimitry Andric // enabled with the -verify-region-info option.
1250b57cec5SDimitry Andric {
1260b57cec5SDimitry Andric TimeRegion PassTimer(getPassTimer(P));
1270b57cec5SDimitry Andric CurrentRegion->verifyRegion();
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric // Then call the regular verifyAnalysis functions.
1310b57cec5SDimitry Andric verifyPreservedAnalysis(P);
1320b57cec5SDimitry Andric
133e8d8bef9SDimitry Andric if (LocalChanged)
1340b57cec5SDimitry Andric removeNotPreservedAnalysis(P);
1350b57cec5SDimitry Andric recordAvailableAnalysis(P);
1360b57cec5SDimitry Andric removeDeadPasses(P,
137e8d8bef9SDimitry Andric (!isPassDebuggingExecutionsOrMore())
138e8d8bef9SDimitry Andric ? "<deleted>"
139e8d8bef9SDimitry Andric : CurrentRegion->getNameStr(),
1400b57cec5SDimitry Andric ON_REGION_MSG);
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric // Pop the region from queue after running all passes.
1440b57cec5SDimitry Andric RQ.pop_back();
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric // Free all region nodes created in region passes.
1470b57cec5SDimitry Andric RI->clearNodeCache();
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric
1500b57cec5SDimitry Andric // Finalization
1510b57cec5SDimitry Andric for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
1520b57cec5SDimitry Andric RegionPass *P = (RegionPass*)getContainedPass(Index);
1530b57cec5SDimitry Andric Changed |= P->doFinalization();
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric // Print the region tree after all pass.
1570b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\nRegion tree of function " << F.getName()
1580b57cec5SDimitry Andric << " after all region Pass:\n";
1590b57cec5SDimitry Andric RI->dump(); dbgs() << "\n";);
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric return Changed;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric /// Print passes managed by this manager
dumpPassStructure(unsigned Offset)1650b57cec5SDimitry Andric void RGPassManager::dumpPassStructure(unsigned Offset) {
1660b57cec5SDimitry Andric errs().indent(Offset*2) << "Region Pass Manager\n";
1670b57cec5SDimitry Andric for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
1680b57cec5SDimitry Andric Pass *P = getContainedPass(Index);
1690b57cec5SDimitry Andric P->dumpPassStructure(Offset + 1);
1700b57cec5SDimitry Andric dumpLastUses(P, Offset+1);
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andric namespace {
1750b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1760b57cec5SDimitry Andric // PrintRegionPass
1770b57cec5SDimitry Andric class PrintRegionPass : public RegionPass {
1780b57cec5SDimitry Andric private:
1790b57cec5SDimitry Andric std::string Banner;
1800b57cec5SDimitry Andric raw_ostream &Out; // raw_ostream to print on.
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric public:
1830b57cec5SDimitry Andric static char ID;
PrintRegionPass(const std::string & B,raw_ostream & o)1840b57cec5SDimitry Andric PrintRegionPass(const std::string &B, raw_ostream &o)
1850b57cec5SDimitry Andric : RegionPass(ID), Banner(B), Out(o) {}
1860b57cec5SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const1870b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
1880b57cec5SDimitry Andric AU.setPreservesAll();
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric
runOnRegion(Region * R,RGPassManager & RGM)1910b57cec5SDimitry Andric bool runOnRegion(Region *R, RGPassManager &RGM) override {
1924824e7fdSDimitry Andric if (!isFunctionInPrintList(R->getEntry()->getParent()->getName()))
1934824e7fdSDimitry Andric return false;
1940b57cec5SDimitry Andric Out << Banner;
1950b57cec5SDimitry Andric for (const auto *BB : R->blocks()) {
1960b57cec5SDimitry Andric if (BB)
1970b57cec5SDimitry Andric BB->print(Out);
1980b57cec5SDimitry Andric else
1990b57cec5SDimitry Andric Out << "Printing <null> Block";
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric
2020b57cec5SDimitry Andric return false;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric
getPassName() const2050b57cec5SDimitry Andric StringRef getPassName() const override { return "Print Region IR"; }
2060b57cec5SDimitry Andric };
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric char PrintRegionPass::ID = 0;
2090b57cec5SDimitry Andric } //end anonymous namespace
2100b57cec5SDimitry Andric
2110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2120b57cec5SDimitry Andric // RegionPass
2130b57cec5SDimitry Andric
2140b57cec5SDimitry Andric // Check if this pass is suitable for the current RGPassManager, if
2150b57cec5SDimitry Andric // available. This pass P is not suitable for a RGPassManager if P
2160b57cec5SDimitry Andric // is not preserving higher level analysis info used by other
2170b57cec5SDimitry Andric // RGPassManager passes. In such case, pop RGPassManager from the
2180b57cec5SDimitry Andric // stack. This will force assignPassManager() to create new
2190b57cec5SDimitry Andric // LPPassManger as expected.
preparePassManager(PMStack & PMS)2200b57cec5SDimitry Andric void RegionPass::preparePassManager(PMStack &PMS) {
2210b57cec5SDimitry Andric
2220b57cec5SDimitry Andric // Find RGPassManager
2230b57cec5SDimitry Andric while (!PMS.empty() &&
2240b57cec5SDimitry Andric PMS.top()->getPassManagerType() > PMT_RegionPassManager)
2250b57cec5SDimitry Andric PMS.pop();
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andric
2280b57cec5SDimitry Andric // If this pass is destroying high level information that is used
2290b57cec5SDimitry Andric // by other passes that are managed by LPM then do not insert
2300b57cec5SDimitry Andric // this pass in current LPM. Use new RGPassManager.
2310b57cec5SDimitry Andric if (PMS.top()->getPassManagerType() == PMT_RegionPassManager &&
2320b57cec5SDimitry Andric !PMS.top()->preserveHigherLevelAnalysis(this))
2330b57cec5SDimitry Andric PMS.pop();
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric /// Assign pass manager to manage this pass.
assignPassManager(PMStack & PMS,PassManagerType PreferredType)2370b57cec5SDimitry Andric void RegionPass::assignPassManager(PMStack &PMS,
2380b57cec5SDimitry Andric PassManagerType PreferredType) {
2390b57cec5SDimitry Andric // Find RGPassManager
2400b57cec5SDimitry Andric while (!PMS.empty() &&
2410b57cec5SDimitry Andric PMS.top()->getPassManagerType() > PMT_RegionPassManager)
2420b57cec5SDimitry Andric PMS.pop();
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric RGPassManager *RGPM;
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric // Create new Region Pass Manager if it does not exist.
2470b57cec5SDimitry Andric if (PMS.top()->getPassManagerType() == PMT_RegionPassManager)
2480b57cec5SDimitry Andric RGPM = (RGPassManager*)PMS.top();
2490b57cec5SDimitry Andric else {
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric assert (!PMS.empty() && "Unable to create Region Pass Manager");
2520b57cec5SDimitry Andric PMDataManager *PMD = PMS.top();
2530b57cec5SDimitry Andric
2540b57cec5SDimitry Andric // [1] Create new Region Pass Manager
2550b57cec5SDimitry Andric RGPM = new RGPassManager();
2560b57cec5SDimitry Andric RGPM->populateInheritedAnalysis(PMS);
2570b57cec5SDimitry Andric
2580b57cec5SDimitry Andric // [2] Set up new manager's top level manager
2590b57cec5SDimitry Andric PMTopLevelManager *TPM = PMD->getTopLevelManager();
2600b57cec5SDimitry Andric TPM->addIndirectPassManager(RGPM);
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric // [3] Assign manager to manage this new manager. This may create
2630b57cec5SDimitry Andric // and push new managers into PMS
2640b57cec5SDimitry Andric TPM->schedulePass(RGPM);
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric // [4] Push new manager into PMS
2670b57cec5SDimitry Andric PMS.push(RGPM);
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric
2700b57cec5SDimitry Andric RGPM->add(this);
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric
2730b57cec5SDimitry Andric /// Get the printer pass
createPrinterPass(raw_ostream & O,const std::string & Banner) const2740b57cec5SDimitry Andric Pass *RegionPass::createPrinterPass(raw_ostream &O,
2750b57cec5SDimitry Andric const std::string &Banner) const {
2760b57cec5SDimitry Andric return new PrintRegionPass(Banner, O);
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric
getDescription(const Region & R)2790b57cec5SDimitry Andric static std::string getDescription(const Region &R) {
2800b57cec5SDimitry Andric return "region";
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric
skipRegion(Region & R) const2830b57cec5SDimitry Andric bool RegionPass::skipRegion(Region &R) const {
2840b57cec5SDimitry Andric Function &F = *R.getEntry()->getParent();
2850b57cec5SDimitry Andric OptPassGate &Gate = F.getContext().getOptPassGate();
286*bdd1243dSDimitry Andric if (Gate.isEnabled() &&
287*bdd1243dSDimitry Andric !Gate.shouldRunPass(this->getPassName(), getDescription(R)))
2880b57cec5SDimitry Andric return true;
2890b57cec5SDimitry Andric
2900b57cec5SDimitry Andric if (F.hasOptNone()) {
2910b57cec5SDimitry Andric // Report this only once per function.
2920b57cec5SDimitry Andric if (R.getEntry() == &F.getEntryBlock())
2930b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Skipping pass '" << getPassName()
2940b57cec5SDimitry Andric << "' on function " << F.getName() << "\n");
2950b57cec5SDimitry Andric return true;
2960b57cec5SDimitry Andric }
2970b57cec5SDimitry Andric return false;
2980b57cec5SDimitry Andric }
299