1/* 2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16namespace ark::libllvmbackend { 17 18void RegisterPasses(llvm::PassInstrumentationCallbacks &passInstrumentation) 19{ 20 auto registerName = [&passInstrumentation](llvm::StringRef className, llvm::StringRef passName) { 21 passInstrumentation.addClassToPassName(className, passName); 22 }; 23 24% PassRegistry::llvm_passes.each do |pass| 25 registerName("<%= PassRegistry::passes_namespace %>::<%= pass.name %>", <%= PassRegistry::passes_namespace %>::<%= pass.name %>::ARG_NAME); 26% end 27} 28 29using StringRef = llvm::StringRef; 30using LLVMCompilerOptions = ark::llvmbackend::LLVMCompilerOptions; 31using PipelineElements = llvm::ArrayRef<llvm::PassBuilder::PipelineElement>; 32 33struct PassParser 34{ 35public: 36 explicit PassParser(ark::llvmbackend::LLVMArkInterface *arkInterface) : arkInterface_{arkInterface} 37 { 38 } 39 40 bool ParseModulePasses(StringRef name, llvm::ModulePassManager &modulePm, const LLVMCompilerOptions &options); 41 bool ParseFunctionPasses(StringRef name, llvm::FunctionPassManager &functionPm, const LLVMCompilerOptions &options); 42 bool ParseSCCPasses(StringRef name, llvm::CGSCCPassManager &sccPm, const LLVMCompilerOptions &options); 43 bool ParseLoopPasses(StringRef name, llvm::LoopPassManager &sccPm, const LLVMCompilerOptions &options); 44 45 void RegisterParserCallbacks(llvm::PassBuilder &builder, const ark::llvmbackend::LLVMCompilerOptions &options) 46 { 47 builder.registerPipelineParsingCallback( 48 [&](StringRef name, llvm::ModulePassManager &modulePm, PipelineElements /*unused*/) -> bool { 49 return ParseModulePasses(name, modulePm, options); 50 }); 51 builder.registerPipelineParsingCallback( 52 [&](StringRef name, llvm::FunctionPassManager &functionPm, PipelineElements /*unused*/) -> bool { 53 return ParseFunctionPasses(name, functionPm, options); 54 }); 55 builder.registerPipelineParsingCallback( 56 [&](StringRef name, llvm::CGSCCPassManager &sccPm, PipelineElements /*unused*/) -> bool { 57 return ParseSCCPasses(name, sccPm, options); 58 }); 59 builder.registerPipelineParsingCallback( 60 [&](StringRef name, llvm::LoopPassManager &sccPm, PipelineElements /*unused*/) -> bool { 61 return ParseLoopPasses(name, sccPm, options); 62 }); 63 } 64private: 65 ark::llvmbackend::LLVMArkInterface *arkInterface_; 66}; 67 68bool PassParser::ParseModulePasses(StringRef name, llvm::ModulePassManager &modulePm, const LLVMCompilerOptions &options) 69{ 70 auto &pm = modulePm; 71 namespace pass = <%= PassRegistry::passes_namespace %>; 72 73% PassRegistry::llvm_passes.select{|p| p.type.include? 'module'}.each do |pass| 74 if (name.equals(pass::<%= pass.name %>::ARG_NAME)) { 75 if (pass::<%= pass.name %>::ShouldInsert(&options)) { 76% if pass.setup == 'default' 77 pm.addPass(pass::<%= pass.name %>()); 78% else 79 pm.addPass(pass::<%= pass.name %>::Create(arkInterface_, &options)); 80% end 81#ifndef NDEBUG 82 pm.addPass(llvm::VerifierPass()); 83#endif 84 } 85 return true; 86 } 87% end 88 89 return false; 90} 91 92bool PassParser::ParseFunctionPasses(StringRef name, llvm::FunctionPassManager &functionPm, const LLVMCompilerOptions &options) 93{ 94 auto &pm = functionPm; 95 namespace pass = <%= PassRegistry::passes_namespace %>; 96 97% PassRegistry::llvm_passes.select{|p| p.type.include? 'function'}.each do |pass| 98 if (name.equals(pass::<%= pass.name %>::ARG_NAME)) { 99 if (pass::<%= pass.name %>::ShouldInsert(&options)) { 100% if pass.setup == 'default' 101 pm.addPass(pass::<%= pass.name %>()); 102% else 103 pm.addPass(pass::<%= pass.name %>::Create(arkInterface_, &options)); 104% end 105#ifndef NDEBUG 106 pm.addPass(llvm::VerifierPass()); 107#endif 108 } 109 return true; 110 } 111% end 112 113 return false; 114} 115 116bool PassParser::ParseSCCPasses(StringRef name, llvm::CGSCCPassManager &sccPm, const LLVMCompilerOptions &options) 117{ 118 auto &pm = sccPm; 119 namespace pass = <%= PassRegistry::passes_namespace %>; 120 121% PassRegistry::llvm_passes.select{|p| p.type.include? 'scc'}.each do |pass| 122 if (name.equals(pass::<%= pass.name %>::ARG_NAME)) { 123 if (pass::<%= pass.name %>::ShouldInsert(&options)) { 124% if pass.setup == 'default' 125 pm.addPass(pass::<%= pass.name %>()); 126% else 127 pm.addPass(pass::<%= pass.name %>::Create(arkInterface_, &options)); 128% end 129 } 130 return true; 131 } 132% end 133 134 return false; 135} 136 137bool PassParser::ParseLoopPasses(StringRef name, llvm::LoopPassManager &loopPm, const LLVMCompilerOptions &options) 138{ 139 auto &pm = loopPm; 140 namespace pass = <%= PassRegistry::passes_namespace %>; 141 142% PassRegistry::llvm_passes.select{|p| p.type.include? 'loop'}.each do |pass| 143 if (name.equals(pass::<%= pass.name %>::ARG_NAME)) { 144 if (pass::<%= pass.name %>::ShouldInsert(&options)) { 145% if pass.setup == 'default' 146 pm.addPass(pass::<%= pass.name %>()); 147% else 148 pm.addPass(pass::<%= pass.name %>::Create(arkInterface_, &options)); 149% end 150 } 151 return true; 152 } 153% end 154 155 return false; 156} 157 158} // namespace ark::libllvmbackend 159