• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_INTRUSION_H
17 #define LIBLLVMBACKEND_TRANSFORMS_PASSES_GC_INTRUSION_H
18 
19 #include <llvm/ADT/SetVector.h>
20 #include <llvm/IR/IRBuilder.h>
21 #include <llvm/IR/PassManager.h>
22 
23 namespace ark::llvmbackend {
24 struct LLVMCompilerOptions;
25 }  // namespace ark::llvmbackend
26 
27 namespace ark::llvmbackend::passes {
28 
29 class GcRefLiveness;
30 
31 class GcIntrusion : public llvm::PassInfoMixin<GcIntrusion> {
32 public:
ShouldInsert(const ark::llvmbackend::LLVMCompilerOptions * options)33     static bool ShouldInsert([[maybe_unused]] const ark::llvmbackend::LLVMCompilerOptions *options)
34     {
35         return true;
36     }
37 
38     // NOLINTNEXTLINE(readability-identifier-naming)
39     llvm::PreservedAnalyses run(llvm::Function &function, llvm::FunctionAnalysisManager &analysisManager);
40 
41 private:
42     using SSAVarRelocs = llvm::DenseMap<llvm::Value *, llvm::DenseMap<llvm::BasicBlock *, llvm::Value *>>;
43     using InstructionOrderMap = llvm::DenseMap<llvm::Value *, uint64_t>;
44     using SortedUses = llvm::DenseMap<llvm::Value *, std::list<llvm::Use *>>;
45     using RPOMap = llvm::DenseMap<llvm::BasicBlock *, uint32_t>;
46     struct GcIntrusionContext {
47         SSAVarRelocs relocs;
48         InstructionOrderMap orderMap;
49         SortedUses sortedUses;
50         RPOMap rpoMap;
51     };
52 
53     void RewriteWithGcInBlock(llvm::BasicBlock *block, GcRefLiveness *liveness, llvm::SetVector<llvm::Value *> *alive,
54                               llvm::DenseSet<llvm::BasicBlock *> *visited, GcIntrusionContext *gcContext);
55 
56     static bool ComesBefore(llvm::Value *a, llvm::Value *b, InstructionOrderMap *orderMap);
57 
58     void HoistForRelocation(llvm::Function *function);
59 
60     bool MoveComparisons(llvm::Function *function);
61 
62     void FixupEscapedUsages(llvm::Instruction *inst, const llvm::SmallVector<llvm::Instruction *> &casts);
63 
64     llvm::Value *CreateBackwardCasts(llvm::IRBuilder<> *builder, llvm::Value *from,
65                                      const llvm::SmallVector<llvm::Instruction *> &casts);
66 
67     uint32_t GetStatepointId(const llvm::Instruction &inst);
68 
69     void ReplaceWithPhi(llvm::Value *var, llvm::BasicBlock *block, GcIntrusionContext *gcContext);
70 
71     void PropagateRelocs(GcRefLiveness *liveness, llvm::DenseSet<llvm::BasicBlock *> *visited, llvm::BasicBlock *block,
72                          GcIntrusionContext *gcContext);
73 
74     void CopySinglePredRelocs(GcRefLiveness *liveness, llvm::BasicBlock *block, GcIntrusionContext *gcContext);
75 
76     llvm::Value *GetUniqueLiveOut(SSAVarRelocs *relocs, llvm::BasicBlock *block, llvm::Value *var) const;
77 
78     void ReplaceWithRelocated(llvm::CallInst *call, llvm::CallInst *gcCall, llvm::Value *inst, llvm::Value *relocated,
79                               GcIntrusionContext *gcContext);
80 
81     void RewriteWithGc(llvm::CallInst *call, GcRefLiveness *liveness, llvm::SetVector<llvm::Value *> *refs,
82                        GcIntrusionContext *gcContext);
83 
84     std::vector<llvm::Value *> GetDeoptsFromInlineInfo(llvm::IRBuilder<> &builder, llvm::CallInst *call);
85 
86     void CreateSortedUseList(llvm::BasicBlock *block, llvm::Value *from, GcIntrusionContext *gcContext);
87 
88     void ReplaceDominatedUses(llvm::Value *from, llvm::Value *to, llvm::BasicBlock *block,
89                               GcIntrusionContext *gcContext);
90 
91     void UpdatePhiInputs(llvm::BasicBlock *block, SSAVarRelocs *relocs);
92 
93 public:
94     static constexpr llvm::StringRef ARG_NAME = "gc-intrusion";
95 };
96 
97 }  // namespace ark::llvmbackend::passes
98 
99 #endif  //  LIBLLVMBACKEND_TRANSFORMS_PASSES_GC_INTRUSION_H
100