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