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 #ifndef LIBLLVMBACKEND_TRANSFORMS_PASSES_GC_UTILS_H
17 #define LIBLLVMBACKEND_TRANSFORMS_PASSES_GC_UTILS_H
18
19 #include "llvm_ark_interface.h"
20
21 #include <llvm/ADT/SmallSet.h>
22 #include <llvm/IR/Function.h>
23 #include <llvm/IR/Type.h>
24 #include <llvm/IR/Instructions.h>
25
26 namespace ark::llvmbackend::gc_utils {
27
28 enum class DerivedStatus { UNKNOWN, DERIVED, NOT_DERIVED };
29 bool IsDerived(llvm::Value *val);
30 DerivedStatus IsPHIDerived(llvm::PHINode *phi, llvm::SmallSet<llvm::Value *, 8U> *visited);
31 DerivedStatus IsDerivedImpl(llvm::Value *val, llvm::SmallSet<llvm::Value *, 8U> *visited = nullptr);
32 bool HasBeenGcRef(const llvm::Value *val, bool any = true);
33 void MarkAsNonMovable(llvm::Instruction *instruction);
34 bool IsNonMovable(const llvm::Value *value);
35
IsGcRefType(llvm::Type * type)36 inline bool IsGcRefType(llvm::Type *type)
37 {
38 return type->isPointerTy() && type->getPointerAddressSpace() == ark::llvmbackend::LLVMArkInterface::GC_ADDR_SPACE;
39 }
40
IsGcFunction(const llvm::Function & function)41 inline bool IsGcFunction(const llvm::Function &function)
42 {
43 return function.hasGC() && function.getGC() == ark::llvmbackend::LLVMArkInterface::GC_STRATEGY;
44 }
45
IsFunctionSupplemental(const llvm::Function & function)46 inline bool IsFunctionSupplemental(const llvm::Function &function)
47 {
48 if (function.isDeclaration()) {
49 return true;
50 }
51 if (function.getName().equals(ark::llvmbackend::LLVMArkInterface::GC_SAFEPOINT_POLL_NAME)) {
52 return true;
53 }
54 return false;
55 }
56
57 /// Returns true if a value is an integer comparison with 0.
IsNullCmp(const llvm::Value * val)58 inline bool IsNullCmp(const llvm::Value *val)
59 {
60 auto cmp = llvm::dyn_cast<llvm::ICmpInst>(val);
61 if (cmp == nullptr) {
62 return false;
63 }
64
65 auto op0 = llvm::dyn_cast<llvm::Constant>(cmp->getOperand(0));
66 auto op1 = llvm::dyn_cast<llvm::Constant>(cmp->getOperand(1));
67 return (op0 != nullptr && op0->isNullValue()) || (op1 != nullptr && op1->isNullValue());
68 }
69
70 /// Returns true if a value is an instruction that allowed to use with escaped value.
IsAllowedEscapedUser(const llvm::Value * val)71 inline bool IsAllowedEscapedUser(const llvm::Value *val)
72 {
73 return llvm::isa<llvm::CastInst>(val) || IsNullCmp(val);
74 }
75
76 } // namespace ark::llvmbackend::gc_utils
77
78 #endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_GC_UTILS_H
79