//===---- Canonicalization.cpp - Run canonicalization passes --------------===// // // 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 // //===----------------------------------------------------------------------===// // // Run the set of default canonicalization passes. // // This pass is mainly used for debugging. // //===----------------------------------------------------------------------===// #include "polly/Canonicalization.h" #include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/FunctionAttrs.h" #include "llvm/Transforms/InstCombine/InstCombine.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar/EarlyCSE.h" #include "llvm/Transforms/Scalar/IndVarSimplify.h" #include "llvm/Transforms/Scalar/LoopRotation.h" #include "llvm/Transforms/Scalar/Reassociate.h" #include "llvm/Transforms/Scalar/SimplifyCFG.h" #include "llvm/Transforms/Scalar/TailRecursionElimination.h" #include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/Mem2Reg.h" using namespace llvm; using namespace polly; static cl::opt PollyInliner("polly-run-inliner", cl::desc("Run an early inliner pass before Polly"), cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); void polly::registerCanonicalicationPasses(llvm::legacy::PassManagerBase &PM) { bool UseMemSSA = true; PM.add(llvm::createPromoteMemoryToRegisterPass()); PM.add(llvm::createEarlyCSEPass(UseMemSSA)); PM.add(llvm::createInstructionCombiningPass()); PM.add(llvm::createCFGSimplificationPass()); PM.add(llvm::createTailCallEliminationPass()); PM.add(llvm::createCFGSimplificationPass()); PM.add(llvm::createReassociatePass()); PM.add(llvm::createLoopRotatePass()); if (PollyInliner) { PM.add(llvm::createFunctionInliningPass(200)); PM.add(llvm::createPromoteMemoryToRegisterPass()); PM.add(llvm::createCFGSimplificationPass()); PM.add(llvm::createInstructionCombiningPass()); PM.add(createBarrierNoopPass()); } PM.add(llvm::createInstructionCombiningPass()); PM.add(llvm::createIndVarSimplifyPass()); } /// Adapted from llvm::PassBuilder::buildInlinerPipeline static ModuleInlinerWrapperPass buildInlinePasses(llvm::OptimizationLevel Level) { InlineParams IP = getInlineParams(200); ModuleInlinerWrapperPass MIWP(IP); // Require the GlobalsAA analysis for the module so we can query it within // the CGSCC pipeline. MIWP.addModulePass(RequireAnalysisPass()); // Invalidate AAManager so it can be recreated and pick up the newly available // GlobalsAA. MIWP.addModulePass( createModuleToFunctionPassAdaptor(InvalidateAnalysisPass())); // Require the ProfileSummaryAnalysis for the module so we can query it within // the inliner pass. MIWP.addModulePass(RequireAnalysisPass()); // Now begin the main postorder CGSCC pipeline. // FIXME: The current CGSCC pipeline has its origins in the legacy pass // manager and trying to emulate its precise behavior. Much of this doesn't // make a lot of sense and we should revisit the core CGSCC structure. CGSCCPassManager &MainCGPipeline = MIWP.getPM(); // Now deduce any function attributes based in the current code. MainCGPipeline.addPass(PostOrderFunctionAttrsPass()); return MIWP; } FunctionPassManager polly::buildCanonicalicationPassesForNPM(llvm::ModulePassManager &MPM, llvm::OptimizationLevel Level) { FunctionPassManager FPM; bool UseMemSSA = true; FPM.addPass(PromotePass()); FPM.addPass(EarlyCSEPass(UseMemSSA)); FPM.addPass(InstCombinePass()); FPM.addPass(SimplifyCFGPass()); FPM.addPass(TailCallElimPass()); FPM.addPass(SimplifyCFGPass()); FPM.addPass(ReassociatePass()); { LoopPassManager LPM; LPM.addPass(LoopRotatePass(Level != OptimizationLevel::Oz)); FPM.addPass(createFunctionToLoopPassAdaptor( std::move(LPM), /*UseMemorySSA=*/false, /*UseBlockFrequencyInfo=*/false)); } if (PollyInliner) { MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); MPM.addPass(buildInlinePasses(Level)); FPM = FunctionPassManager(); FPM.addPass(PromotePass()); FPM.addPass(SimplifyCFGPass()); FPM.addPass(InstCombinePass()); } FPM.addPass(InstCombinePass()); { LoopPassManager LPM; LPM.addPass(IndVarSimplifyPass()); FPM.addPass(createFunctionToLoopPassAdaptor( std::move(LPM), /*UseMemorySSA=*/false, /*UseBlockFrequencyInfo=*/true)); } return FPM; } namespace { class PollyCanonicalize : public ModulePass { PollyCanonicalize(const PollyCanonicalize &) = delete; const PollyCanonicalize &operator=(const PollyCanonicalize &) = delete; public: static char ID; explicit PollyCanonicalize() : ModulePass(ID) {} ~PollyCanonicalize(); /// @name FunctionPass interface. //@{ void getAnalysisUsage(AnalysisUsage &AU) const override; void releaseMemory() override; bool runOnModule(Module &M) override; void print(raw_ostream &OS, const Module *) const override; //@} }; } // namespace PollyCanonicalize::~PollyCanonicalize() {} void PollyCanonicalize::getAnalysisUsage(AnalysisUsage &AU) const {} void PollyCanonicalize::releaseMemory() {} bool PollyCanonicalize::runOnModule(Module &M) { legacy::PassManager PM; registerCanonicalicationPasses(PM); PM.run(M); return true; } void PollyCanonicalize::print(raw_ostream &OS, const Module *) const {} char PollyCanonicalize::ID = 0; Pass *polly::createPollyCanonicalizePass() { return new PollyCanonicalize(); } INITIALIZE_PASS_BEGIN(PollyCanonicalize, "polly-canonicalize", "Polly - Run canonicalization passes", false, false) INITIALIZE_PASS_END(PollyCanonicalize, "polly-canonicalize", "Polly - Run canonicalization passes", false, false)