1b1994897Sopenharmony_ci/**
2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License.
5b1994897Sopenharmony_ci * You may obtain a copy of the License at
6b1994897Sopenharmony_ci *
7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8b1994897Sopenharmony_ci *
9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and
13b1994897Sopenharmony_ci * limitations under the License.
14b1994897Sopenharmony_ci */
15b1994897Sopenharmony_ci
16b1994897Sopenharmony_ci#ifndef COMPILER_OPTIMIZER_IR_GRAPH_H
17b1994897Sopenharmony_ci#define COMPILER_OPTIMIZER_IR_GRAPH_H
18b1994897Sopenharmony_ci
19b1994897Sopenharmony_ci#include <algorithm>
20b1994897Sopenharmony_ci#include <optional>
21b1994897Sopenharmony_ci#include "compiler_events_gen.h"
22b1994897Sopenharmony_ci#include "inst.h"
23b1994897Sopenharmony_ci#include "marker.h"
24b1994897Sopenharmony_ci#include "optimizer/pass_manager.h"
25b1994897Sopenharmony_ci#include "utils/arena_containers.h"
26b1994897Sopenharmony_ci
27b1994897Sopenharmony_cinamespace panda {
28b1994897Sopenharmony_ciclass Method;
29b1994897Sopenharmony_ciclass CodeAllocator;
30b1994897Sopenharmony_ci}  // namespace panda
31b1994897Sopenharmony_ci
32b1994897Sopenharmony_cinamespace panda::compiler {
33b1994897Sopenharmony_ciclass BasicBlock;
34b1994897Sopenharmony_ciclass Graph;
35b1994897Sopenharmony_ciclass RuntimeInfo;
36b1994897Sopenharmony_ciclass PassManager;
37b1994897Sopenharmony_ciclass LivenessAnalyzer;
38b1994897Sopenharmony_ciclass DominatorsTree;
39b1994897Sopenharmony_ciclass Rpo;
40b1994897Sopenharmony_ciclass Loop;
41b1994897Sopenharmony_ciclass ParameterInfo;
42b1994897Sopenharmony_ci
43b1994897Sopenharmony_ci/**
44b1994897Sopenharmony_ci * Specifies graph compilation mode.
45b1994897Sopenharmony_ci */
46b1994897Sopenharmony_ciclass GraphMode {
47b1994897Sopenharmony_cipublic:
48b1994897Sopenharmony_ci    explicit GraphMode(uint32_t value) : value_(value) {}
49b1994897Sopenharmony_ci
50b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
51b1994897Sopenharmony_ci#define DECLARE_GRAPH_MODE(name)                    \
52b1994897Sopenharmony_ci    static GraphMode name(bool set = true)          \
53b1994897Sopenharmony_ci    {                                               \
54b1994897Sopenharmony_ci        return GraphMode(Flag##name ::Encode(set)); \
55b1994897Sopenharmony_ci    }                                               \
56b1994897Sopenharmony_ci    void Set##name(bool v)                          \
57b1994897Sopenharmony_ci    {                                               \
58b1994897Sopenharmony_ci        Flag##name ::Set(v, &value_);               \
59b1994897Sopenharmony_ci    }                                               \
60b1994897Sopenharmony_ci    bool Is##name() const                           \
61b1994897Sopenharmony_ci    {                                               \
62b1994897Sopenharmony_ci        return Flag##name ::Get(value_);            \
63b1994897Sopenharmony_ci    }
64b1994897Sopenharmony_ci
65b1994897Sopenharmony_ci    DECLARE_GRAPH_MODE(Osr);
66b1994897Sopenharmony_ci    // The graph is used in BytecodeOptimizer mode
67b1994897Sopenharmony_ci    DECLARE_GRAPH_MODE(BytecodeOpt);
68b1994897Sopenharmony_ci    // The method from dynamic language
69b1994897Sopenharmony_ci    DECLARE_GRAPH_MODE(DynamicMethod);
70b1994897Sopenharmony_ci    // Graph will be compiled with native calling convention
71b1994897Sopenharmony_ci    DECLARE_GRAPH_MODE(Native);
72b1994897Sopenharmony_ci    // FastPath from compiled code to runtime
73b1994897Sopenharmony_ci    DECLARE_GRAPH_MODE(FastPath);
74b1994897Sopenharmony_ci    // Boundary frame is used for compiled code
75b1994897Sopenharmony_ci    DECLARE_GRAPH_MODE(Boundary);
76b1994897Sopenharmony_ci    // Graph will be compiled for calling inside interpreter
77b1994897Sopenharmony_ci    DECLARE_GRAPH_MODE(Interpreter);
78b1994897Sopenharmony_ci    // Graph will be compiled for interpreter main loop
79b1994897Sopenharmony_ci    DECLARE_GRAPH_MODE(InterpreterEntry);
80b1994897Sopenharmony_ci
81b1994897Sopenharmony_ci#undef DECLARE_GRAPH_MODE
82b1994897Sopenharmony_ci
83b1994897Sopenharmony_ci    bool SupportManagedCode() const
84b1994897Sopenharmony_ci    {
85b1994897Sopenharmony_ci        return !IsNative() && !IsFastPath() && !IsBoundary() && !IsInterpreter() && !IsInterpreterEntry();
86b1994897Sopenharmony_ci    }
87b1994897Sopenharmony_ci
88b1994897Sopenharmony_ci    void Dump(std::ostream &stm);
89b1994897Sopenharmony_ci
90b1994897Sopenharmony_ciprivate:
91b1994897Sopenharmony_ci    using FlagOsr = BitField<bool, 0, 1>;
92b1994897Sopenharmony_ci    using FlagBytecodeOpt = FlagOsr::NextFlag;
93b1994897Sopenharmony_ci    using FlagDynamicMethod = FlagBytecodeOpt::NextFlag;
94b1994897Sopenharmony_ci    using FlagNative = FlagDynamicMethod::NextFlag;
95b1994897Sopenharmony_ci    using FlagFastPath = FlagNative::NextFlag;
96b1994897Sopenharmony_ci    using FlagBoundary = FlagFastPath::NextFlag;
97b1994897Sopenharmony_ci    using FlagInterpreter = FlagBoundary::NextFlag;
98b1994897Sopenharmony_ci    using FlagInterpreterEntry = FlagInterpreter::NextFlag;
99b1994897Sopenharmony_ci
100b1994897Sopenharmony_ci    uint32_t value_ {0};
101b1994897Sopenharmony_ci
102b1994897Sopenharmony_ci    friend GraphMode operator|(GraphMode a, GraphMode b);
103b1994897Sopenharmony_ci};
104b1994897Sopenharmony_ci
105b1994897Sopenharmony_ciinline GraphMode operator|(GraphMode a, GraphMode b)
106b1994897Sopenharmony_ci{
107b1994897Sopenharmony_ci    return GraphMode(a.value_ | b.value_);
108b1994897Sopenharmony_ci}
109b1994897Sopenharmony_ci
110b1994897Sopenharmony_ciusing EncodeDataType = Span<uint8_t>;
111b1994897Sopenharmony_ci
112b1994897Sopenharmony_ciclass Graph final : public MarkerMgr {
113b1994897Sopenharmony_cipublic:
114b1994897Sopenharmony_ci    explicit Graph(ArenaAllocator *allocator, ArenaAllocator *local_allocator, Arch arch)
115b1994897Sopenharmony_ci        : Graph(allocator, local_allocator, arch, false)
116b1994897Sopenharmony_ci    {
117b1994897Sopenharmony_ci    }
118b1994897Sopenharmony_ci
119b1994897Sopenharmony_ci    Graph(ArenaAllocator *allocator, ArenaAllocator *local_allocator, Arch arch, bool osr_mode)
120b1994897Sopenharmony_ci        : Graph(allocator, local_allocator, arch, nullptr, GetDefaultRuntime(), osr_mode)
121b1994897Sopenharmony_ci    {
122b1994897Sopenharmony_ci    }
123b1994897Sopenharmony_ci
124b1994897Sopenharmony_ci    Graph(ArenaAllocator *allocator, ArenaAllocator *local_allocator, Arch arch, bool dynamic_method, bool bytecode_opt)
125b1994897Sopenharmony_ci        : Graph(allocator, local_allocator, arch, nullptr, GetDefaultRuntime(), false, nullptr, dynamic_method,
126b1994897Sopenharmony_ci                bytecode_opt)
127b1994897Sopenharmony_ci    {
128b1994897Sopenharmony_ci    }
129b1994897Sopenharmony_ci
130b1994897Sopenharmony_ci    Graph(ArenaAllocator *allocator, ArenaAllocator *local_allocator, Arch arch, RuntimeInterface::MethodPtr method,
131b1994897Sopenharmony_ci          RuntimeInterface *runtime, bool osr_mode)
132b1994897Sopenharmony_ci        : Graph(allocator, local_allocator, arch, method, runtime, osr_mode, nullptr)
133b1994897Sopenharmony_ci    {
134b1994897Sopenharmony_ci    }
135b1994897Sopenharmony_ci
136b1994897Sopenharmony_ci    Graph(ArenaAllocator *allocator, ArenaAllocator *local_allocator, Arch arch, RuntimeInterface::MethodPtr method,
137b1994897Sopenharmony_ci          RuntimeInterface *runtime, bool osr_mode, Graph *parent, bool dynamic_method = false,
138b1994897Sopenharmony_ci          bool bytecode_opt = false)
139b1994897Sopenharmony_ci        : Graph(allocator, local_allocator, arch, method, runtime, parent,
140b1994897Sopenharmony_ci                GraphMode::Osr(osr_mode) | GraphMode::BytecodeOpt(bytecode_opt) |
141b1994897Sopenharmony_ci                    GraphMode::DynamicMethod(dynamic_method))
142b1994897Sopenharmony_ci    {
143b1994897Sopenharmony_ci    }
144b1994897Sopenharmony_ci
145b1994897Sopenharmony_ci    Graph(ArenaAllocator *allocator, ArenaAllocator *local_allocator, Arch arch, RuntimeInterface::MethodPtr method,
146b1994897Sopenharmony_ci          RuntimeInterface *runtime, Graph *parent, GraphMode mode)
147b1994897Sopenharmony_ci        : ALLOCATOR(allocator),
148b1994897Sopenharmony_ci          LOCAL_ALLOCATOR(local_allocator),
149b1994897Sopenharmony_ci          arch_(arch),
150b1994897Sopenharmony_ci          vector_bb_(allocator->Adapter()),
151b1994897Sopenharmony_ci          throwable_insts_(allocator->Adapter()),
152b1994897Sopenharmony_ci          runtime_(runtime),
153b1994897Sopenharmony_ci          method_(method),
154b1994897Sopenharmony_ci          pass_manager_(this, parent != nullptr ? parent->GetPassManager() : nullptr),
155b1994897Sopenharmony_ci          event_writer_(runtime->GetClassNameFromMethod(method), runtime->GetMethodName(method)),
156b1994897Sopenharmony_ci          mode_(mode),
157b1994897Sopenharmony_ci          single_implementation_list_(allocator->Adapter()),
158b1994897Sopenharmony_ci          try_begin_blocks_(allocator->Adapter()),
159b1994897Sopenharmony_ci          spilled_constants_(allocator->Adapter()),
160b1994897Sopenharmony_ci          parent_graph_(parent)
161b1994897Sopenharmony_ci    {
162b1994897Sopenharmony_ci        SetNeedCleanup(true);
163b1994897Sopenharmony_ci    }
164b1994897Sopenharmony_ci
165b1994897Sopenharmony_ci    ~Graph() override;
166b1994897Sopenharmony_ci
167b1994897Sopenharmony_ci    Graph *CreateChildGraph(RuntimeInterface::MethodPtr method)
168b1994897Sopenharmony_ci    {
169b1994897Sopenharmony_ci        auto graph = GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), GetArch(), method, GetRuntime(),
170b1994897Sopenharmony_ci                                                this, mode_);
171b1994897Sopenharmony_ci        return graph;
172b1994897Sopenharmony_ci    }
173b1994897Sopenharmony_ci
174b1994897Sopenharmony_ci    /// Get default runtime interface object
175b1994897Sopenharmony_ci    static RuntimeInterface *GetDefaultRuntime()
176b1994897Sopenharmony_ci    {
177b1994897Sopenharmony_ci        static RuntimeInterface runtime_interface;
178b1994897Sopenharmony_ci        return &runtime_interface;
179b1994897Sopenharmony_ci    }
180b1994897Sopenharmony_ci
181b1994897Sopenharmony_ci    Arch GetArch() const
182b1994897Sopenharmony_ci    {
183b1994897Sopenharmony_ci        return arch_;
184b1994897Sopenharmony_ci    }
185b1994897Sopenharmony_ci
186b1994897Sopenharmony_ci    void AddBlock(BasicBlock *block);
187b1994897Sopenharmony_ci#ifndef NDEBUG
188b1994897Sopenharmony_ci    void AddBlock(BasicBlock *block, uint32_t id);
189b1994897Sopenharmony_ci#endif
190b1994897Sopenharmony_ci    void DisconnectBlock(BasicBlock *block, bool remove_last_inst = true, bool fix_dom_tree = true);
191b1994897Sopenharmony_ci    void DisconnectBlockRec(BasicBlock *block, bool remove_last_inst = true, bool fix_dom_tree = true);
192b1994897Sopenharmony_ci
193b1994897Sopenharmony_ci    void EraseBlock(BasicBlock *block);
194b1994897Sopenharmony_ci    void RestoreBlock(BasicBlock *block);
195b1994897Sopenharmony_ci    // Remove empty block. Block must have one successor and no Phis.
196b1994897Sopenharmony_ci    void RemoveEmptyBlock(BasicBlock *block);
197b1994897Sopenharmony_ci
198b1994897Sopenharmony_ci    // Remove empty block. Block may have Phis and can't be a loop pre-header.
199b1994897Sopenharmony_ci    void RemoveEmptyBlockWithPhis(BasicBlock *block, bool irr_loop = false);
200b1994897Sopenharmony_ci
201b1994897Sopenharmony_ci    // Remove block predecessors.
202b1994897Sopenharmony_ci    void RemovePredecessors(BasicBlock *block, bool remove_last_inst = true);
203b1994897Sopenharmony_ci
204b1994897Sopenharmony_ci    // Remove block successors.
205b1994897Sopenharmony_ci    void RemoveSuccessors(BasicBlock *block);
206b1994897Sopenharmony_ci
207b1994897Sopenharmony_ci    // Remove unreachable blocks.
208b1994897Sopenharmony_ci    void RemoveUnreachableBlocks();
209b1994897Sopenharmony_ci
210b1994897Sopenharmony_ci    // get end block
211b1994897Sopenharmony_ci    BasicBlock *GetEndBlock()
212b1994897Sopenharmony_ci    {
213b1994897Sopenharmony_ci        return end_block_;
214b1994897Sopenharmony_ci    }
215b1994897Sopenharmony_ci
216b1994897Sopenharmony_ci    BasicBlock *GetEndBlock() const
217b1994897Sopenharmony_ci    {
218b1994897Sopenharmony_ci        return end_block_;
219b1994897Sopenharmony_ci    }
220b1994897Sopenharmony_ci    // set end block
221b1994897Sopenharmony_ci    void SetEndBlock(BasicBlock *end_block)
222b1994897Sopenharmony_ci    {
223b1994897Sopenharmony_ci        end_block_ = end_block;
224b1994897Sopenharmony_ci    }
225b1994897Sopenharmony_ci    bool HasEndBlock()
226b1994897Sopenharmony_ci    {
227b1994897Sopenharmony_ci        return end_block_ != nullptr;
228b1994897Sopenharmony_ci    }
229b1994897Sopenharmony_ci    // get start block
230b1994897Sopenharmony_ci    BasicBlock *GetStartBlock()
231b1994897Sopenharmony_ci    {
232b1994897Sopenharmony_ci        return start_block_;
233b1994897Sopenharmony_ci    }
234b1994897Sopenharmony_ci    BasicBlock *GetStartBlock() const
235b1994897Sopenharmony_ci    {
236b1994897Sopenharmony_ci        return start_block_;
237b1994897Sopenharmony_ci    }
238b1994897Sopenharmony_ci    // set start block
239b1994897Sopenharmony_ci    void SetStartBlock(BasicBlock *start_block)
240b1994897Sopenharmony_ci    {
241b1994897Sopenharmony_ci        start_block_ = start_block;
242b1994897Sopenharmony_ci    }
243b1994897Sopenharmony_ci    // get vector_bb_
244b1994897Sopenharmony_ci    const ArenaVector<BasicBlock *> &GetVectorBlocks() const
245b1994897Sopenharmony_ci    {
246b1994897Sopenharmony_ci        return vector_bb_;
247b1994897Sopenharmony_ci    }
248b1994897Sopenharmony_ci
249b1994897Sopenharmony_ci    size_t GetAliveBlocksCount() const
250b1994897Sopenharmony_ci    {
251b1994897Sopenharmony_ci        return std::count_if(vector_bb_.begin(), vector_bb_.end(), [](BasicBlock *block) { return block != nullptr; });
252b1994897Sopenharmony_ci    }
253b1994897Sopenharmony_ci
254b1994897Sopenharmony_ci    PassManager *GetPassManager()
255b1994897Sopenharmony_ci    {
256b1994897Sopenharmony_ci        return &pass_manager_;
257b1994897Sopenharmony_ci    }
258b1994897Sopenharmony_ci    const PassManager *GetPassManager() const
259b1994897Sopenharmony_ci    {
260b1994897Sopenharmony_ci        return &pass_manager_;
261b1994897Sopenharmony_ci    }
262b1994897Sopenharmony_ci
263b1994897Sopenharmony_ci    const ArenaVector<BasicBlock *> &GetBlocksRPO() const;
264b1994897Sopenharmony_ci
265b1994897Sopenharmony_ci    const ArenaVector<BasicBlock *> &GetBlocksLinearOrder() const;
266b1994897Sopenharmony_ci
267b1994897Sopenharmony_ci    template <class Callback>
268b1994897Sopenharmony_ci    void VisitAllInstructions(Callback callback);
269b1994897Sopenharmony_ci
270b1994897Sopenharmony_ci    /// Main allocator for graph, all related to Graph data should be allocated via this allocator.
271b1994897Sopenharmony_ci    ArenaAllocator *GetAllocator() const
272b1994897Sopenharmony_ci    {
273b1994897Sopenharmony_ci        return ALLOCATOR;
274b1994897Sopenharmony_ci    }
275b1994897Sopenharmony_ci    /// Allocator for temproray usage, when allocated data is no longer needed after optimization/analysis finished.
276b1994897Sopenharmony_ci    ArenaAllocator *GetLocalAllocator() const
277b1994897Sopenharmony_ci    {
278b1994897Sopenharmony_ci        return LOCAL_ALLOCATOR;
279b1994897Sopenharmony_ci    }
280b1994897Sopenharmony_ci    bool IsDFConstruct() const
281b1994897Sopenharmony_ci    {
282b1994897Sopenharmony_ci        return FlagDFConstruct::Get(bit_fields_);
283b1994897Sopenharmony_ci    }
284b1994897Sopenharmony_ci    void SetDFConstruct()
285b1994897Sopenharmony_ci    {
286b1994897Sopenharmony_ci        FlagDFConstruct::Set(true, &bit_fields_);
287b1994897Sopenharmony_ci    }
288b1994897Sopenharmony_ci
289b1994897Sopenharmony_ci    bool IsAotMode() const
290b1994897Sopenharmony_ci    {
291b1994897Sopenharmony_ci        return false;
292b1994897Sopenharmony_ci    }
293b1994897Sopenharmony_ci
294b1994897Sopenharmony_ci    bool IsOfflineCompilationMode() const
295b1994897Sopenharmony_ci    {
296b1994897Sopenharmony_ci        return IsAotMode() || GetMode().IsInterpreter();
297b1994897Sopenharmony_ci    }
298b1994897Sopenharmony_ci
299b1994897Sopenharmony_ci    bool IsDefaultLocationsInit() const
300b1994897Sopenharmony_ci    {
301b1994897Sopenharmony_ci        return FlagDefaultLocationsInit::Get(bit_fields_);
302b1994897Sopenharmony_ci    }
303b1994897Sopenharmony_ci    void SetDefaultLocationsInit()
304b1994897Sopenharmony_ci    {
305b1994897Sopenharmony_ci        FlagDefaultLocationsInit::Set(true, &bit_fields_);
306b1994897Sopenharmony_ci    }
307b1994897Sopenharmony_ci#ifndef NDEBUG
308b1994897Sopenharmony_ci    bool IsRegAllocApplied() const
309b1994897Sopenharmony_ci    {
310b1994897Sopenharmony_ci        return FlagRegallocApplied::Get(bit_fields_);
311b1994897Sopenharmony_ci    }
312b1994897Sopenharmony_ci    void SetRegAllocApplied()
313b1994897Sopenharmony_ci    {
314b1994897Sopenharmony_ci        FlagRegallocApplied::Set(true, &bit_fields_);
315b1994897Sopenharmony_ci    }
316b1994897Sopenharmony_ci    bool IsRegAccAllocApplied() const
317b1994897Sopenharmony_ci    {
318b1994897Sopenharmony_ci        return FlagRegaccallocApplied::Get(bit_fields_);
319b1994897Sopenharmony_ci    }
320b1994897Sopenharmony_ci    void SetRegAccAllocApplied()
321b1994897Sopenharmony_ci    {
322b1994897Sopenharmony_ci        FlagRegaccallocApplied::Set(true, &bit_fields_);
323b1994897Sopenharmony_ci    }
324b1994897Sopenharmony_ci    bool IsInliningComplete() const
325b1994897Sopenharmony_ci    {
326b1994897Sopenharmony_ci        return FlagInliningComplete::Get(bit_fields_);
327b1994897Sopenharmony_ci    }
328b1994897Sopenharmony_ci    void SetInliningComplete()
329b1994897Sopenharmony_ci    {
330b1994897Sopenharmony_ci        FlagInliningComplete::Set(true, &bit_fields_);
331b1994897Sopenharmony_ci    }
332b1994897Sopenharmony_ci    bool IsSchedulerComplete() const
333b1994897Sopenharmony_ci    {
334b1994897Sopenharmony_ci        return FlagSchedulerComplete::Get(bit_fields_);
335b1994897Sopenharmony_ci    }
336b1994897Sopenharmony_ci    void SetSchedulerComplete()
337b1994897Sopenharmony_ci    {
338b1994897Sopenharmony_ci        FlagSchedulerComplete::Set(true, &bit_fields_);
339b1994897Sopenharmony_ci    }
340b1994897Sopenharmony_ci    bool IsLowLevelInstructionsEnabled() const
341b1994897Sopenharmony_ci    {
342b1994897Sopenharmony_ci        return FlagLowLevelInstnsEnabled::Get(bit_fields_);
343b1994897Sopenharmony_ci    }
344b1994897Sopenharmony_ci    void SetLowLevelInstructionsEnabled()
345b1994897Sopenharmony_ci    {
346b1994897Sopenharmony_ci        FlagLowLevelInstnsEnabled::Set(true, &bit_fields_);
347b1994897Sopenharmony_ci    }
348b1994897Sopenharmony_ci#else
349b1994897Sopenharmony_ci    bool IsRegAllocApplied() const
350b1994897Sopenharmony_ci    {
351b1994897Sopenharmony_ci        return false;
352b1994897Sopenharmony_ci    }
353b1994897Sopenharmony_ci#endif  // NDEBUG
354b1994897Sopenharmony_ci
355b1994897Sopenharmony_ci    void SetData(EncodeDataType data)
356b1994897Sopenharmony_ci    {
357b1994897Sopenharmony_ci        data_ = data;
358b1994897Sopenharmony_ci    }
359b1994897Sopenharmony_ci
360b1994897Sopenharmony_ci    EncodeDataType GetData() const
361b1994897Sopenharmony_ci    {
362b1994897Sopenharmony_ci        return data_;
363b1994897Sopenharmony_ci    }
364b1994897Sopenharmony_ci
365b1994897Sopenharmony_ci    EncodeDataType GetData()
366b1994897Sopenharmony_ci    {
367b1994897Sopenharmony_ci        return data_;
368b1994897Sopenharmony_ci    }
369b1994897Sopenharmony_ci
370b1994897Sopenharmony_ci    void SetCodeInfo(Span<uint8_t> data)
371b1994897Sopenharmony_ci    {
372b1994897Sopenharmony_ci        code_info_data_ = data.SubSpan<const uint8_t>(0, data.size());
373b1994897Sopenharmony_ci    }
374b1994897Sopenharmony_ci
375b1994897Sopenharmony_ci    Span<const uint8_t> GetCodeInfoData() const
376b1994897Sopenharmony_ci    {
377b1994897Sopenharmony_ci        return code_info_data_;
378b1994897Sopenharmony_ci    }
379b1994897Sopenharmony_ci
380b1994897Sopenharmony_ci    void DumpUsedRegs(std::ostream &out = std::cerr, const char *prefix = nullptr) const
381b1994897Sopenharmony_ci    {
382b1994897Sopenharmony_ci        if (prefix != nullptr) {
383b1994897Sopenharmony_ci            out << prefix;
384b1994897Sopenharmony_ci        }
385b1994897Sopenharmony_ci        out << "'\n  used scalar regs: ";
386b1994897Sopenharmony_ci        if (used_regs_ != nullptr) {
387b1994897Sopenharmony_ci            for (unsigned i = 0; i < used_regs_->size(); ++i) {
388b1994897Sopenharmony_ci                if (used_regs_->at(i)) {
389b1994897Sopenharmony_ci                    out << i << " ";
390b1994897Sopenharmony_ci                }
391b1994897Sopenharmony_ci            }
392b1994897Sopenharmony_ci        }
393b1994897Sopenharmony_ci        out << "\n  used float  regs: ";
394b1994897Sopenharmony_ci        if (used_regs_ != nullptr) {
395b1994897Sopenharmony_ci            for (unsigned i = 0; i < used_vregs_->size(); ++i) {
396b1994897Sopenharmony_ci                if (used_vregs_->at(i)) {
397b1994897Sopenharmony_ci                    out << i << " ";
398b1994897Sopenharmony_ci                }
399b1994897Sopenharmony_ci            }
400b1994897Sopenharmony_ci        }
401b1994897Sopenharmony_ci        out << std::endl;
402b1994897Sopenharmony_ci    }
403b1994897Sopenharmony_ci
404b1994897Sopenharmony_ci    // Get registers mask which used in graph
405b1994897Sopenharmony_ci    template <DataType::Type reg_type>
406b1994897Sopenharmony_ci    ArenaVector<bool> *GetUsedRegs() const
407b1994897Sopenharmony_ci    {
408b1994897Sopenharmony_ci        // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
409b1994897Sopenharmony_ci        if constexpr (reg_type == DataType::INT64) {
410b1994897Sopenharmony_ci            return used_regs_;
411b1994897Sopenharmony_ci        }
412b1994897Sopenharmony_ci        // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
413b1994897Sopenharmony_ci        if constexpr (reg_type == DataType::FLOAT64) {
414b1994897Sopenharmony_ci            return used_vregs_;
415b1994897Sopenharmony_ci        }
416b1994897Sopenharmony_ci        UNREACHABLE();
417b1994897Sopenharmony_ci        return nullptr;
418b1994897Sopenharmony_ci    }
419b1994897Sopenharmony_ci
420b1994897Sopenharmony_ci    void SetRegUsage(Register reg, DataType::Type type)
421b1994897Sopenharmony_ci    {
422b1994897Sopenharmony_ci        ASSERT(reg != INVALID_REG);
423b1994897Sopenharmony_ci        if (DataType::IsFloatType(type)) {
424b1994897Sopenharmony_ci            SetUsedReg<DataType::FLOAT64>(reg);
425b1994897Sopenharmony_ci        } else {
426b1994897Sopenharmony_ci            SetUsedReg<DataType::INT64>(reg);
427b1994897Sopenharmony_ci        }
428b1994897Sopenharmony_ci    }
429b1994897Sopenharmony_ci
430b1994897Sopenharmony_ci    template <DataType::Type reg_type>
431b1994897Sopenharmony_ci    void SetUsedReg(Register reg)
432b1994897Sopenharmony_ci    {
433b1994897Sopenharmony_ci        ArenaVector<bool> *graph_regs = nullptr;
434b1994897Sopenharmony_ci        // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
435b1994897Sopenharmony_ci        if constexpr (reg_type == DataType::INT64) {
436b1994897Sopenharmony_ci            graph_regs = used_regs_;
437b1994897Sopenharmony_ci            // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation)
438b1994897Sopenharmony_ci        } else if constexpr (reg_type == DataType::FLOAT64) {
439b1994897Sopenharmony_ci            graph_regs = used_vregs_;
440b1994897Sopenharmony_ci        } else {
441b1994897Sopenharmony_ci            UNREACHABLE();
442b1994897Sopenharmony_ci        }
443b1994897Sopenharmony_ci        CHECK_NOT_NULL(graph_regs);
444b1994897Sopenharmony_ci        ASSERT(reg < graph_regs->size());
445b1994897Sopenharmony_ci        (*graph_regs)[reg] = true;
446b1994897Sopenharmony_ci    }
447b1994897Sopenharmony_ci
448b1994897Sopenharmony_ci    template <DataType::Type reg_type>
449b1994897Sopenharmony_ci    void InitUsedRegs(const ArenaVector<bool> *used_regs)
450b1994897Sopenharmony_ci    {
451b1994897Sopenharmony_ci        if (used_regs == nullptr) {
452b1994897Sopenharmony_ci            return;
453b1994897Sopenharmony_ci        }
454b1994897Sopenharmony_ci        ArenaVector<bool> *graph_regs = nullptr;
455b1994897Sopenharmony_ci        // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
456b1994897Sopenharmony_ci        if constexpr (reg_type == DataType::INT64) {
457b1994897Sopenharmony_ci            used_regs_ = GetAllocator()->New<ArenaVector<bool>>(GetAllocator()->Adapter());
458b1994897Sopenharmony_ci            graph_regs = used_regs_;
459b1994897Sopenharmony_ci            // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation)
460b1994897Sopenharmony_ci        } else if constexpr (reg_type == DataType::FLOAT64) {
461b1994897Sopenharmony_ci            used_vregs_ = GetAllocator()->New<ArenaVector<bool>>(GetAllocator()->Adapter());
462b1994897Sopenharmony_ci            graph_regs = used_vregs_;
463b1994897Sopenharmony_ci        } else {
464b1994897Sopenharmony_ci            UNREACHABLE();
465b1994897Sopenharmony_ci        }
466b1994897Sopenharmony_ci        CHECK_NOT_NULL(graph_regs);
467b1994897Sopenharmony_ci        graph_regs->resize(used_regs->size());
468b1994897Sopenharmony_ci        std::copy(used_regs->begin(), used_regs->end(), graph_regs->begin());
469b1994897Sopenharmony_ci    }
470b1994897Sopenharmony_ci
471b1994897Sopenharmony_ci    uint32_t GetStackSlotsCount() const
472b1994897Sopenharmony_ci    {
473b1994897Sopenharmony_ci        return stack_slot_count_;
474b1994897Sopenharmony_ci    }
475b1994897Sopenharmony_ci
476b1994897Sopenharmony_ci    void SetStackSlotsCount(uint32_t stack_slot_count)
477b1994897Sopenharmony_ci    {
478b1994897Sopenharmony_ci        stack_slot_count_ = stack_slot_count;
479b1994897Sopenharmony_ci    }
480b1994897Sopenharmony_ci
481b1994897Sopenharmony_ci    void UpdateStackSlotsCount(uint32_t stack_slot_count)
482b1994897Sopenharmony_ci    {
483b1994897Sopenharmony_ci        stack_slot_count_ = std::max(stack_slot_count_, stack_slot_count);
484b1994897Sopenharmony_ci    }
485b1994897Sopenharmony_ci
486b1994897Sopenharmony_ci    uint32_t GetParametersSlotsCount() const;
487b1994897Sopenharmony_ci
488b1994897Sopenharmony_ci    uint32_t GetExtSlotsStart() const
489b1994897Sopenharmony_ci    {
490b1994897Sopenharmony_ci        return ext_stack_slot_;
491b1994897Sopenharmony_ci    }
492b1994897Sopenharmony_ci
493b1994897Sopenharmony_ci    void SetExtSlotsStart(uint32_t ext_stack_slot)
494b1994897Sopenharmony_ci    {
495b1994897Sopenharmony_ci        ext_stack_slot_ = ext_stack_slot;
496b1994897Sopenharmony_ci    }
497b1994897Sopenharmony_ci
498b1994897Sopenharmony_ci    BasicBlock *CreateEmptyBlock(uint32_t guest_pc = INVALID_PC);
499b1994897Sopenharmony_ci    BasicBlock *CreateEmptyBlock(BasicBlock *base_block);
500b1994897Sopenharmony_ci#ifndef NDEBUG
501b1994897Sopenharmony_ci    BasicBlock *CreateEmptyBlock(uint32_t id, uint32_t guest_pc);
502b1994897Sopenharmony_ci#endif
503b1994897Sopenharmony_ci    BasicBlock *CreateStartBlock();
504b1994897Sopenharmony_ci    BasicBlock *CreateEndBlock(uint32_t guest_pc = INVALID_PC);
505b1994897Sopenharmony_ci    ConstantInst *GetFirstConstInst()
506b1994897Sopenharmony_ci    {
507b1994897Sopenharmony_ci        return first_const_inst_;
508b1994897Sopenharmony_ci    }
509b1994897Sopenharmony_ci    void SetFirstConstInst(ConstantInst *const_inst)
510b1994897Sopenharmony_ci    {
511b1994897Sopenharmony_ci        first_const_inst_ = const_inst;
512b1994897Sopenharmony_ci    }
513b1994897Sopenharmony_ci
514b1994897Sopenharmony_ci    Inst *GetNullPtrInst() const
515b1994897Sopenharmony_ci    {
516b1994897Sopenharmony_ci        return nullptr_inst_;
517b1994897Sopenharmony_ci    }
518b1994897Sopenharmony_ci    bool HasNullPtrInst() const
519b1994897Sopenharmony_ci    {
520b1994897Sopenharmony_ci        return nullptr_inst_ != nullptr;
521b1994897Sopenharmony_ci    }
522b1994897Sopenharmony_ci    void UnsetNullPtrInst()
523b1994897Sopenharmony_ci    {
524b1994897Sopenharmony_ci        ASSERT(HasNullPtrInst());
525b1994897Sopenharmony_ci        nullptr_inst_ = nullptr;
526b1994897Sopenharmony_ci    }
527b1994897Sopenharmony_ci
528b1994897Sopenharmony_ci    /// Find constant in the list, return nullptr if not found
529b1994897Sopenharmony_ci    ConstantInst *FindConstant(DataType::Type type, uint64_t value);
530b1994897Sopenharmony_ci    /// Find constant in the list or create new one and insert at the end
531b1994897Sopenharmony_ci    template <typename T>
532b1994897Sopenharmony_ci    ConstantInst *FindOrCreateConstant(T value);
533b1994897Sopenharmony_ci
534b1994897Sopenharmony_ci    /**
535b1994897Sopenharmony_ci     * Find constant that is equal to the given one specified by inst. If not found, add inst to the graph.
536b1994897Sopenharmony_ci     * @param inst Constant instruction to be added
537b1994897Sopenharmony_ci     * @return Found instruction or inst if not found
538b1994897Sopenharmony_ci     */
539b1994897Sopenharmony_ci    ConstantInst *FindOrAddConstant(ConstantInst *inst);
540b1994897Sopenharmony_ci
541b1994897Sopenharmony_ci    ParameterInst *AddNewParameter(uint16_t arg_number);
542b1994897Sopenharmony_ci
543b1994897Sopenharmony_ci    ParameterInst *AddNewParameter(uint16_t arg_number, DataType::Type type)
544b1994897Sopenharmony_ci    {
545b1994897Sopenharmony_ci        ParameterInst *param = AddNewParameter(arg_number);
546b1994897Sopenharmony_ci        param->SetType(type);
547b1994897Sopenharmony_ci        return param;
548b1994897Sopenharmony_ci    }
549b1994897Sopenharmony_ci
550b1994897Sopenharmony_ci    /*
551b1994897Sopenharmony_ci     * The function remove the ConstantInst from the graph list
552b1994897Sopenharmony_ci     * !NOTE ConstantInst isn't removed from BasicBlock list
553b1994897Sopenharmony_ci     */
554b1994897Sopenharmony_ci    void RemoveConstFromList(ConstantInst *const_inst);
555b1994897Sopenharmony_ci
556b1994897Sopenharmony_ci    ConstantInst *GetSpilledConstant(ImmTableSlot slot)
557b1994897Sopenharmony_ci    {
558b1994897Sopenharmony_ci        ASSERT(static_cast<size_t>(slot) < spilled_constants_.size());
559b1994897Sopenharmony_ci        return spilled_constants_[slot];
560b1994897Sopenharmony_ci    }
561b1994897Sopenharmony_ci
562b1994897Sopenharmony_ci    ImmTableSlot AddSpilledConstant(ConstantInst *const_inst)
563b1994897Sopenharmony_ci    {
564b1994897Sopenharmony_ci        // Constant already in the table
565b1994897Sopenharmony_ci        auto current_slot = const_inst->GetImmTableSlot();
566b1994897Sopenharmony_ci        if (current_slot != INVALID_IMM_TABLE_SLOT) {
567b1994897Sopenharmony_ci            ASSERT(spilled_constants_[current_slot] == const_inst);
568b1994897Sopenharmony_ci            return current_slot;
569b1994897Sopenharmony_ci        }
570b1994897Sopenharmony_ci
571b1994897Sopenharmony_ci        auto count = spilled_constants_.size();
572b1994897Sopenharmony_ci        if (count >= MAX_NUM_IMM_SLOTS) {
573b1994897Sopenharmony_ci            return INVALID_IMM_TABLE_SLOT;
574b1994897Sopenharmony_ci        }
575b1994897Sopenharmony_ci        spilled_constants_.push_back(const_inst);
576b1994897Sopenharmony_ci        const_inst->SetImmTableSlot(count);
577b1994897Sopenharmony_ci        return ImmTableSlot(count);
578b1994897Sopenharmony_ci    }
579b1994897Sopenharmony_ci
580b1994897Sopenharmony_ci    ImmTableSlot FindSpilledConstantSlot(ConstantInst *const_inst) const
581b1994897Sopenharmony_ci    {
582b1994897Sopenharmony_ci        auto slot = std::find(spilled_constants_.begin(), spilled_constants_.end(), const_inst);
583b1994897Sopenharmony_ci        if (slot == spilled_constants_.end()) {
584b1994897Sopenharmony_ci            return INVALID_IMM_TABLE_SLOT;
585b1994897Sopenharmony_ci        }
586b1994897Sopenharmony_ci        return std::distance(spilled_constants_.begin(), slot);
587b1994897Sopenharmony_ci    }
588b1994897Sopenharmony_ci
589b1994897Sopenharmony_ci    size_t GetSpilledConstantsCount() const
590b1994897Sopenharmony_ci    {
591b1994897Sopenharmony_ci        return spilled_constants_.size();
592b1994897Sopenharmony_ci    }
593b1994897Sopenharmony_ci
594b1994897Sopenharmony_ci    bool HasAvailableConstantSpillSlots() const
595b1994897Sopenharmony_ci    {
596b1994897Sopenharmony_ci        return GetSpilledConstantsCount() < MAX_NUM_IMM_SLOTS;
597b1994897Sopenharmony_ci    }
598b1994897Sopenharmony_ci
599b1994897Sopenharmony_ci    auto begin()  // NOLINT(readability-identifier-naming)
600b1994897Sopenharmony_ci    {
601b1994897Sopenharmony_ci        return vector_bb_.begin();
602b1994897Sopenharmony_ci    }
603b1994897Sopenharmony_ci    auto begin() const  // NOLINT(readability-identifier-naming)
604b1994897Sopenharmony_ci    {
605b1994897Sopenharmony_ci        return vector_bb_.begin();
606b1994897Sopenharmony_ci    }
607b1994897Sopenharmony_ci    auto end()  // NOLINT(readability-identifier-naming)
608b1994897Sopenharmony_ci    {
609b1994897Sopenharmony_ci        return vector_bb_.end();
610b1994897Sopenharmony_ci    }
611b1994897Sopenharmony_ci    auto end() const  // NOLINT(readability-identifier-naming)
612b1994897Sopenharmony_ci    {
613b1994897Sopenharmony_ci        return vector_bb_.end();
614b1994897Sopenharmony_ci    }
615b1994897Sopenharmony_ci
616b1994897Sopenharmony_ci    void Dump(std::ostream *out) const;
617b1994897Sopenharmony_ci
618b1994897Sopenharmony_ci    Loop *GetRootLoop()
619b1994897Sopenharmony_ci    {
620b1994897Sopenharmony_ci        return root_loop_;
621b1994897Sopenharmony_ci    }
622b1994897Sopenharmony_ci    const Loop *GetRootLoop() const
623b1994897Sopenharmony_ci    {
624b1994897Sopenharmony_ci        return root_loop_;
625b1994897Sopenharmony_ci    }
626b1994897Sopenharmony_ci
627b1994897Sopenharmony_ci    void SetRootLoop(Loop *root_loop)
628b1994897Sopenharmony_ci    {
629b1994897Sopenharmony_ci        root_loop_ = root_loop;
630b1994897Sopenharmony_ci    }
631b1994897Sopenharmony_ci
632b1994897Sopenharmony_ci    void SetHasIrreducibleLoop(bool has_irr_loop)
633b1994897Sopenharmony_ci    {
634b1994897Sopenharmony_ci        FlagIrredicibleLoop::Set(has_irr_loop, &bit_fields_);
635b1994897Sopenharmony_ci    }
636b1994897Sopenharmony_ci
637b1994897Sopenharmony_ci    void SetHasInfiniteLoop(bool has_inf_loop)
638b1994897Sopenharmony_ci    {
639b1994897Sopenharmony_ci        FlagInfiniteLoop::Set(has_inf_loop, &bit_fields_);
640b1994897Sopenharmony_ci    }
641b1994897Sopenharmony_ci
642b1994897Sopenharmony_ci    void SetHasFloatRegs()
643b1994897Sopenharmony_ci    {
644b1994897Sopenharmony_ci        FlagFloatRegs::Set(true, &bit_fields_);
645b1994897Sopenharmony_ci    }
646b1994897Sopenharmony_ci
647b1994897Sopenharmony_ci    bool HasLoop() const;
648b1994897Sopenharmony_ci    bool HasIrreducibleLoop() const;
649b1994897Sopenharmony_ci    bool HasInfiniteLoop() const;
650b1994897Sopenharmony_ci    bool HasFloatRegs() const;
651b1994897Sopenharmony_ci
652b1994897Sopenharmony_ci    /**
653b1994897Sopenharmony_ci     * Try-catch info
654b1994897Sopenharmony_ci     * Vector of begin try-blocks in order they were declared in the bytecode
655b1994897Sopenharmony_ci     */
656b1994897Sopenharmony_ci    void AppendTryBeginBlock(const BasicBlock *block)
657b1994897Sopenharmony_ci    {
658b1994897Sopenharmony_ci        try_begin_blocks_.push_back(block);
659b1994897Sopenharmony_ci    }
660b1994897Sopenharmony_ci
661b1994897Sopenharmony_ci    void EraseTryBeginBlock(const BasicBlock *block)
662b1994897Sopenharmony_ci    {
663b1994897Sopenharmony_ci        auto it = std::find(try_begin_blocks_.begin(), try_begin_blocks_.end(), block);
664b1994897Sopenharmony_ci        if (it == try_begin_blocks_.end()) {
665b1994897Sopenharmony_ci            ASSERT(false && "Trying to remove non try_begin block");
666b1994897Sopenharmony_ci            return;
667b1994897Sopenharmony_ci        }
668b1994897Sopenharmony_ci        try_begin_blocks_.erase(it);
669b1994897Sopenharmony_ci    }
670b1994897Sopenharmony_ci
671b1994897Sopenharmony_ci    const auto &GetTryBeginBlocks() const
672b1994897Sopenharmony_ci    {
673b1994897Sopenharmony_ci        return try_begin_blocks_;
674b1994897Sopenharmony_ci    }
675b1994897Sopenharmony_ci
676b1994897Sopenharmony_ci    void AppendThrowableInst(const Inst *inst, BasicBlock *catch_handler)
677b1994897Sopenharmony_ci    {
678b1994897Sopenharmony_ci        auto it = throwable_insts_.emplace(inst, GetAllocator()->Adapter()).first;
679b1994897Sopenharmony_ci        it->second.push_back(catch_handler);
680b1994897Sopenharmony_ci    }
681b1994897Sopenharmony_ci
682b1994897Sopenharmony_ci    bool IsInstThrowable(const Inst *inst) const
683b1994897Sopenharmony_ci    {
684b1994897Sopenharmony_ci        return throwable_insts_.count(inst) > 0;
685b1994897Sopenharmony_ci    }
686b1994897Sopenharmony_ci
687b1994897Sopenharmony_ci    void RemoveThrowableInst(const Inst *inst);
688b1994897Sopenharmony_ci    void ReplaceThrowableInst(Inst *old_inst, Inst *new_inst);
689b1994897Sopenharmony_ci
690b1994897Sopenharmony_ci    const auto &GetThrowableInstHandlers(const Inst *inst) const
691b1994897Sopenharmony_ci    {
692b1994897Sopenharmony_ci        ASSERT(IsInstThrowable(inst));
693b1994897Sopenharmony_ci        return throwable_insts_.at(inst);
694b1994897Sopenharmony_ci    }
695b1994897Sopenharmony_ci
696b1994897Sopenharmony_ci    void ClearTryCatchInfo()
697b1994897Sopenharmony_ci    {
698b1994897Sopenharmony_ci        throwable_insts_.clear();
699b1994897Sopenharmony_ci        try_begin_blocks_.clear();
700b1994897Sopenharmony_ci    }
701b1994897Sopenharmony_ci
702b1994897Sopenharmony_ci    void DumpThrowableInsts(std::ostream *out) const;
703b1994897Sopenharmony_ci
704b1994897Sopenharmony_ci    /**
705b1994897Sopenharmony_ci     * Run pass specified by template argument T.
706b1994897Sopenharmony_ci     * Optimization passes might take additional arguments that will passed to Optimization's constructor.
707b1994897Sopenharmony_ci     * Analyses can't take additional arguments.
708b1994897Sopenharmony_ci     * @tparam T Type of pass
709b1994897Sopenharmony_ci     * @param args Additional arguments for optimizations passes
710b1994897Sopenharmony_ci     * @return true if pass was successful
711b1994897Sopenharmony_ci     */
712b1994897Sopenharmony_ci    template <typename T, typename... Args>
713b1994897Sopenharmony_ci    bool RunPass(Args... args)
714b1994897Sopenharmony_ci    {
715b1994897Sopenharmony_ci        ASSERT(GetPassManager());
716b1994897Sopenharmony_ci        return pass_manager_.RunPass<T>(std::forward<Args>(args)...);
717b1994897Sopenharmony_ci    }
718b1994897Sopenharmony_ci    template <typename T, typename... Args>
719b1994897Sopenharmony_ci    bool RunPass(Args... args) const
720b1994897Sopenharmony_ci    {
721b1994897Sopenharmony_ci        ASSERT(GetPassManager());
722b1994897Sopenharmony_ci        return pass_manager_.RunPass<T>(std::forward<Args>(args)...);
723b1994897Sopenharmony_ci    }
724b1994897Sopenharmony_ci
725b1994897Sopenharmony_ci    template <typename T>
726b1994897Sopenharmony_ci    bool RunPass(T *pass)
727b1994897Sopenharmony_ci    {
728b1994897Sopenharmony_ci        ASSERT(GetPassManager());
729b1994897Sopenharmony_ci        return pass_manager_.RunPass(pass, GetLocalAllocator()->GetAllocatedSize());
730b1994897Sopenharmony_ci    }
731b1994897Sopenharmony_ci
732b1994897Sopenharmony_ci    /**
733b1994897Sopenharmony_ci     * Get analysis instance.
734b1994897Sopenharmony_ci     * All analyses are reside in Graph object in composition relationship.
735b1994897Sopenharmony_ci     * @tparam T Type of analysis
736b1994897Sopenharmony_ci     * @return Reference to analysis instance
737b1994897Sopenharmony_ci     */
738b1994897Sopenharmony_ci    template <typename T>
739b1994897Sopenharmony_ci    T &GetAnalysis()
740b1994897Sopenharmony_ci    {
741b1994897Sopenharmony_ci        ASSERT(GetPassManager());
742b1994897Sopenharmony_ci        return GetPassManager()->GetAnalysis<T>();
743b1994897Sopenharmony_ci    }
744b1994897Sopenharmony_ci    template <typename T>
745b1994897Sopenharmony_ci    const T &GetAnalysis() const
746b1994897Sopenharmony_ci    {
747b1994897Sopenharmony_ci        ASSERT(GetPassManager());
748b1994897Sopenharmony_ci        return pass_manager_.GetAnalysis<T>();
749b1994897Sopenharmony_ci    }
750b1994897Sopenharmony_ci
751b1994897Sopenharmony_ci    /**
752b1994897Sopenharmony_ci     * Same as GetAnalysis but additionaly checck that analysis in valid state.
753b1994897Sopenharmony_ci     * @tparam T Type of analysis
754b1994897Sopenharmony_ci     * @return Reference to analysis instance
755b1994897Sopenharmony_ci     */
756b1994897Sopenharmony_ci    template <typename T>
757b1994897Sopenharmony_ci    T &GetValidAnalysis()
758b1994897Sopenharmony_ci    {
759b1994897Sopenharmony_ci        RunPass<T>();
760b1994897Sopenharmony_ci        ASSERT(IsAnalysisValid<T>());
761b1994897Sopenharmony_ci        return GetAnalysis<T>();
762b1994897Sopenharmony_ci    }
763b1994897Sopenharmony_ci    template <typename T>
764b1994897Sopenharmony_ci    const T &GetValidAnalysis() const
765b1994897Sopenharmony_ci    {
766b1994897Sopenharmony_ci        RunPass<T>();
767b1994897Sopenharmony_ci        ASSERT(IsAnalysisValid<T>());
768b1994897Sopenharmony_ci        return GetAnalysis<T>();
769b1994897Sopenharmony_ci    }
770b1994897Sopenharmony_ci
771b1994897Sopenharmony_ci    /**
772b1994897Sopenharmony_ci     * Return true if Analysis valid, false otherwise
773b1994897Sopenharmony_ci     * @tparam T Type of analysis
774b1994897Sopenharmony_ci     */
775b1994897Sopenharmony_ci    template <typename T>
776b1994897Sopenharmony_ci    bool IsAnalysisValid() const
777b1994897Sopenharmony_ci    {
778b1994897Sopenharmony_ci        return GetAnalysis<T>().IsValid();
779b1994897Sopenharmony_ci    }
780b1994897Sopenharmony_ci
781b1994897Sopenharmony_ci    /**
782b1994897Sopenharmony_ci     * Reset valid state of specified analysis
783b1994897Sopenharmony_ci     * @tparam T Type of analysis
784b1994897Sopenharmony_ci     */
785b1994897Sopenharmony_ci    template <typename T>
786b1994897Sopenharmony_ci    void InvalidateAnalysis()
787b1994897Sopenharmony_ci    {
788b1994897Sopenharmony_ci        ASSERT(GetPassManager());
789b1994897Sopenharmony_ci        GetPassManager()->GetAnalysis<T>().SetValid(false);
790b1994897Sopenharmony_ci    }
791b1994897Sopenharmony_ci
792b1994897Sopenharmony_ci    /// Accessors to the number of current instruction id.
793b1994897Sopenharmony_ci    auto GetCurrentInstructionId() const
794b1994897Sopenharmony_ci    {
795b1994897Sopenharmony_ci        return instr_current_id_;
796b1994897Sopenharmony_ci    }
797b1994897Sopenharmony_ci    auto SetCurrentInstructionId(size_t v)
798b1994897Sopenharmony_ci    {
799b1994897Sopenharmony_ci        instr_current_id_ = v;
800b1994897Sopenharmony_ci    }
801b1994897Sopenharmony_ci
802b1994897Sopenharmony_ci    /// RuntimeInterface accessors
803b1994897Sopenharmony_ci    RuntimeInterface *GetRuntime() const
804b1994897Sopenharmony_ci    {
805b1994897Sopenharmony_ci        return runtime_;
806b1994897Sopenharmony_ci    }
807b1994897Sopenharmony_ci    void SetRuntime(RuntimeInterface *runtime)
808b1994897Sopenharmony_ci    {
809b1994897Sopenharmony_ci        runtime_ = runtime;
810b1994897Sopenharmony_ci    }
811b1994897Sopenharmony_ci    auto GetMethod() const
812b1994897Sopenharmony_ci    {
813b1994897Sopenharmony_ci        return method_;
814b1994897Sopenharmony_ci    }
815b1994897Sopenharmony_ci    auto SetMethod(RuntimeInterface::MethodPtr method)
816b1994897Sopenharmony_ci    {
817b1994897Sopenharmony_ci        method_ = method;
818b1994897Sopenharmony_ci    }
819b1994897Sopenharmony_ci
820b1994897Sopenharmony_ci    void ResetParameterInfo();
821b1994897Sopenharmony_ci
822b1994897Sopenharmony_ci    EventWriter &GetEventWriter()
823b1994897Sopenharmony_ci    {
824b1994897Sopenharmony_ci        return event_writer_;
825b1994897Sopenharmony_ci    }
826b1994897Sopenharmony_ci
827b1994897Sopenharmony_ci    // clang-format off
828b1994897Sopenharmony_ci
829b1994897Sopenharmony_ci    /**
830b1994897Sopenharmony_ci     * Create instruction by opcode
831b1994897Sopenharmony_ci     */
832b1994897Sopenharmony_ci    [[nodiscard]] Inst* CreateInst(Opcode opc) const
833b1994897Sopenharmony_ci    {
834b1994897Sopenharmony_ci        switch (opc) {
835b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
836b1994897Sopenharmony_ci#define INST_DEF(OPCODE, BASE, ...)                                      \
837b1994897Sopenharmony_ci            case Opcode::OPCODE: {                                       \
838b1994897Sopenharmony_ci                auto inst = Inst::New<BASE>(ALLOCATOR, Opcode::OPCODE);  \
839b1994897Sopenharmony_ci                inst->SetId(instr_current_id_++);                        \
840b1994897Sopenharmony_ci                return inst;                                             \
841b1994897Sopenharmony_ci                }
842b1994897Sopenharmony_ci                OPCODE_LIST(INST_DEF)
843b1994897Sopenharmony_ci
844b1994897Sopenharmony_ci#undef INST_DEF
845b1994897Sopenharmony_ci            default:
846b1994897Sopenharmony_ci                return nullptr;
847b1994897Sopenharmony_ci        }
848b1994897Sopenharmony_ci    }
849b1994897Sopenharmony_ci    /**
850b1994897Sopenharmony_ci     * Define creation methods for all opcodes
851b1994897Sopenharmony_ci     */
852b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
853b1994897Sopenharmony_ci#define INST_DEF(OPCODE, BASE, ...)                                               \
854b1994897Sopenharmony_ci    template <typename... Args>                                                   \
855b1994897Sopenharmony_ci    [[nodiscard]] BASE* CreateInst##OPCODE(Args&&... args) const {                \
856b1994897Sopenharmony_ci        auto inst = Inst::New<BASE>(ALLOCATOR, Opcode::OPCODE, std::forward<Args>(args)...);  \
857b1994897Sopenharmony_ci        inst->SetId(instr_current_id_++); \
858b1994897Sopenharmony_ci        return inst; \
859b1994897Sopenharmony_ci    }
860b1994897Sopenharmony_ci    OPCODE_LIST(INST_DEF)
861b1994897Sopenharmony_ci
862b1994897Sopenharmony_ci#undef INST_DEF
863b1994897Sopenharmony_ci    // clang-format on
864b1994897Sopenharmony_ci
865b1994897Sopenharmony_ci    uint32_t GetBitFields()
866b1994897Sopenharmony_ci    {
867b1994897Sopenharmony_ci        return bit_fields_;
868b1994897Sopenharmony_ci    }
869b1994897Sopenharmony_ci
870b1994897Sopenharmony_ci    void SetBitFields(uint32_t bit_fields)
871b1994897Sopenharmony_ci    {
872b1994897Sopenharmony_ci        bit_fields_ = bit_fields;
873b1994897Sopenharmony_ci    }
874b1994897Sopenharmony_ci
875b1994897Sopenharmony_ci    bool NeedCleanup() const
876b1994897Sopenharmony_ci    {
877b1994897Sopenharmony_ci        return FlagNeedCleanup::Get(bit_fields_);
878b1994897Sopenharmony_ci    }
879b1994897Sopenharmony_ci
880b1994897Sopenharmony_ci    void SetNeedCleanup(bool v)
881b1994897Sopenharmony_ci    {
882b1994897Sopenharmony_ci        FlagNeedCleanup::Set(v, &bit_fields_);
883b1994897Sopenharmony_ci    }
884b1994897Sopenharmony_ci
885b1994897Sopenharmony_ci    bool IsOsrMode() const
886b1994897Sopenharmony_ci    {
887b1994897Sopenharmony_ci        return mode_.IsOsr();
888b1994897Sopenharmony_ci    }
889b1994897Sopenharmony_ci
890b1994897Sopenharmony_ci    bool IsBytecodeOptimizer() const
891b1994897Sopenharmony_ci    {
892b1994897Sopenharmony_ci        return mode_.IsBytecodeOpt();
893b1994897Sopenharmony_ci    }
894b1994897Sopenharmony_ci
895b1994897Sopenharmony_ci    bool IsDynamicMethod() const
896b1994897Sopenharmony_ci    {
897b1994897Sopenharmony_ci        return mode_.IsDynamicMethod();
898b1994897Sopenharmony_ci    }
899b1994897Sopenharmony_ci
900b1994897Sopenharmony_ci    bool SupportManagedCode() const
901b1994897Sopenharmony_ci    {
902b1994897Sopenharmony_ci        return mode_.SupportManagedCode();
903b1994897Sopenharmony_ci    }
904b1994897Sopenharmony_ci
905b1994897Sopenharmony_ci    GraphMode GetMode() const
906b1994897Sopenharmony_ci    {
907b1994897Sopenharmony_ci        return mode_;
908b1994897Sopenharmony_ci    }
909b1994897Sopenharmony_ci
910b1994897Sopenharmony_ci    void SetMode(GraphMode mode)
911b1994897Sopenharmony_ci    {
912b1994897Sopenharmony_ci        mode_ = mode;
913b1994897Sopenharmony_ci    }
914b1994897Sopenharmony_ci
915b1994897Sopenharmony_ci#ifndef NDEBUG
916b1994897Sopenharmony_ci    compiler::inst_modes::Mode GetCompilerMode()
917b1994897Sopenharmony_ci    {
918b1994897Sopenharmony_ci        if (IsBytecodeOptimizer()) {
919b1994897Sopenharmony_ci            return compiler::inst_modes::BYTECODE_OPT;
920b1994897Sopenharmony_ci        }
921b1994897Sopenharmony_ci        if (SupportManagedCode()) {
922b1994897Sopenharmony_ci            return compiler::inst_modes::JIT_AOT;
923b1994897Sopenharmony_ci        }
924b1994897Sopenharmony_ci        return compiler::inst_modes::IRTOC;
925b1994897Sopenharmony_ci    }
926b1994897Sopenharmony_ci#endif
927b1994897Sopenharmony_ci
928b1994897Sopenharmony_ci    void AddSingleImplementationMethod(RuntimeInterface::MethodPtr method)
929b1994897Sopenharmony_ci    {
930b1994897Sopenharmony_ci        single_implementation_list_.push_back(method);
931b1994897Sopenharmony_ci    }
932b1994897Sopenharmony_ci
933b1994897Sopenharmony_ci    void SetDynamicMethod()
934b1994897Sopenharmony_ci    {
935b1994897Sopenharmony_ci        mode_.SetDynamicMethod(true);
936b1994897Sopenharmony_ci    }
937b1994897Sopenharmony_ci
938b1994897Sopenharmony_ci    auto &GetSingleImplementationList()
939b1994897Sopenharmony_ci    {
940b1994897Sopenharmony_ci        return single_implementation_list_;
941b1994897Sopenharmony_ci    }
942b1994897Sopenharmony_ci
943b1994897Sopenharmony_ci    Graph *GetParentGraph()
944b1994897Sopenharmony_ci    {
945b1994897Sopenharmony_ci        return parent_graph_;
946b1994897Sopenharmony_ci    }
947b1994897Sopenharmony_ci
948b1994897Sopenharmony_ci    Graph *GetOutermostParentGraph()
949b1994897Sopenharmony_ci    {
950b1994897Sopenharmony_ci        auto graph = this;
951b1994897Sopenharmony_ci        while (graph->GetParentGraph() != nullptr) {
952b1994897Sopenharmony_ci            graph = graph->GetParentGraph();
953b1994897Sopenharmony_ci        }
954b1994897Sopenharmony_ci        return graph;
955b1994897Sopenharmony_ci    }
956b1994897Sopenharmony_ci
957b1994897Sopenharmony_ci    void SetVRegsCount(size_t count)
958b1994897Sopenharmony_ci    {
959b1994897Sopenharmony_ci        vregs_count_ = count;
960b1994897Sopenharmony_ci    }
961b1994897Sopenharmony_ci
962b1994897Sopenharmony_ci    size_t GetVRegsCount() const
963b1994897Sopenharmony_ci    {
964b1994897Sopenharmony_ci        return vregs_count_;
965b1994897Sopenharmony_ci    }
966b1994897Sopenharmony_ci
967b1994897Sopenharmony_ci    int64_t GetBranchCounter(const BasicBlock *block, bool true_succ);
968b1994897Sopenharmony_ci
969b1994897Sopenharmony_ci    /**
970b1994897Sopenharmony_ci     * This class provides methods for ranged-based `for` loop over all parameters in the graph.
971b1994897Sopenharmony_ci     */
972b1994897Sopenharmony_ci    class ParameterList {
973b1994897Sopenharmony_ci    public:
974b1994897Sopenharmony_ci        class Iterator {
975b1994897Sopenharmony_ci        public:
976b1994897Sopenharmony_ci            explicit Iterator(Inst *inst) : inst_(inst) {}
977b1994897Sopenharmony_ci
978b1994897Sopenharmony_ci            Iterator &operator++()
979b1994897Sopenharmony_ci            {
980b1994897Sopenharmony_ci                for (inst_ = inst_->GetNext(); inst_ != nullptr && inst_->GetOpcode() != Opcode::Parameter;
981b1994897Sopenharmony_ci                     inst_ = inst_->GetNext()) {
982b1994897Sopenharmony_ci                }
983b1994897Sopenharmony_ci                return *this;
984b1994897Sopenharmony_ci            }
985b1994897Sopenharmony_ci            bool operator!=(const Iterator &other)
986b1994897Sopenharmony_ci            {
987b1994897Sopenharmony_ci                return inst_ != other.inst_;
988b1994897Sopenharmony_ci            }
989b1994897Sopenharmony_ci            Inst *operator*()
990b1994897Sopenharmony_ci            {
991b1994897Sopenharmony_ci                return inst_;
992b1994897Sopenharmony_ci            }
993b1994897Sopenharmony_ci            Inst *operator->()
994b1994897Sopenharmony_ci            {
995b1994897Sopenharmony_ci                return inst_;
996b1994897Sopenharmony_ci            }
997b1994897Sopenharmony_ci
998b1994897Sopenharmony_ci        private:
999b1994897Sopenharmony_ci            Inst *inst_ {nullptr};
1000b1994897Sopenharmony_ci        };
1001b1994897Sopenharmony_ci
1002b1994897Sopenharmony_ci        explicit ParameterList(const Graph *graph) : graph_(graph) {}
1003b1994897Sopenharmony_ci
1004b1994897Sopenharmony_ci        // NOLINTNEXTLINE(readability-identifier-naming)
1005b1994897Sopenharmony_ci        Iterator begin();
1006b1994897Sopenharmony_ci        // NOLINTNEXTLINE(readability-identifier-naming)
1007b1994897Sopenharmony_ci        static Iterator end()
1008b1994897Sopenharmony_ci        {
1009b1994897Sopenharmony_ci            return Iterator(nullptr);
1010b1994897Sopenharmony_ci        }
1011b1994897Sopenharmony_ci
1012b1994897Sopenharmony_ci    private:
1013b1994897Sopenharmony_ci        const Graph *graph_ {nullptr};
1014b1994897Sopenharmony_ci    };
1015b1994897Sopenharmony_ci
1016b1994897Sopenharmony_ci    /**
1017b1994897Sopenharmony_ci     * Get list of all parameters
1018b1994897Sopenharmony_ci     * @return instance of the ParameterList class
1019b1994897Sopenharmony_ci     */
1020b1994897Sopenharmony_ci    ParameterList GetParameters() const
1021b1994897Sopenharmony_ci    {
1022b1994897Sopenharmony_ci        return ParameterList(this);
1023b1994897Sopenharmony_ci    }
1024b1994897Sopenharmony_ci
1025b1994897Sopenharmony_ci    void InitDefaultLocations();
1026b1994897Sopenharmony_ci
1027b1994897Sopenharmony_ciprivate:
1028b1994897Sopenharmony_ci    void AddConstInStartBlock(ConstantInst *const_inst);
1029b1994897Sopenharmony_ci
1030b1994897Sopenharmony_ci    NO_MOVE_SEMANTIC(Graph);
1031b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(Graph);
1032b1994897Sopenharmony_ci
1033b1994897Sopenharmony_ciprivate:
1034b1994897Sopenharmony_ci    ArenaAllocator *const ALLOCATOR;
1035b1994897Sopenharmony_ci    ArenaAllocator *const LOCAL_ALLOCATOR;
1036b1994897Sopenharmony_ci
1037b1994897Sopenharmony_ci    Arch arch_ {RUNTIME_ARCH};
1038b1994897Sopenharmony_ci
1039b1994897Sopenharmony_ci    // List of blocks in insertion order.
1040b1994897Sopenharmony_ci    ArenaVector<BasicBlock *> vector_bb_;
1041b1994897Sopenharmony_ci    BasicBlock *start_block_ {nullptr};
1042b1994897Sopenharmony_ci    BasicBlock *end_block_ {nullptr};
1043b1994897Sopenharmony_ci
1044b1994897Sopenharmony_ci    Loop *root_loop_ {nullptr};
1045b1994897Sopenharmony_ci
1046b1994897Sopenharmony_ci    uint32_t bit_fields_ {0};
1047b1994897Sopenharmony_ci    using FlagDFConstruct = BitField<bool, 0, 1>;
1048b1994897Sopenharmony_ci    using FlagNeedCleanup = FlagDFConstruct::NextFlag;
1049b1994897Sopenharmony_ci    using FlagIrredicibleLoop = FlagNeedCleanup::NextFlag;
1050b1994897Sopenharmony_ci    using FlagInfiniteLoop = FlagIrredicibleLoop::NextFlag;
1051b1994897Sopenharmony_ci    using FlagFloatRegs = FlagInfiniteLoop::NextFlag;
1052b1994897Sopenharmony_ci    using FlagDefaultLocationsInit = FlagFloatRegs::NextFlag;
1053b1994897Sopenharmony_ci#ifndef NDEBUG
1054b1994897Sopenharmony_ci    using FlagRegallocApplied = FlagDefaultLocationsInit::NextFlag;
1055b1994897Sopenharmony_ci    using FlagRegaccallocApplied = FlagRegallocApplied::NextFlag;
1056b1994897Sopenharmony_ci    using FlagInliningComplete = FlagRegaccallocApplied::NextFlag;
1057b1994897Sopenharmony_ci    using FlagSchedulerComplete = FlagInliningComplete::NextFlag;
1058b1994897Sopenharmony_ci    using FlagLowLevelInstnsEnabled = FlagSchedulerComplete::NextFlag;
1059b1994897Sopenharmony_ci#endif  // NDEBUG
1060b1994897Sopenharmony_ci
1061b1994897Sopenharmony_ci    // codegen data
1062b1994897Sopenharmony_ci    EncodeDataType data_;
1063b1994897Sopenharmony_ci    Span<const uint8_t> code_info_data_;
1064b1994897Sopenharmony_ci    ArenaVector<bool> *used_regs_ {nullptr};
1065b1994897Sopenharmony_ci    ArenaVector<bool> *used_vregs_ {nullptr};
1066b1994897Sopenharmony_ci
1067b1994897Sopenharmony_ci    // TODO (a.popov) Replace by ArenaMap from throwable_inst* to try_inst*
1068b1994897Sopenharmony_ci    ArenaMap<const Inst *, ArenaVector<BasicBlock *>> throwable_insts_;
1069b1994897Sopenharmony_ci
1070b1994897Sopenharmony_ci    mutable size_t instr_current_id_ {0};
1071b1994897Sopenharmony_ci    // first constant instruction in graph !TODO rewrite it to hash-map
1072b1994897Sopenharmony_ci    ConstantInst *first_const_inst_ {nullptr};
1073b1994897Sopenharmony_ci    Inst *nullptr_inst_ {nullptr};
1074b1994897Sopenharmony_ci
1075b1994897Sopenharmony_ci    RuntimeInterface *runtime_ {nullptr};
1076b1994897Sopenharmony_ci    RuntimeInterface::MethodPtr method_ {nullptr};
1077b1994897Sopenharmony_ci
1078b1994897Sopenharmony_ci    ParameterInfo *param_info_ {nullptr};
1079b1994897Sopenharmony_ci
1080b1994897Sopenharmony_ci    mutable PassManager pass_manager_;
1081b1994897Sopenharmony_ci    EventWriter event_writer_;
1082b1994897Sopenharmony_ci
1083b1994897Sopenharmony_ci    GraphMode mode_;
1084b1994897Sopenharmony_ci
1085b1994897Sopenharmony_ci    ArenaVector<RuntimeInterface::MethodPtr> single_implementation_list_;
1086b1994897Sopenharmony_ci    ArenaVector<const BasicBlock *> try_begin_blocks_;
1087b1994897Sopenharmony_ci    ArenaVector<ConstantInst *> spilled_constants_;
1088b1994897Sopenharmony_ci    // Graph that inlines this graph
1089b1994897Sopenharmony_ci    Graph *parent_graph_ {nullptr};
1090b1994897Sopenharmony_ci    // Number of used stack slots
1091b1994897Sopenharmony_ci    uint32_t stack_slot_count_ {0};
1092b1994897Sopenharmony_ci    // Number of used stack slots for parameters
1093b1994897Sopenharmony_ci    uint32_t param_slots_count_ {0};
1094b1994897Sopenharmony_ci    // First language extension slot
1095b1994897Sopenharmony_ci    uint32_t ext_stack_slot_ {0};
1096b1994897Sopenharmony_ci    // Number of the virtual registers used in the compiled method (inlined methods aren't included).
1097b1994897Sopenharmony_ci    uint32_t vregs_count_ {0};
1098b1994897Sopenharmony_ci};
1099b1994897Sopenharmony_ci
1100b1994897Sopenharmony_ciclass MarkerHolder {
1101b1994897Sopenharmony_cipublic:
1102b1994897Sopenharmony_ci    NO_COPY_SEMANTIC(MarkerHolder);
1103b1994897Sopenharmony_ci    NO_MOVE_SEMANTIC(MarkerHolder);
1104b1994897Sopenharmony_ci
1105b1994897Sopenharmony_ci    explicit MarkerHolder(const Graph *graph) : graph_(graph), marker_(graph->NewMarker())
1106b1994897Sopenharmony_ci    {
1107b1994897Sopenharmony_ci        ASSERT(marker_ != UNDEF_MARKER);
1108b1994897Sopenharmony_ci    }
1109b1994897Sopenharmony_ci
1110b1994897Sopenharmony_ci    ~MarkerHolder()
1111b1994897Sopenharmony_ci    {
1112b1994897Sopenharmony_ci        graph_->EraseMarker(marker_);
1113b1994897Sopenharmony_ci    }
1114b1994897Sopenharmony_ci
1115b1994897Sopenharmony_ci    Marker GetMarker()
1116b1994897Sopenharmony_ci    {
1117b1994897Sopenharmony_ci        return marker_;
1118b1994897Sopenharmony_ci    }
1119b1994897Sopenharmony_ci
1120b1994897Sopenharmony_ciprivate:
1121b1994897Sopenharmony_ci    const Graph *graph_;
1122b1994897Sopenharmony_ci    Marker marker_ {UNDEF_MARKER};
1123b1994897Sopenharmony_ci};
1124b1994897Sopenharmony_ci
1125b1994897Sopenharmony_citemplate <typename T>
1126b1994897Sopenharmony_ciConstantInst *Graph::FindOrCreateConstant(T value)
1127b1994897Sopenharmony_ci{
1128b1994897Sopenharmony_ci    bool is_support_int32 = IsBytecodeOptimizer();
1129b1994897Sopenharmony_ci    if (first_const_inst_ == nullptr) {
1130b1994897Sopenharmony_ci        first_const_inst_ = CreateInstConstant(value, is_support_int32);
1131b1994897Sopenharmony_ci        AddConstInStartBlock(first_const_inst_);
1132b1994897Sopenharmony_ci        return first_const_inst_;
1133b1994897Sopenharmony_ci    }
1134b1994897Sopenharmony_ci    ConstantInst *current_const = first_const_inst_;
1135b1994897Sopenharmony_ci    ConstantInst *prev_const = nullptr;
1136b1994897Sopenharmony_ci    while (current_const != nullptr) {
1137b1994897Sopenharmony_ci        if (current_const->IsEqualConst(value, is_support_int32)) {
1138b1994897Sopenharmony_ci            return current_const;
1139b1994897Sopenharmony_ci        }
1140b1994897Sopenharmony_ci        prev_const = current_const;
1141b1994897Sopenharmony_ci        current_const = current_const->GetNextConst();
1142b1994897Sopenharmony_ci    }
1143b1994897Sopenharmony_ci    ASSERT(prev_const != nullptr);
1144b1994897Sopenharmony_ci    auto *new_const = CreateInstConstant(value, is_support_int32);
1145b1994897Sopenharmony_ci    AddConstInStartBlock(new_const);
1146b1994897Sopenharmony_ci
1147b1994897Sopenharmony_ci    prev_const->SetNextConst(new_const);
1148b1994897Sopenharmony_ci    return new_const;
1149b1994897Sopenharmony_ci}
1150b1994897Sopenharmony_ci
1151b1994897Sopenharmony_civoid InvalidateBlocksOrderAnalyzes(Graph *graph);
1152b1994897Sopenharmony_civoid MarkLoopExits(const Graph *graph, Marker marker);
1153b1994897Sopenharmony_civoid RemovePredecessorUpdateDF(BasicBlock *block, BasicBlock *rm_pred);
1154b1994897Sopenharmony_cistd::string GetMethodFullName(const Graph *graph, RuntimeInterface::MethodPtr method);
1155b1994897Sopenharmony_ci}  // namespace panda::compiler
1156b1994897Sopenharmony_ci
1157b1994897Sopenharmony_ci#endif  // COMPILER_OPTIMIZER_IR_GRAPH_H
1158