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_ARK_GVN_H 17 #define LIBLLVMBACKEND_TRANSFORMS_PASSES_ARK_GVN_H 18 19 #include <llvm/IR/PassManager.h> 20 21 namespace ark::llvmbackend { 22 struct LLVMCompilerOptions; 23 } // namespace ark::llvmbackend 24 25 namespace llvm { 26 class DominatorTree; 27 } // namespace llvm 28 29 namespace ark::llvmbackend { 30 class LLVMArkInterface; 31 } // namespace ark::llvmbackend 32 33 namespace ark::llvmbackend::passes { 34 35 class ArkGVN : public llvm::PassInfoMixin<ArkGVN> { 36 public: 37 explicit ArkGVN(LLVMArkInterface *arkInterface = nullptr); 38 ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions * options)39 static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options) 40 { 41 return true; 42 } 43 static ArkGVN Create(LLVMArkInterface *arkInterface, const ark::llvmbackend::LLVMCompilerOptions *options); 44 45 // NOLINTNEXTLINE(readability-identifier-naming) 46 llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager); 47 48 private: 49 enum BuiltinType { 50 LOAD_CLASS, // 51 LOAD_AND_INIT_CLASS, // 52 LOAD_STRING, // 53 RESOLVE_VIRTUAL_METHOD, // 54 NONE, // 55 }; 56 57 struct BuiltinKey { 58 BuiltinType builtinTy = BuiltinType::NONE; 59 llvm::SmallVector<llvm::Value *, 2U> args; 60 // To store as a key in llvm::SmallDenseMap 61 bool isValid = true; 62 }; 63 64 struct MapInfo { 65 // NOLINTNEXTLINE(readability-identifier-naming) getEmptyKeyMapInfo66 static inline BuiltinKey getEmptyKey() 67 { 68 return BuiltinKey(); 69 } 70 71 // NOLINTNEXTLINE(readability-identifier-naming) getTombstoneKeyMapInfo72 static inline BuiltinKey getTombstoneKey() 73 { 74 auto key = BuiltinKey(); 75 key.isValid = false; 76 return key; 77 } 78 79 // NOLINTNEXTLINE(readability-identifier-naming) getHashValueMapInfo80 static unsigned getHashValue(const BuiltinKey &key) 81 { 82 return static_cast<unsigned>(llvm::hash_combine( 83 llvm::hash_value(key.builtinTy), llvm::hash_combine_range(key.args.begin(), key.args.end()))); 84 } 85 86 // NOLINTNEXTLINE(readability-identifier-naming) isEqualMapInfo87 static bool isEqual(const BuiltinKey &a, const BuiltinKey &b) 88 { 89 return a.builtinTy == b.builtinTy && a.args == b.args; 90 } 91 }; 92 93 using LocalTable = llvm::SmallDenseMap<BuiltinKey, llvm::Value *, 4U, MapInfo>; 94 using GvnBuiltins = llvm::SmallVector<llvm::Function *, BuiltinType::NONE>; 95 96 private: 97 bool RunOnFunction(const llvm::DominatorTree &tree, const GvnBuiltins &builtins); 98 bool RunOnBasicBlock(llvm::BasicBlock *block, const llvm::DominatorTree &tree, const GvnBuiltins &builtins); 99 100 BuiltinKey ParseBuiltin(const llvm::CallInst *callInst, const GvnBuiltins &builtins); 101 102 llvm::Value *FindDominantCall(const BuiltinKey &curBuiltin, llvm::BasicBlock *block, 103 const llvm::DominatorTree &tree); 104 105 private: 106 LLVMArkInterface *arkInterface_; 107 std::vector<llvm::BasicBlock *> workStack_; 108 llvm::DenseMap<llvm::BasicBlock *, LocalTable> bbTables_; 109 110 public: 111 static constexpr llvm::StringRef ARG_NAME = "ark-gvn"; 112 }; 113 114 } // namespace ark::llvmbackend::passes 115 #endif // LIBLLVMBACKEND_TRANSFORMS_PASSES_ARK_GVN_H 116