// Copyright (c) 2021 CINN Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "paddle/cinn/backends/llvm/llvm_optimizer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "llvm/Support/CodeGen.h" namespace cinn::backends { namespace { template class CustomPassManager : public PassManagerT { public: template explicit CustomPassManager(bool print_passes, Ts &&...ts) : PassManagerT(std::forward(ts)...), print_passes_(print_passes) {} void add(llvm::Pass *pass) override { if (print_passes_) { if (is_function_pass_manager_) { VLOG(1) << "llvm run function pass[" << std::string(pass->getPassName()) << "]"; } if (is_module_pass_manager_) { VLOG(1) << "llvm run module pass[" << std::string(pass->getPassName()) << "]"; } } // static bool add_pass = true; // if (add_pass) { // PassManagerT::add(pass); //} // if (std::string(pass->getPassName()) == "Loop Vectorization") { // return; //} PassManagerT::add(pass); } void run(llvm::Function &f) { // NOLINT if (is_function_pass_manager_) { PassManagerT::run(f); } } void run(llvm::Module &m) { // NOLINT if (is_module_pass_manager_) { PassManagerT::run(m); } } private: static constexpr bool is_function_pass_manager_ = std::is_same::value; static constexpr bool is_module_pass_manager_ = std::is_same::value; bool print_passes_; }; using CustomFunctionPassManager = CustomPassManager; using CustomModulePassManager = CustomPassManager; } // namespace LLVMModuleOptimizer::LLVMModuleOptimizer(llvm::TargetMachine *machine, int opt_level, llvm::FastMathFlags fast_math_flags, bool print_passes) : opt_level_(opt_level), print_passes_(print_passes), machine_(machine) {} void LLVMModuleOptimizer::operator()(llvm::Module *m) { auto machine = std::move(llvm::cantFail(llvm::cantFail(llvm::orc::JITTargetMachineBuilder::detectHost()).createTargetMachine())); auto fpm = std::make_unique(print_passes_, m); // fpm->add(llvm::createTargetTransformInfoWrapperPass(llvm::TargetIRAnalysis())); // fpm->add(llvm::createInstructionCombiningPass()); // fpm->add(llvm::createReassociatePass()); // fpm->add(llvm::createGVNPass()); // fpm->add(llvm::createCFGSimplificationPass()); // fpm->add(llvm::createSROAPass()); // fpm->add(llvm::createEarlyCSEPass()); // fpm->add(llvm::createLowerExpectIntrinsicPass()); // fpm->add(llvm::createCallSiteSplittingPass()); // fpm->add(llvm::createLoopVectorizePass()); // fpm->add(llvm::createSLPVectorizerPass()); // fpm->add(llvm::createLoadStoreVectorizerPass()); // fpm->add(llvm::createLoopUnrollPass()); auto mpm = std::make_unique(print_passes_); // mpm->add(llvm::createTargetTransformInfoWrapperPass(llvm::TargetIRAnalysis())); // LOG(INFO) << "llvm run pass: target machine: name[" << machine_->getTarget().getName() << "]"; // LOG(INFO) << "llvm run pass: target machine: cpu[" << machine_->getTargetCPU().str() << "]"; fpm->add(llvm::createTargetTransformInfoWrapperPass(machine->getTargetIRAnalysis())); mpm->add(llvm::createTargetTransformInfoWrapperPass(machine->getTargetIRAnalysis())); auto builder = std::make_unique(); builder->OptLevel = opt_level_; builder->Inliner = llvm::createFunctionInliningPass(); builder->LoopVectorize = true; builder->SLPVectorize = true; #if LLVM_VERSION_MAJOR >= 11 machine->adjustPassManager(*builder); #endif builder->populateFunctionPassManager(*fpm); builder->populateModulePassManager(*mpm); fpm->doInitialization(); std::for_each(m->begin(), m->end(), [&fpm](auto &fn) { fpm->run(fn); }); fpm->doFinalization(); mpm->run(*m); } } // namespace cinn::backends