xref: /freebsd-src/contrib/llvm-project/llvm/lib/Analysis/RegionPass.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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