• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 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 "transforms/builtins.h"
17 #include "transforms/passes/check_external.h"
18 #include "transforms/transform_utils.h"
19 #include "utils.h"
20 #include "llvm_ark_interface.h"
21 #include "llvm_compiler_options.h"
22 
23 namespace ark::llvmbackend::passes {
24 
Create()25 CheckExternal CheckExternal::Create()
26 {
27     return CheckExternal();
28 }
29 
ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions * options)30 bool CheckExternal::ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions *options)
31 {
32     return options->inlining;
33 }
34 
run(llvm::Function & function,llvm::FunctionAnalysisManager &)35 llvm::PreservedAnalyses CheckExternal::run(llvm::Function &function,
36                                            llvm::FunctionAnalysisManager & /*analysis_manager*/)
37 {
38     bool changed = false;
39     llvm::SmallVector<llvm::CallInst *> remove;
40     for (auto &block : function) {
41         for (auto &instruction : block) {
42             auto *call = llvm::dyn_cast<llvm::CallInst>(&instruction);
43             if (call == nullptr) {
44                 continue;
45             }
46             auto callee = call->getCalledFunction();
47             if (callee == nullptr || callee->isIntrinsic()) {
48                 continue;
49             }
50             // Remove calls to KeepThis here since it's a convenient place:
51             // 1) It is a function pass
52             // 2) It is after DeadArgElim
53             // 3) It is before inlining
54             if (callee == ark::llvmbackend::builtins::KeepThis(function.getParent())) {
55                 remove.push_back(call);
56                 continue;
57             }
58             if (call->hasFnAttr(llvm::Attribute::NoInline) && !callee->isDeclaration() &&
59                 !call->hasFnAttr("keep-noinline") && !ark::llvmbackend::utils::HasCallsWithDeopt(*callee)) {
60                 changed = true;
61                 call->removeAttributeAtIndex(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoInline);
62             }
63         }
64     }
65     for (auto &inst : remove) {
66         changed = true;
67         inst->eraseFromParent();
68     }
69     return changed ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all();
70 }
71 
72 }  // namespace ark::llvmbackend::passes
73