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 16 #include "discard_inline_module.h" 17 18 #include "llvm_ark_interface.h" 19 #include "inline_ir_utils.h" 20 #include "llvm_compiler_options.h" 21 22 #include <llvm/IR/Module.h> 23 #include <llvm/IR/Function.h> 24 #include <llvm/Pass.h> 25 #include <llvm/Support/Debug.h> 26 #include <llvm/Transforms/IPO/FunctionImport.h> 27 28 #define DEBUG_TYPE "discard-inline-module" 29 30 using llvm::convertToDeclaration; 31 32 namespace ark::llvmbackend::passes { 33 ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions * options)34bool DiscardInlineModule::ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) 35 { 36 return true; 37 } 38 39 /// Discard all functions and global variables from inline module run(llvm::Module & module,llvm::ModuleAnalysisManager &)40llvm::PreservedAnalyses DiscardInlineModule::run(llvm::Module &module, llvm::ModuleAnalysisManager & /*AM*/) 41 { 42 bool changed = false; 43 for (auto &object : module.global_objects()) { 44 changed |= DiscardIfNecessary(&object); 45 } 46 changed |= RemoveDanglingAliases(module); 47 return changed ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all(); 48 } DiscardIfNecessary(llvm::GlobalObject * object)49bool DiscardInlineModule::DiscardIfNecessary(llvm::GlobalObject *object) 50 { 51 if (object->hasMetadata(LLVMArkInterface::FUNCTION_MD_INLINE_MODULE)) { 52 if (!ShouldKeep(*object)) { 53 LLVM_DEBUG(llvm::dbgs() << "Removed '" << object->getName() << "'\n"); 54 convertToDeclaration(*object); 55 return true; 56 } 57 } 58 LLVM_DEBUG(llvm::dbgs() << "Keeping '" << object->getName() << "'\n"); 59 return false; 60 } 61 ShouldKeep(const llvm::GlobalValue & globalValue) const62bool DiscardInlineModule::ShouldKeep(const llvm::GlobalValue &globalValue) const 63 { 64 // Example: static function, constant global variable 65 return globalValue.hasLocalLinkage() 66 /** 67 * Examples: 68 * 69 * 1. Function template instantiations 70 * 2. When a class declaration defines function. Example: 71 * class Foo { 72 * int bar() { 73 * return 42; 74 * } 75 * } 76 * 77 * We keep such functions because multiple definitions are allowed for them. 78 * The linker will choose appropriate 79 */ 80 || globalValue.hasLinkOnceLinkage(); 81 } 82 83 } // namespace ark::llvmbackend::passes 84