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_INST_H 17b1994897Sopenharmony_ci#define COMPILER_OPTIMIZER_IR_INST_H 18b1994897Sopenharmony_ci 19b1994897Sopenharmony_ci#include <array> 20b1994897Sopenharmony_ci#include <vector> 21b1994897Sopenharmony_ci#include <iostream> 22b1994897Sopenharmony_ci#include "constants.h" 23b1994897Sopenharmony_ci#include "datatype.h" 24b1994897Sopenharmony_ci#include "ir-dyn-base-types.h" 25b1994897Sopenharmony_ci#include "marker.h" 26b1994897Sopenharmony_ci#include "utils/arena_containers.h" 27b1994897Sopenharmony_ci#include "utils/span.h" 28b1994897Sopenharmony_ci#include "utils/bit_field.h" 29b1994897Sopenharmony_ci#include "utils/bit_utils.h" 30b1994897Sopenharmony_ci#include "utils/bit_vector.h" 31b1994897Sopenharmony_ci#include "macros.h" 32b1994897Sopenharmony_ci#include "mem/arena_allocator.h" 33b1994897Sopenharmony_ci#include "opcodes.h" 34b1994897Sopenharmony_ci#include "compiler_options.h" 35b1994897Sopenharmony_ci#include "runtime_interface.h" 36b1994897Sopenharmony_ci#include "spill_fill_data.h" 37b1994897Sopenharmony_ci 38b1994897Sopenharmony_cinamespace panda::compiler { 39b1994897Sopenharmony_ciclass Inst; 40b1994897Sopenharmony_ciclass BasicBlock; 41b1994897Sopenharmony_ciclass Graph; 42b1994897Sopenharmony_ciclass GraphVisitor; 43b1994897Sopenharmony_ciclass VnObject; 44b1994897Sopenharmony_ciclass SaveStateItem; 45b1994897Sopenharmony_ciclass LocationsInfo; 46b1994897Sopenharmony_ciusing InstVector = ArenaVector<Inst *>; 47b1994897Sopenharmony_ci 48b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 49b1994897Sopenharmony_ci#define INST_DEF(opcode, base, ...) class base; 50b1994897Sopenharmony_ci// NOLINTNEXTLINE(fuchsia-multiple-inheritance) 51b1994897Sopenharmony_ciOPCODE_LIST(INST_DEF) 52b1994897Sopenharmony_ci#undef INST_DEF 53b1994897Sopenharmony_ci 54b1994897Sopenharmony_ci/* 55b1994897Sopenharmony_ci * Condition code, used in Compare, If[Imm] and Select[Imm] instructions. 56b1994897Sopenharmony_ci * 57b1994897Sopenharmony_ci * N.B. BranchElimination and Peephole rely on the order of these codes. Change carefully. 58b1994897Sopenharmony_ci */ 59b1994897Sopenharmony_cienum ConditionCode { 60b1994897Sopenharmony_ci // All types. 61b1994897Sopenharmony_ci CC_EQ = 0, // == 62b1994897Sopenharmony_ci CC_NE, // != 63b1994897Sopenharmony_ci // Signed integers and floating-point numbers. 64b1994897Sopenharmony_ci CC_LT, // < 65b1994897Sopenharmony_ci CC_LE, // <= 66b1994897Sopenharmony_ci CC_GT, // > 67b1994897Sopenharmony_ci CC_GE, // >= 68b1994897Sopenharmony_ci // Unsigned integers. 69b1994897Sopenharmony_ci CC_B, // < 70b1994897Sopenharmony_ci CC_BE, // <= 71b1994897Sopenharmony_ci CC_A, // > 72b1994897Sopenharmony_ci CC_AE, // >= 73b1994897Sopenharmony_ci // Compare result of bitwise AND with zero 74b1994897Sopenharmony_ci CC_TST_EQ, // (lhs AND rhs) == 0 75b1994897Sopenharmony_ci CC_TST_NE, // (lhs AND rhs) != 0 76b1994897Sopenharmony_ci // First and last aliases. 77b1994897Sopenharmony_ci CC_FIRST = CC_EQ, 78b1994897Sopenharmony_ci CC_LAST = CC_TST_NE, 79b1994897Sopenharmony_ci}; 80b1994897Sopenharmony_ci 81b1994897Sopenharmony_ciinline ConditionCode GetInverseConditionCode(ConditionCode code) 82b1994897Sopenharmony_ci{ 83b1994897Sopenharmony_ci switch (code) { 84b1994897Sopenharmony_ci case ConditionCode::CC_EQ: 85b1994897Sopenharmony_ci return ConditionCode::CC_NE; 86b1994897Sopenharmony_ci case ConditionCode::CC_NE: 87b1994897Sopenharmony_ci return ConditionCode::CC_EQ; 88b1994897Sopenharmony_ci default: 89b1994897Sopenharmony_ci UNREACHABLE(); 90b1994897Sopenharmony_ci } 91b1994897Sopenharmony_ci} 92b1994897Sopenharmony_ci 93b1994897Sopenharmony_ciinline ConditionCode InverseSignednessConditionCode(ConditionCode code) 94b1994897Sopenharmony_ci{ 95b1994897Sopenharmony_ci switch (code) { 96b1994897Sopenharmony_ci case ConditionCode::CC_EQ: 97b1994897Sopenharmony_ci return ConditionCode::CC_EQ; 98b1994897Sopenharmony_ci case ConditionCode::CC_NE: 99b1994897Sopenharmony_ci return ConditionCode::CC_NE; 100b1994897Sopenharmony_ci 101b1994897Sopenharmony_ci case ConditionCode::CC_LT: 102b1994897Sopenharmony_ci return ConditionCode::CC_B; 103b1994897Sopenharmony_ci case ConditionCode::CC_LE: 104b1994897Sopenharmony_ci return ConditionCode::CC_BE; 105b1994897Sopenharmony_ci case ConditionCode::CC_GT: 106b1994897Sopenharmony_ci return ConditionCode::CC_A; 107b1994897Sopenharmony_ci case ConditionCode::CC_GE: 108b1994897Sopenharmony_ci return ConditionCode::CC_AE; 109b1994897Sopenharmony_ci 110b1994897Sopenharmony_ci case ConditionCode::CC_B: 111b1994897Sopenharmony_ci return ConditionCode::CC_LT; 112b1994897Sopenharmony_ci case ConditionCode::CC_BE: 113b1994897Sopenharmony_ci return ConditionCode::CC_LE; 114b1994897Sopenharmony_ci case ConditionCode::CC_A: 115b1994897Sopenharmony_ci return ConditionCode::CC_GT; 116b1994897Sopenharmony_ci case ConditionCode::CC_AE: 117b1994897Sopenharmony_ci return ConditionCode::CC_GE; 118b1994897Sopenharmony_ci 119b1994897Sopenharmony_ci case ConditionCode::CC_TST_EQ: 120b1994897Sopenharmony_ci return ConditionCode::CC_TST_EQ; 121b1994897Sopenharmony_ci case ConditionCode::CC_TST_NE: 122b1994897Sopenharmony_ci return ConditionCode::CC_TST_NE; 123b1994897Sopenharmony_ci 124b1994897Sopenharmony_ci default: 125b1994897Sopenharmony_ci UNREACHABLE(); 126b1994897Sopenharmony_ci } 127b1994897Sopenharmony_ci} 128b1994897Sopenharmony_ci 129b1994897Sopenharmony_ciinline bool IsSignedConditionCode(ConditionCode code) 130b1994897Sopenharmony_ci{ 131b1994897Sopenharmony_ci switch (code) { 132b1994897Sopenharmony_ci case ConditionCode::CC_LT: 133b1994897Sopenharmony_ci case ConditionCode::CC_LE: 134b1994897Sopenharmony_ci case ConditionCode::CC_GT: 135b1994897Sopenharmony_ci case ConditionCode::CC_GE: 136b1994897Sopenharmony_ci return true; 137b1994897Sopenharmony_ci 138b1994897Sopenharmony_ci case ConditionCode::CC_EQ: 139b1994897Sopenharmony_ci case ConditionCode::CC_NE: 140b1994897Sopenharmony_ci case ConditionCode::CC_B: 141b1994897Sopenharmony_ci case ConditionCode::CC_BE: 142b1994897Sopenharmony_ci case ConditionCode::CC_A: 143b1994897Sopenharmony_ci case ConditionCode::CC_AE: 144b1994897Sopenharmony_ci case ConditionCode::CC_TST_EQ: 145b1994897Sopenharmony_ci case ConditionCode::CC_TST_NE: 146b1994897Sopenharmony_ci return false; 147b1994897Sopenharmony_ci 148b1994897Sopenharmony_ci default: 149b1994897Sopenharmony_ci UNREACHABLE(); 150b1994897Sopenharmony_ci } 151b1994897Sopenharmony_ci} 152b1994897Sopenharmony_ci 153b1994897Sopenharmony_ciinline ConditionCode SwapOperandsConditionCode(ConditionCode code) 154b1994897Sopenharmony_ci{ 155b1994897Sopenharmony_ci switch (code) { 156b1994897Sopenharmony_ci case ConditionCode::CC_EQ: 157b1994897Sopenharmony_ci case ConditionCode::CC_NE: 158b1994897Sopenharmony_ci return code; 159b1994897Sopenharmony_ci default: 160b1994897Sopenharmony_ci UNREACHABLE(); 161b1994897Sopenharmony_ci } 162b1994897Sopenharmony_ci} 163b1994897Sopenharmony_ci 164b1994897Sopenharmony_cienum class Opcode { 165b1994897Sopenharmony_ci INVALID = -1, 166b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 167b1994897Sopenharmony_ci#define INST_DEF(opcode, ...) opcode, 168b1994897Sopenharmony_ci OPCODE_LIST(INST_DEF) 169b1994897Sopenharmony_ci 170b1994897Sopenharmony_ci#undef INST_DEF 171b1994897Sopenharmony_ci NUM_OPCODES 172b1994897Sopenharmony_ci}; 173b1994897Sopenharmony_ci 174b1994897Sopenharmony_ci/** 175b1994897Sopenharmony_ci * Convert opcode to its string representation 176b1994897Sopenharmony_ci */ 177b1994897Sopenharmony_ciconstexpr std::array<const char *const, static_cast<size_t>(Opcode::NUM_OPCODES)> OPCODE_NAMES = { 178b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 179b1994897Sopenharmony_ci#define INST_DEF(opcode, ...) #opcode, 180b1994897Sopenharmony_ci OPCODE_LIST(INST_DEF) 181b1994897Sopenharmony_ci#undef INST_DEF 182b1994897Sopenharmony_ci}; 183b1994897Sopenharmony_ci 184b1994897Sopenharmony_ciconstexpr const char *GetOpcodeString(Opcode opc) 185b1994897Sopenharmony_ci{ 186b1994897Sopenharmony_ci ASSERT(static_cast<int>(opc) < static_cast<int>(Opcode::NUM_OPCODES)); 187b1994897Sopenharmony_ci return OPCODE_NAMES[static_cast<int>(opc)]; 188b1994897Sopenharmony_ci} 189b1994897Sopenharmony_ci 190b1994897Sopenharmony_ci/** 191b1994897Sopenharmony_ci * Instruction flags. See `instrutions.yaml` section `flags` for more information. 192b1994897Sopenharmony_ci */ 193b1994897Sopenharmony_cinamespace inst_flags { 194b1994897Sopenharmony_cinamespace internal { 195b1994897Sopenharmony_cienum FlagsIndex { 196b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 197b1994897Sopenharmony_ci#define FLAG_DEF(flag) flag##_INDEX, 198b1994897Sopenharmony_ci FLAGS_LIST(FLAG_DEF) 199b1994897Sopenharmony_ci#undef FLAG_DEF 200b1994897Sopenharmony_ci FLAGS_COUNT 201b1994897Sopenharmony_ci}; 202b1994897Sopenharmony_ci} // namespace internal 203b1994897Sopenharmony_ci 204b1994897Sopenharmony_cienum Flags : uint32_t { 205b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 206b1994897Sopenharmony_ci#define FLAG_DEF(flag) flag = (1U << internal::flag##_INDEX), 207b1994897Sopenharmony_ci FLAGS_LIST(FLAG_DEF) 208b1994897Sopenharmony_ci#undef FLAG_DEF 209b1994897Sopenharmony_ci FLAGS_COUNT = internal::FLAGS_COUNT, 210b1994897Sopenharmony_ci NONE = 0 211b1994897Sopenharmony_ci}; 212b1994897Sopenharmony_ci 213b1994897Sopenharmony_ciinline constexpr uintptr_t GetFlagsMask(Opcode opcode) 214b1994897Sopenharmony_ci{ 215b1994897Sopenharmony_ci#define INST_DEF(OPCODE, BASE, FLAGS) FLAGS, // NOLINT(cppcoreguidelines-macro-usage) 216b1994897Sopenharmony_ci // NOLINTNEXTLINE(hicpp-signed-bitwise) 217b1994897Sopenharmony_ci constexpr std::array<uintptr_t, static_cast<int>(Opcode::NUM_OPCODES)> INST_FLAGS_TABLE = {OPCODE_LIST(INST_DEF)}; 218b1994897Sopenharmony_ci#undef INST_DEF 219b1994897Sopenharmony_ci return INST_FLAGS_TABLE[static_cast<size_t>(opcode)]; 220b1994897Sopenharmony_ci} 221b1994897Sopenharmony_ci} // namespace inst_flags 222b1994897Sopenharmony_ci 223b1994897Sopenharmony_ci#ifndef NDEBUG 224b1994897Sopenharmony_cinamespace inst_modes { 225b1994897Sopenharmony_cinamespace internal { 226b1994897Sopenharmony_cienum ModeIndex { 227b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 228b1994897Sopenharmony_ci#define MODE_DEF(mode) mode##_INDEX, 229b1994897Sopenharmony_ci MODES_LIST(MODE_DEF) 230b1994897Sopenharmony_ci#undef MODE_DEF 231b1994897Sopenharmony_ci MODES_COUNT 232b1994897Sopenharmony_ci}; 233b1994897Sopenharmony_ci} // namespace internal 234b1994897Sopenharmony_ci 235b1994897Sopenharmony_cienum Mode : uint8_t { 236b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 237b1994897Sopenharmony_ci#define MODE_DEF(mode) mode = (1U << internal::mode##_INDEX), 238b1994897Sopenharmony_ci MODES_LIST(MODE_DEF) 239b1994897Sopenharmony_ci#undef MODE_DEF 240b1994897Sopenharmony_ci MODES_COUNT = internal::MODES_COUNT, 241b1994897Sopenharmony_ci}; 242b1994897Sopenharmony_ci 243b1994897Sopenharmony_ciinline constexpr uint8_t GetModesMask(Opcode opcode) 244b1994897Sopenharmony_ci{ 245b1994897Sopenharmony_ci // NOLINTNEXTLINE(hicpp-signed-bitwise) 246b1994897Sopenharmony_ci constexpr std::array<uint8_t, static_cast<int>(Opcode::NUM_OPCODES)> INST_MODES_TABLE = {INST_MODES_LIST}; 247b1994897Sopenharmony_ci return INST_MODES_TABLE[static_cast<size_t>(opcode)]; 248b1994897Sopenharmony_ci} 249b1994897Sopenharmony_ci} // namespace inst_modes 250b1994897Sopenharmony_ci#endif 251b1994897Sopenharmony_ci 252b1994897Sopenharmony_cinamespace internal { 253b1994897Sopenharmony_ciinline constexpr std::array<const char *, ShiftType::INVALID_SHIFT + 1> SHIFT_TYPE_NAMES = {"LSL", "LSR", "ASR", "ROR", 254b1994897Sopenharmony_ci "INVALID"}; 255b1994897Sopenharmony_ci} // namespace internal 256b1994897Sopenharmony_ci 257b1994897Sopenharmony_ciinline const char *GetShiftTypeStr(ShiftType type) 258b1994897Sopenharmony_ci{ 259b1994897Sopenharmony_ci ASSERT(type <= INVALID_SHIFT); 260b1994897Sopenharmony_ci return internal::SHIFT_TYPE_NAMES[type]; 261b1994897Sopenharmony_ci} 262b1994897Sopenharmony_ci 263b1994897Sopenharmony_ci/** 264b1994897Sopenharmony_ci * Describes type of the object produced by an instruction. 265b1994897Sopenharmony_ci */ 266b1994897Sopenharmony_ciclass ObjectTypeInfo { 267b1994897Sopenharmony_cipublic: 268b1994897Sopenharmony_ci using ClassType = RuntimeInterface::ClassPtr; 269b1994897Sopenharmony_ci 270b1994897Sopenharmony_ci ObjectTypeInfo() = default; 271b1994897Sopenharmony_ci explicit ObjectTypeInfo(ClassType v) : class_(v) {} 272b1994897Sopenharmony_ci 273b1994897Sopenharmony_ci // NOLINTNEXTLINE(google-explicit-constructor) 274b1994897Sopenharmony_ci operator bool() const 275b1994897Sopenharmony_ci { 276b1994897Sopenharmony_ci return class_ != ClassType(); 277b1994897Sopenharmony_ci } 278b1994897Sopenharmony_ci 279b1994897Sopenharmony_ci ClassType GetClass() const 280b1994897Sopenharmony_ci { 281b1994897Sopenharmony_ci return class_; 282b1994897Sopenharmony_ci } 283b1994897Sopenharmony_ci 284b1994897Sopenharmony_ci bool IsValid() const 285b1994897Sopenharmony_ci { 286b1994897Sopenharmony_ci return class_ != ClassType {}; 287b1994897Sopenharmony_ci } 288b1994897Sopenharmony_ci 289b1994897Sopenharmony_ciprivate: 290b1994897Sopenharmony_ci ClassType class_ {}; 291b1994897Sopenharmony_ci}; 292b1994897Sopenharmony_ci 293b1994897Sopenharmony_ci/** 294b1994897Sopenharmony_ci * Class for storing panda bytecode's virtual register 295b1994897Sopenharmony_ci */ 296b1994897Sopenharmony_ciclass VirtualRegister final { 297b1994897Sopenharmony_cipublic: 298b1994897Sopenharmony_ci using ValueType = uint16_t; 299b1994897Sopenharmony_ci static constexpr unsigned BITS_FOR_VREG = (sizeof(ValueType) * BITS_PER_BYTE) - 1; 300b1994897Sopenharmony_ci static constexpr ValueType INVALID = std::numeric_limits<ValueType>::max(); 301b1994897Sopenharmony_ci 302b1994897Sopenharmony_ci VirtualRegister() = default; 303b1994897Sopenharmony_ci explicit VirtualRegister(uint16_t v, bool is_acc) : value_(v) 304b1994897Sopenharmony_ci { 305b1994897Sopenharmony_ci IsAccFlag::Set(is_acc, &value_); 306b1994897Sopenharmony_ci } 307b1994897Sopenharmony_ci 308b1994897Sopenharmony_ci explicit operator uint16_t() const 309b1994897Sopenharmony_ci { 310b1994897Sopenharmony_ci return value_; 311b1994897Sopenharmony_ci } 312b1994897Sopenharmony_ci 313b1994897Sopenharmony_ci uint16_t Value() const 314b1994897Sopenharmony_ci { 315b1994897Sopenharmony_ci return ValueField::Get(value_); 316b1994897Sopenharmony_ci } 317b1994897Sopenharmony_ci 318b1994897Sopenharmony_ci bool IsAccumulator() const 319b1994897Sopenharmony_ci { 320b1994897Sopenharmony_ci return IsAccFlag::Get(value_); 321b1994897Sopenharmony_ci } 322b1994897Sopenharmony_ci 323b1994897Sopenharmony_ciprivate: 324b1994897Sopenharmony_ci uint16_t value_ {INVALID}; 325b1994897Sopenharmony_ci 326b1994897Sopenharmony_ci using ValueField = BitField<unsigned, 0, BITS_FOR_VREG>; 327b1994897Sopenharmony_ci using IsAccFlag = ValueField::NextFlag; 328b1994897Sopenharmony_ci}; 329b1994897Sopenharmony_ci 330b1994897Sopenharmony_ci// How many bits will be used in Inst's bit fields for number of inputs. 331b1994897Sopenharmony_ciconstexpr size_t BITS_PER_INPUTS_NUM = 3; 332b1994897Sopenharmony_ci// Maximum number of static inputs 333b1994897Sopenharmony_ciconstexpr size_t MAX_STATIC_INPUTS = (1U << BITS_PER_INPUTS_NUM) - 1; 334b1994897Sopenharmony_ci 335b1994897Sopenharmony_ci/** 336b1994897Sopenharmony_ci * Currently Input class is just a wrapper for the Inst class. 337b1994897Sopenharmony_ci */ 338b1994897Sopenharmony_ciclass Input final { 339b1994897Sopenharmony_cipublic: 340b1994897Sopenharmony_ci Input() = default; 341b1994897Sopenharmony_ci explicit Input(Inst *inst) : inst_(inst) {} 342b1994897Sopenharmony_ci 343b1994897Sopenharmony_ci Inst *GetInst() 344b1994897Sopenharmony_ci { 345b1994897Sopenharmony_ci return inst_; 346b1994897Sopenharmony_ci } 347b1994897Sopenharmony_ci const Inst *GetInst() const 348b1994897Sopenharmony_ci { 349b1994897Sopenharmony_ci return inst_; 350b1994897Sopenharmony_ci } 351b1994897Sopenharmony_ci 352b1994897Sopenharmony_ci static inline uint8_t GetPadding(Arch arch, uint32_t inputs_count) 353b1994897Sopenharmony_ci { 354b1994897Sopenharmony_ci return static_cast<uint8_t>(!Is64BitsArch(arch) && inputs_count % 2U == 1U); 355b1994897Sopenharmony_ci } 356b1994897Sopenharmony_ci 357b1994897Sopenharmony_ciprivate: 358b1994897Sopenharmony_ci Inst *inst_ {nullptr}; 359b1994897Sopenharmony_ci}; 360b1994897Sopenharmony_ci 361b1994897Sopenharmony_ci/** 362b1994897Sopenharmony_ci * User is a intrusive list node, thus it stores pointers to next and previous users. 363b1994897Sopenharmony_ci * Also user has properties value to determine owner instruction and corresponding index of the input. 364b1994897Sopenharmony_ci */ 365b1994897Sopenharmony_ciclass User final { 366b1994897Sopenharmony_cipublic: 367b1994897Sopenharmony_ci User() = default; 368b1994897Sopenharmony_ci User(bool is_static, unsigned index, unsigned size) 369b1994897Sopenharmony_ci : properties_(IsStaticFlag::Encode(is_static) | IndexField::Encode(index) | SizeField::Encode(size) | 370b1994897Sopenharmony_ci BbNumField::Encode(BbNumField::MaxValue())) 371b1994897Sopenharmony_ci { 372b1994897Sopenharmony_ci ASSERT(index < 1U << (BITS_FOR_INDEX - 1U)); 373b1994897Sopenharmony_ci ASSERT(size < 1U << (BITS_FOR_SIZE - 1U)); 374b1994897Sopenharmony_ci } 375b1994897Sopenharmony_ci ~User() = default; 376b1994897Sopenharmony_ci 377b1994897Sopenharmony_ci // Copy/move semantic is disabled because we use tricky pointer arithmetic based on 'this' value 378b1994897Sopenharmony_ci NO_COPY_SEMANTIC(User); 379b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(User); 380b1994897Sopenharmony_ci 381b1994897Sopenharmony_ci Inst *GetInst(); 382b1994897Sopenharmony_ci const Inst *GetInst() const 383b1994897Sopenharmony_ci { 384b1994897Sopenharmony_ci return const_cast<User *>(this)->GetInst(); 385b1994897Sopenharmony_ci } 386b1994897Sopenharmony_ci 387b1994897Sopenharmony_ci Inst *GetInput(); 388b1994897Sopenharmony_ci const Inst *GetInput() const; 389b1994897Sopenharmony_ci 390b1994897Sopenharmony_ci bool IsDynamic() const 391b1994897Sopenharmony_ci { 392b1994897Sopenharmony_ci return !IsStaticFlag::Decode(properties_); 393b1994897Sopenharmony_ci } 394b1994897Sopenharmony_ci unsigned GetIndex() const 395b1994897Sopenharmony_ci { 396b1994897Sopenharmony_ci return IndexField::Decode(properties_); 397b1994897Sopenharmony_ci } 398b1994897Sopenharmony_ci unsigned GetSize() const 399b1994897Sopenharmony_ci { 400b1994897Sopenharmony_ci return SizeField::Decode(properties_); 401b1994897Sopenharmony_ci } 402b1994897Sopenharmony_ci 403b1994897Sopenharmony_ci VirtualRegister GetVirtualRegister() const 404b1994897Sopenharmony_ci { 405b1994897Sopenharmony_ci ASSERT(IsDynamic()); 406b1994897Sopenharmony_ci return VirtualRegister(VregField::Decode(properties_), IsAccFlag::Decode(properties_)); 407b1994897Sopenharmony_ci } 408b1994897Sopenharmony_ci 409b1994897Sopenharmony_ci void SetVirtualRegister(VirtualRegister reg) 410b1994897Sopenharmony_ci { 411b1994897Sopenharmony_ci static_assert(sizeof(reg) <= sizeof(uintptr_t), "Consider passing the register by reference"); 412b1994897Sopenharmony_ci ASSERT(IsDynamic()); 413b1994897Sopenharmony_ci VregField::Set(reg.Value(), &properties_); 414b1994897Sopenharmony_ci IsAccFlag::Set(reg.IsAccumulator(), &properties_); 415b1994897Sopenharmony_ci } 416b1994897Sopenharmony_ci 417b1994897Sopenharmony_ci uint32_t GetBbNum() const 418b1994897Sopenharmony_ci { 419b1994897Sopenharmony_ci ASSERT(IsDynamic()); 420b1994897Sopenharmony_ci return BbNumField::Decode(properties_); 421b1994897Sopenharmony_ci } 422b1994897Sopenharmony_ci 423b1994897Sopenharmony_ci void SetBbNum(uint32_t bb_num) 424b1994897Sopenharmony_ci { 425b1994897Sopenharmony_ci ASSERT(IsDynamic()); 426b1994897Sopenharmony_ci BbNumField::Set(bb_num, &properties_); 427b1994897Sopenharmony_ci } 428b1994897Sopenharmony_ci 429b1994897Sopenharmony_ci auto GetNext() const 430b1994897Sopenharmony_ci { 431b1994897Sopenharmony_ci return next_; 432b1994897Sopenharmony_ci } 433b1994897Sopenharmony_ci 434b1994897Sopenharmony_ci auto GetPrev() const 435b1994897Sopenharmony_ci { 436b1994897Sopenharmony_ci return prev_; 437b1994897Sopenharmony_ci } 438b1994897Sopenharmony_ci 439b1994897Sopenharmony_ci void SetNext(User *next) 440b1994897Sopenharmony_ci { 441b1994897Sopenharmony_ci next_ = next; 442b1994897Sopenharmony_ci } 443b1994897Sopenharmony_ci 444b1994897Sopenharmony_ci void SetPrev(User *prev) 445b1994897Sopenharmony_ci { 446b1994897Sopenharmony_ci prev_ = prev; 447b1994897Sopenharmony_ci } 448b1994897Sopenharmony_ci 449b1994897Sopenharmony_ci void Remove() 450b1994897Sopenharmony_ci { 451b1994897Sopenharmony_ci if (prev_ != nullptr) { 452b1994897Sopenharmony_ci prev_->next_ = next_; 453b1994897Sopenharmony_ci } 454b1994897Sopenharmony_ci if (next_ != nullptr) { 455b1994897Sopenharmony_ci next_->prev_ = prev_; 456b1994897Sopenharmony_ci } 457b1994897Sopenharmony_ci } 458b1994897Sopenharmony_ci 459b1994897Sopenharmony_ciprivate: 460b1994897Sopenharmony_ci static constexpr unsigned BITS_FOR_INDEX = 21; 461b1994897Sopenharmony_ci static constexpr unsigned BITS_FOR_SIZE = BITS_FOR_INDEX; 462b1994897Sopenharmony_ci static constexpr unsigned BITS_FOR_BB_NUM = 20; 463b1994897Sopenharmony_ci using IndexField = BitField<unsigned, 0, BITS_FOR_INDEX>; 464b1994897Sopenharmony_ci using SizeField = IndexField::NextField<unsigned, BITS_FOR_SIZE>; 465b1994897Sopenharmony_ci using IsStaticFlag = SizeField::NextFlag; 466b1994897Sopenharmony_ci 467b1994897Sopenharmony_ci using BbNumField = IsStaticFlag::NextField<uint32_t, BITS_FOR_BB_NUM>; 468b1994897Sopenharmony_ci 469b1994897Sopenharmony_ci using VregField = IsStaticFlag::NextField<unsigned, VirtualRegister::BITS_FOR_VREG>; 470b1994897Sopenharmony_ci using IsAccFlag = VregField::NextFlag; 471b1994897Sopenharmony_ci 472b1994897Sopenharmony_ci uint64_t properties_ {0}; 473b1994897Sopenharmony_ci User *next_ {nullptr}; 474b1994897Sopenharmony_ci User *prev_ {nullptr}; 475b1994897Sopenharmony_ci}; 476b1994897Sopenharmony_ci 477b1994897Sopenharmony_ci/** 478b1994897Sopenharmony_ci * List of users. Intended for range loop. 479b1994897Sopenharmony_ci * @tparam T should be User or const User 480b1994897Sopenharmony_ci */ 481b1994897Sopenharmony_citemplate <typename T> 482b1994897Sopenharmony_ciclass UserList { 483b1994897Sopenharmony_ci template <typename U> 484b1994897Sopenharmony_ci struct UserIterator { 485b1994897Sopenharmony_ci UserIterator() = default; 486b1994897Sopenharmony_ci explicit UserIterator(U *u) : user_(u) {} 487b1994897Sopenharmony_ci 488b1994897Sopenharmony_ci UserIterator &operator++() 489b1994897Sopenharmony_ci { 490b1994897Sopenharmony_ci user_ = user_->GetNext(); 491b1994897Sopenharmony_ci return *this; 492b1994897Sopenharmony_ci } 493b1994897Sopenharmony_ci bool operator!=(const UserIterator &other) 494b1994897Sopenharmony_ci { 495b1994897Sopenharmony_ci return user_ != other.user_; 496b1994897Sopenharmony_ci } 497b1994897Sopenharmony_ci U &operator*() 498b1994897Sopenharmony_ci { 499b1994897Sopenharmony_ci return *user_; 500b1994897Sopenharmony_ci } 501b1994897Sopenharmony_ci U *operator->() 502b1994897Sopenharmony_ci { 503b1994897Sopenharmony_ci return user_; 504b1994897Sopenharmony_ci } 505b1994897Sopenharmony_ci 506b1994897Sopenharmony_ci private: 507b1994897Sopenharmony_ci U *user_ {nullptr}; 508b1994897Sopenharmony_ci }; 509b1994897Sopenharmony_ci 510b1994897Sopenharmony_cipublic: 511b1994897Sopenharmony_ci using Iterator = UserIterator<T>; 512b1994897Sopenharmony_ci using ConstIterator = UserIterator<const T>; 513b1994897Sopenharmony_ci using PointerType = std::conditional_t<std::is_const_v<T>, T *const *, T **>; 514b1994897Sopenharmony_ci 515b1994897Sopenharmony_ci explicit UserList(PointerType head) : head_(head) {} 516b1994897Sopenharmony_ci 517b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-identifier-naming) 518b1994897Sopenharmony_ci Iterator begin() 519b1994897Sopenharmony_ci { 520b1994897Sopenharmony_ci return Iterator(*head_); 521b1994897Sopenharmony_ci } 522b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-identifier-naming) 523b1994897Sopenharmony_ci Iterator end() 524b1994897Sopenharmony_ci { 525b1994897Sopenharmony_ci return Iterator(nullptr); 526b1994897Sopenharmony_ci } 527b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-identifier-naming) 528b1994897Sopenharmony_ci ConstIterator begin() const 529b1994897Sopenharmony_ci { 530b1994897Sopenharmony_ci return ConstIterator(*head_); 531b1994897Sopenharmony_ci } 532b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-identifier-naming) 533b1994897Sopenharmony_ci ConstIterator end() const 534b1994897Sopenharmony_ci { 535b1994897Sopenharmony_ci return ConstIterator(nullptr); 536b1994897Sopenharmony_ci } 537b1994897Sopenharmony_ci bool Empty() const 538b1994897Sopenharmony_ci { 539b1994897Sopenharmony_ci return *head_ == nullptr; 540b1994897Sopenharmony_ci } 541b1994897Sopenharmony_ci T &Front() 542b1994897Sopenharmony_ci { 543b1994897Sopenharmony_ci return **head_; 544b1994897Sopenharmony_ci } 545b1994897Sopenharmony_ci const T &Front() const 546b1994897Sopenharmony_ci { 547b1994897Sopenharmony_ci return **head_; 548b1994897Sopenharmony_ci } 549b1994897Sopenharmony_ci 550b1994897Sopenharmony_ciprivate: 551b1994897Sopenharmony_ci PointerType head_ {nullptr}; 552b1994897Sopenharmony_ci}; 553b1994897Sopenharmony_ci 554b1994897Sopenharmony_ciinline bool operator==(const User &lhs, const User &rhs) 555b1994897Sopenharmony_ci{ 556b1994897Sopenharmony_ci return lhs.GetInst() == rhs.GetInst(); 557b1994897Sopenharmony_ci} 558b1994897Sopenharmony_ci 559b1994897Sopenharmony_ci/** 560b1994897Sopenharmony_ci * Operands class for instructions with fixed inputs count. 561b1994897Sopenharmony_ci * Actually, this class do absolutely nothing except that we can get sizeof of it when allocating memory. 562b1994897Sopenharmony_ci */ 563b1994897Sopenharmony_citemplate <int N> 564b1994897Sopenharmony_cistruct Operands { 565b1994897Sopenharmony_ci static_assert(N < MAX_STATIC_INPUTS, "Invalid inputs number"); 566b1994897Sopenharmony_ci 567b1994897Sopenharmony_ci std::array<User, N> users; 568b1994897Sopenharmony_ci std::array<Input, N> inputs; 569b1994897Sopenharmony_ci}; 570b1994897Sopenharmony_ci 571b1994897Sopenharmony_ci/** 572b1994897Sopenharmony_ci * Specialized version for instructions with variable inputs count. 573b1994897Sopenharmony_ci * Users and inputs are stored outside of this class. 574b1994897Sopenharmony_ci */ 575b1994897Sopenharmony_ciclass DynamicOperands { 576b1994897Sopenharmony_cipublic: 577b1994897Sopenharmony_ci explicit DynamicOperands(ArenaAllocator *allocator) : allocator_(allocator) {} 578b1994897Sopenharmony_ci 579b1994897Sopenharmony_ci User *Users() 580b1994897Sopenharmony_ci { 581b1994897Sopenharmony_ci return users_; 582b1994897Sopenharmony_ci } 583b1994897Sopenharmony_ci 584b1994897Sopenharmony_ci Input *Inputs() 585b1994897Sopenharmony_ci { 586b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 587b1994897Sopenharmony_ci return reinterpret_cast<Input *>(users_ + capacity_) + 1; 588b1994897Sopenharmony_ci } 589b1994897Sopenharmony_ci 590b1994897Sopenharmony_ci /// Append new input (and user accordingly) 591b1994897Sopenharmony_ci unsigned Append(Inst *inst); 592b1994897Sopenharmony_ci 593b1994897Sopenharmony_ci /// Remove input and user with index `index`. 594b1994897Sopenharmony_ci void Remove(unsigned index); 595b1994897Sopenharmony_ci 596b1994897Sopenharmony_ci /// Reallocate inputs/users storage to a new one with specified capacity. 597b1994897Sopenharmony_ci void Reallocate(size_t new_capacity = 0); 598b1994897Sopenharmony_ci 599b1994897Sopenharmony_ci /// Get instruction to which these operands belongs to. 600b1994897Sopenharmony_ci Inst *GetOwnerInst() const 601b1994897Sopenharmony_ci { 602b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 603b1994897Sopenharmony_ci return reinterpret_cast<Inst *>(const_cast<DynamicOperands *>(this) + 1); 604b1994897Sopenharmony_ci } 605b1994897Sopenharmony_ci 606b1994897Sopenharmony_ci User *GetUser(unsigned index) 607b1994897Sopenharmony_ci { 608b1994897Sopenharmony_ci CHECK_GE(capacity_ - 1, index); 609b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 610b1994897Sopenharmony_ci return &users_[capacity_ - index - 1]; 611b1994897Sopenharmony_ci } 612b1994897Sopenharmony_ci 613b1994897Sopenharmony_ci Input *GetInput(unsigned index) 614b1994897Sopenharmony_ci { 615b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 616b1994897Sopenharmony_ci return &Inputs()[index]; 617b1994897Sopenharmony_ci } 618b1994897Sopenharmony_ci 619b1994897Sopenharmony_ci void SetInput(unsigned index, Input input) 620b1994897Sopenharmony_ci { 621b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 622b1994897Sopenharmony_ci Inputs()[index] = input; 623b1994897Sopenharmony_ci } 624b1994897Sopenharmony_ci 625b1994897Sopenharmony_ci size_t Size() const 626b1994897Sopenharmony_ci { 627b1994897Sopenharmony_ci return size_; 628b1994897Sopenharmony_ci } 629b1994897Sopenharmony_ci 630b1994897Sopenharmony_ciprivate: 631b1994897Sopenharmony_ci User *users_ {nullptr}; 632b1994897Sopenharmony_ci size_t size_ {0}; 633b1994897Sopenharmony_ci size_t capacity_ {0}; 634b1994897Sopenharmony_ci ArenaAllocator *allocator_ {nullptr}; 635b1994897Sopenharmony_ci}; 636b1994897Sopenharmony_ci 637b1994897Sopenharmony_ci/** 638b1994897Sopenharmony_ci * Base class for all instructions, should not be instantiated directly 639b1994897Sopenharmony_ci */ 640b1994897Sopenharmony_ciclass InstBase { 641b1994897Sopenharmony_ci NO_COPY_SEMANTIC(InstBase); 642b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(InstBase); 643b1994897Sopenharmony_ci 644b1994897Sopenharmony_cipublic: 645b1994897Sopenharmony_ci virtual ~InstBase() = default; 646b1994897Sopenharmony_ci 647b1994897Sopenharmony_cipublic: 648b1994897Sopenharmony_ci ALWAYS_INLINE void operator delete([[maybe_unused]] void *unused, [[maybe_unused]] size_t size) 649b1994897Sopenharmony_ci { 650b1994897Sopenharmony_ci UNREACHABLE(); 651b1994897Sopenharmony_ci } 652b1994897Sopenharmony_ci ALWAYS_INLINE void *operator new([[maybe_unused]] size_t size, void *ptr) noexcept 653b1994897Sopenharmony_ci { 654b1994897Sopenharmony_ci return ptr; 655b1994897Sopenharmony_ci } 656b1994897Sopenharmony_ci ALWAYS_INLINE void operator delete([[maybe_unused]] void *unused1, [[maybe_unused]] void *unused2) noexcept {} 657b1994897Sopenharmony_ci 658b1994897Sopenharmony_ci void *operator new([[maybe_unused]] size_t size) = delete; 659b1994897Sopenharmony_ci 660b1994897Sopenharmony_ciprotected: 661b1994897Sopenharmony_ci InstBase() = default; 662b1994897Sopenharmony_ci}; 663b1994897Sopenharmony_ci 664b1994897Sopenharmony_ci/** 665b1994897Sopenharmony_ci * Base instruction class 666b1994897Sopenharmony_ci */ 667b1994897Sopenharmony_ciclass Inst : public MarkerSet, public InstBase { 668b1994897Sopenharmony_cipublic: 669b1994897Sopenharmony_ci /** 670b1994897Sopenharmony_ci * Create new instruction. All instructions must be created with this method. 671b1994897Sopenharmony_ci * It allocates additional space before Inst object for def-use structures. 672b1994897Sopenharmony_ci * 673b1994897Sopenharmony_ci * @tparam InstType - concrete type of instruction, shall be derived from Inst 674b1994897Sopenharmony_ci * @tparam Args - constructor arguments types 675b1994897Sopenharmony_ci * @param allocator - allocator for memory allocating 676b1994897Sopenharmony_ci * @param args - constructor arguments 677b1994897Sopenharmony_ci * @return - new instruction 678b1994897Sopenharmony_ci */ 679b1994897Sopenharmony_ci template <typename InstType, typename... Args> 680b1994897Sopenharmony_ci [[nodiscard]] static InstType *New(ArenaAllocator *allocator, Args &&... args); 681b1994897Sopenharmony_ci 682b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 683b1994897Sopenharmony_ci#define INST_DEF(opcode, base, ...) inline const base *CastTo##opcode() const; 684b1994897Sopenharmony_ci OPCODE_LIST(INST_DEF) 685b1994897Sopenharmony_ci#undef INST_DEF 686b1994897Sopenharmony_ci 687b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 688b1994897Sopenharmony_ci#define INST_DEF(opcode, base, ...) inline base *CastTo##opcode(); 689b1994897Sopenharmony_ci OPCODE_LIST(INST_DEF) 690b1994897Sopenharmony_ci#undef INST_DEF 691b1994897Sopenharmony_ci 692b1994897Sopenharmony_ci // Methods for instruction chaining inside basic blocks. 693b1994897Sopenharmony_ci Inst *GetNext() 694b1994897Sopenharmony_ci { 695b1994897Sopenharmony_ci return next_; 696b1994897Sopenharmony_ci } 697b1994897Sopenharmony_ci const Inst *GetNext() const 698b1994897Sopenharmony_ci { 699b1994897Sopenharmony_ci return next_; 700b1994897Sopenharmony_ci } 701b1994897Sopenharmony_ci Inst *GetPrev() 702b1994897Sopenharmony_ci { 703b1994897Sopenharmony_ci return prev_; 704b1994897Sopenharmony_ci } 705b1994897Sopenharmony_ci const Inst *GetPrev() const 706b1994897Sopenharmony_ci { 707b1994897Sopenharmony_ci return prev_; 708b1994897Sopenharmony_ci } 709b1994897Sopenharmony_ci void SetNext(Inst *next) 710b1994897Sopenharmony_ci { 711b1994897Sopenharmony_ci next_ = next; 712b1994897Sopenharmony_ci } 713b1994897Sopenharmony_ci void SetPrev(Inst *prev) 714b1994897Sopenharmony_ci { 715b1994897Sopenharmony_ci prev_ = prev; 716b1994897Sopenharmony_ci } 717b1994897Sopenharmony_ci 718b1994897Sopenharmony_ci // Id accessors 719b1994897Sopenharmony_ci auto GetId() const 720b1994897Sopenharmony_ci { 721b1994897Sopenharmony_ci return id_; 722b1994897Sopenharmony_ci } 723b1994897Sopenharmony_ci void SetId(int id) 724b1994897Sopenharmony_ci { 725b1994897Sopenharmony_ci id_ = id; 726b1994897Sopenharmony_ci } 727b1994897Sopenharmony_ci 728b1994897Sopenharmony_ci auto GetLinearNumber() const 729b1994897Sopenharmony_ci { 730b1994897Sopenharmony_ci return linear_number_; 731b1994897Sopenharmony_ci } 732b1994897Sopenharmony_ci void SetLinearNumber(LinearNumber number) 733b1994897Sopenharmony_ci { 734b1994897Sopenharmony_ci linear_number_ = number; 735b1994897Sopenharmony_ci } 736b1994897Sopenharmony_ci 737b1994897Sopenharmony_ci auto GetCloneNumber() const 738b1994897Sopenharmony_ci { 739b1994897Sopenharmony_ci return clone_number_; 740b1994897Sopenharmony_ci } 741b1994897Sopenharmony_ci void SetCloneNumber(int32_t number) 742b1994897Sopenharmony_ci { 743b1994897Sopenharmony_ci clone_number_ = number; 744b1994897Sopenharmony_ci } 745b1994897Sopenharmony_ci 746b1994897Sopenharmony_ci // Opcode accessors 747b1994897Sopenharmony_ci Opcode GetOpcode() const 748b1994897Sopenharmony_ci { 749b1994897Sopenharmony_ci return opcode_; 750b1994897Sopenharmony_ci } 751b1994897Sopenharmony_ci void SetOpcode(Opcode opcode) 752b1994897Sopenharmony_ci { 753b1994897Sopenharmony_ci opcode_ = opcode; 754b1994897Sopenharmony_ci SetField<FieldFlags>(inst_flags::GetFlagsMask(opcode)); 755b1994897Sopenharmony_ci } 756b1994897Sopenharmony_ci const char *GetOpcodeStr() const 757b1994897Sopenharmony_ci { 758b1994897Sopenharmony_ci return GetOpcodeString(GetOpcode()); 759b1994897Sopenharmony_ci } 760b1994897Sopenharmony_ci 761b1994897Sopenharmony_ci // Bytecode PC accessors 762b1994897Sopenharmony_ci uint32_t GetPc() const 763b1994897Sopenharmony_ci { 764b1994897Sopenharmony_ci return pc_; 765b1994897Sopenharmony_ci } 766b1994897Sopenharmony_ci void SetPc(uint32_t pc) 767b1994897Sopenharmony_ci { 768b1994897Sopenharmony_ci pc_ = pc; 769b1994897Sopenharmony_ci } 770b1994897Sopenharmony_ci 771b1994897Sopenharmony_ci // Type accessors 772b1994897Sopenharmony_ci DataType::Type GetType() const 773b1994897Sopenharmony_ci { 774b1994897Sopenharmony_ci return FieldType::Get(bit_fields_); 775b1994897Sopenharmony_ci } 776b1994897Sopenharmony_ci void SetType(DataType::Type type) 777b1994897Sopenharmony_ci { 778b1994897Sopenharmony_ci FieldType::Set(type, &bit_fields_); 779b1994897Sopenharmony_ci } 780b1994897Sopenharmony_ci bool HasType() const 781b1994897Sopenharmony_ci { 782b1994897Sopenharmony_ci return GetType() != DataType::Type::NO_TYPE; 783b1994897Sopenharmony_ci } 784b1994897Sopenharmony_ci 785b1994897Sopenharmony_ci // Parent basic block accessors 786b1994897Sopenharmony_ci BasicBlock *GetBasicBlock() 787b1994897Sopenharmony_ci { 788b1994897Sopenharmony_ci return bb_; 789b1994897Sopenharmony_ci } 790b1994897Sopenharmony_ci const BasicBlock *GetBasicBlock() const 791b1994897Sopenharmony_ci { 792b1994897Sopenharmony_ci return bb_; 793b1994897Sopenharmony_ci } 794b1994897Sopenharmony_ci void SetBasicBlock(BasicBlock *bb) 795b1994897Sopenharmony_ci { 796b1994897Sopenharmony_ci bb_ = bb; 797b1994897Sopenharmony_ci } 798b1994897Sopenharmony_ci 799b1994897Sopenharmony_ci // Instruction properties getters 800b1994897Sopenharmony_ci bool IsControlFlow() const 801b1994897Sopenharmony_ci { 802b1994897Sopenharmony_ci return GetFlag(inst_flags::CF); 803b1994897Sopenharmony_ci } 804b1994897Sopenharmony_ci 805b1994897Sopenharmony_ci bool IsIntrinsic() const 806b1994897Sopenharmony_ci { 807b1994897Sopenharmony_ci return GetOpcode() == Opcode::Intrinsic; 808b1994897Sopenharmony_ci } 809b1994897Sopenharmony_ci 810b1994897Sopenharmony_ci bool IsCall() const 811b1994897Sopenharmony_ci { 812b1994897Sopenharmony_ci return GetFlag(inst_flags::CALL); 813b1994897Sopenharmony_ci } 814b1994897Sopenharmony_ci 815b1994897Sopenharmony_ci bool IsSpillFill() const 816b1994897Sopenharmony_ci { 817b1994897Sopenharmony_ci return GetOpcode() == Opcode::SpillFill; 818b1994897Sopenharmony_ci } 819b1994897Sopenharmony_ci 820b1994897Sopenharmony_ci bool IsAccRead() const; 821b1994897Sopenharmony_ci bool IsAccWrite() const; 822b1994897Sopenharmony_ci bool CanThrow() const 823b1994897Sopenharmony_ci { 824b1994897Sopenharmony_ci return GetFlag(inst_flags::CAN_THROW); 825b1994897Sopenharmony_ci } 826b1994897Sopenharmony_ci bool RequireState() const 827b1994897Sopenharmony_ci { 828b1994897Sopenharmony_ci return GetFlag(inst_flags::REQUIRE_STATE); 829b1994897Sopenharmony_ci } 830b1994897Sopenharmony_ci // Returns true if the instruction not removable in DCE 831b1994897Sopenharmony_ci bool IsNotRemovable() const 832b1994897Sopenharmony_ci { 833b1994897Sopenharmony_ci return GetFlag(inst_flags::NO_DCE); 834b1994897Sopenharmony_ci } 835b1994897Sopenharmony_ci 836b1994897Sopenharmony_ci // Returns true if the instruction doesn't have destination register 837b1994897Sopenharmony_ci bool NoDest() const 838b1994897Sopenharmony_ci { 839b1994897Sopenharmony_ci return GetFlag(inst_flags::PSEUDO_DST) || GetFlag(inst_flags::NO_DST) || GetType() == DataType::VOID; 840b1994897Sopenharmony_ci } 841b1994897Sopenharmony_ci 842b1994897Sopenharmony_ci bool HasPseudoDestination() const 843b1994897Sopenharmony_ci { 844b1994897Sopenharmony_ci return GetFlag(inst_flags::PSEUDO_DST); 845b1994897Sopenharmony_ci } 846b1994897Sopenharmony_ci 847b1994897Sopenharmony_ci bool HasImplicitRuntimeCall() const 848b1994897Sopenharmony_ci { 849b1994897Sopenharmony_ci return GetFlag(inst_flags::IMPLICIT_RUNTIME_CALL); 850b1994897Sopenharmony_ci } 851b1994897Sopenharmony_ci 852b1994897Sopenharmony_ci bool CanDeoptimize() const 853b1994897Sopenharmony_ci { 854b1994897Sopenharmony_ci return GetFlag(inst_flags::CAN_DEOPTIMIZE); 855b1994897Sopenharmony_ci } 856b1994897Sopenharmony_ci 857b1994897Sopenharmony_ci // Returns true if the instruction is low-level 858b1994897Sopenharmony_ci bool IsLowLevel() const 859b1994897Sopenharmony_ci { 860b1994897Sopenharmony_ci return GetFlag(inst_flags::LOW_LEVEL); 861b1994897Sopenharmony_ci } 862b1994897Sopenharmony_ci 863b1994897Sopenharmony_ci // Returns true if the instruction not hoistable 864b1994897Sopenharmony_ci bool IsNotHoistable() const 865b1994897Sopenharmony_ci { 866b1994897Sopenharmony_ci return GetFlag(inst_flags::NO_HOIST); 867b1994897Sopenharmony_ci } 868b1994897Sopenharmony_ci 869b1994897Sopenharmony_ci // Returns true Cse can't be applied to the instruction 870b1994897Sopenharmony_ci bool IsNotCseApplicable() const 871b1994897Sopenharmony_ci { 872b1994897Sopenharmony_ci return GetFlag(inst_flags::NO_CSE); 873b1994897Sopenharmony_ci } 874b1994897Sopenharmony_ci 875b1994897Sopenharmony_ci // Returns true if opcode can not be moved throught runtime calls (REFERENCE type only) 876b1994897Sopenharmony_ci bool IsRefSpecial() const 877b1994897Sopenharmony_ci { 878b1994897Sopenharmony_ci bool result = GetFlag(inst_flags::REF_SPECIAL); 879b1994897Sopenharmony_ci ASSERT(!result || GetType() == DataType::Type::REFERENCE); 880b1994897Sopenharmony_ci return result; 881b1994897Sopenharmony_ci } 882b1994897Sopenharmony_ci 883b1994897Sopenharmony_ci // Returns true if the instruction is a commutative 884b1994897Sopenharmony_ci bool IsCommutative() const 885b1994897Sopenharmony_ci { 886b1994897Sopenharmony_ci return GetFlag(inst_flags::COMMUTATIVE); 887b1994897Sopenharmony_ci } 888b1994897Sopenharmony_ci 889b1994897Sopenharmony_ci // Returns true if the instruction can be used in if-conversion 890b1994897Sopenharmony_ci bool IsIfConvertable() const 891b1994897Sopenharmony_ci { 892b1994897Sopenharmony_ci return GetFlag(inst_flags::IFCVT); 893b1994897Sopenharmony_ci } 894b1994897Sopenharmony_ci 895b1994897Sopenharmony_ci virtual bool IsPropagateLiveness() const; 896b1994897Sopenharmony_ci 897b1994897Sopenharmony_ci bool RequireRegMap() const; 898b1994897Sopenharmony_ci 899b1994897Sopenharmony_ci ObjectTypeInfo GetObjectTypeInfo() const 900b1994897Sopenharmony_ci { 901b1994897Sopenharmony_ci return object_type_info_; 902b1994897Sopenharmony_ci } 903b1994897Sopenharmony_ci 904b1994897Sopenharmony_ci bool HasObjectTypeInfo() const 905b1994897Sopenharmony_ci { 906b1994897Sopenharmony_ci return object_type_info_.IsValid(); 907b1994897Sopenharmony_ci } 908b1994897Sopenharmony_ci 909b1994897Sopenharmony_ci Inst *GetDataFlowInput(int index) const 910b1994897Sopenharmony_ci { 911b1994897Sopenharmony_ci return GetDataFlowInput(GetInput(index).GetInst()); 912b1994897Sopenharmony_ci } 913b1994897Sopenharmony_ci Inst *GetDataFlowInput(Inst *input_inst) const; 914b1994897Sopenharmony_ci 915b1994897Sopenharmony_ci bool IsPrecedingInSameBlock(const Inst *other) const; 916b1994897Sopenharmony_ci 917b1994897Sopenharmony_ci bool IsDominate(const Inst *other) const; 918b1994897Sopenharmony_ci 919b1994897Sopenharmony_ci bool InSameBlockOrDominate(const Inst *other) const; 920b1994897Sopenharmony_ci 921b1994897Sopenharmony_ci const SaveStateInst *GetSaveState() const 922b1994897Sopenharmony_ci { 923b1994897Sopenharmony_ci return const_cast<Inst *>(this)->GetSaveState(); 924b1994897Sopenharmony_ci } 925b1994897Sopenharmony_ci 926b1994897Sopenharmony_ci SaveStateInst *GetSaveState() 927b1994897Sopenharmony_ci { 928b1994897Sopenharmony_ci if (!RequireState()) { 929b1994897Sopenharmony_ci return nullptr; 930b1994897Sopenharmony_ci } 931b1994897Sopenharmony_ci if (GetInputsCount() == 0) { 932b1994897Sopenharmony_ci return nullptr; 933b1994897Sopenharmony_ci } 934b1994897Sopenharmony_ci auto ss = GetInput(GetInputsCount() - 1).GetInst(); 935b1994897Sopenharmony_ci if (ss->GetOpcode() != Opcode::SaveState) { 936b1994897Sopenharmony_ci return nullptr; 937b1994897Sopenharmony_ci } 938b1994897Sopenharmony_ci return ss->CastToSaveState(); 939b1994897Sopenharmony_ci } 940b1994897Sopenharmony_ci 941b1994897Sopenharmony_ci void SetSaveState(Inst *inst) 942b1994897Sopenharmony_ci { 943b1994897Sopenharmony_ci ASSERT(RequireState()); 944b1994897Sopenharmony_ci SetInput(GetInputsCount() - 1, inst); 945b1994897Sopenharmony_ci } 946b1994897Sopenharmony_ci 947b1994897Sopenharmony_ci bool IsZeroRegInst() const; 948b1994897Sopenharmony_ci 949b1994897Sopenharmony_ci /** 950b1994897Sopenharmony_ci * Return instruction clone 951b1994897Sopenharmony_ci */ 952b1994897Sopenharmony_ci virtual Inst *Clone(const Graph *targetGraph) const; 953b1994897Sopenharmony_ci 954b1994897Sopenharmony_ci uintptr_t GetFlagsMask() const 955b1994897Sopenharmony_ci { 956b1994897Sopenharmony_ci return GetField<FieldFlags>(); 957b1994897Sopenharmony_ci } 958b1994897Sopenharmony_ci 959b1994897Sopenharmony_ci bool GetFlag(inst_flags::Flags flag) const 960b1994897Sopenharmony_ci { 961b1994897Sopenharmony_ci return (GetFlagsMask() & flag) != 0; 962b1994897Sopenharmony_ci } 963b1994897Sopenharmony_ci 964b1994897Sopenharmony_ci void SetFlag(inst_flags::Flags flag) 965b1994897Sopenharmony_ci { 966b1994897Sopenharmony_ci SetField<FieldFlags>(GetFlagsMask() | flag); 967b1994897Sopenharmony_ci } 968b1994897Sopenharmony_ci 969b1994897Sopenharmony_ci void ClearFlag(inst_flags::Flags flag) 970b1994897Sopenharmony_ci { 971b1994897Sopenharmony_ci SetField<FieldFlags>(GetFlagsMask() & ~static_cast<uintptr_t>(flag)); 972b1994897Sopenharmony_ci } 973b1994897Sopenharmony_ci 974b1994897Sopenharmony_ci#ifndef NDEBUG 975b1994897Sopenharmony_ci uint8_t GetModesMask() const 976b1994897Sopenharmony_ci { 977b1994897Sopenharmony_ci return inst_modes::GetModesMask(opcode_); 978b1994897Sopenharmony_ci } 979b1994897Sopenharmony_ci 980b1994897Sopenharmony_ci bool SupportsMode(inst_modes::Mode mode) const 981b1994897Sopenharmony_ci { 982b1994897Sopenharmony_ci return (GetModesMask() & mode) != 0; 983b1994897Sopenharmony_ci } 984b1994897Sopenharmony_ci#endif 985b1994897Sopenharmony_ci 986b1994897Sopenharmony_ci void SetTerminator() 987b1994897Sopenharmony_ci { 988b1994897Sopenharmony_ci SetFlag(inst_flags::Flags::TERMINATOR); 989b1994897Sopenharmony_ci } 990b1994897Sopenharmony_ci 991b1994897Sopenharmony_ci void InsertBefore(Inst *inst); 992b1994897Sopenharmony_ci void InsertAfter(Inst *inst); 993b1994897Sopenharmony_ci 994b1994897Sopenharmony_ci /** 995b1994897Sopenharmony_ci * Return true if instruction has dynamic operands storage. 996b1994897Sopenharmony_ci */ 997b1994897Sopenharmony_ci bool IsOperandsDynamic() const 998b1994897Sopenharmony_ci { 999b1994897Sopenharmony_ci return GetField<InputsCount>() == MAX_STATIC_INPUTS; 1000b1994897Sopenharmony_ci } 1001b1994897Sopenharmony_ci 1002b1994897Sopenharmony_ci /** 1003b1994897Sopenharmony_ci * Add user to the instruction. 1004b1994897Sopenharmony_ci * @param user - pointer to User object 1005b1994897Sopenharmony_ci */ 1006b1994897Sopenharmony_ci void AddUser(User *user) 1007b1994897Sopenharmony_ci { 1008b1994897Sopenharmony_ci ASSERT(user && user->GetInst()); 1009b1994897Sopenharmony_ci user->SetNext(first_user_); 1010b1994897Sopenharmony_ci user->SetPrev(nullptr); 1011b1994897Sopenharmony_ci if (first_user_ != nullptr) { 1012b1994897Sopenharmony_ci ASSERT(first_user_->GetPrev() == nullptr); 1013b1994897Sopenharmony_ci first_user_->SetPrev(user); 1014b1994897Sopenharmony_ci } 1015b1994897Sopenharmony_ci first_user_ = user; 1016b1994897Sopenharmony_ci } 1017b1994897Sopenharmony_ci 1018b1994897Sopenharmony_ci /** 1019b1994897Sopenharmony_ci * Remove instruction from users. 1020b1994897Sopenharmony_ci * @param user - pointer to User object 1021b1994897Sopenharmony_ci */ 1022b1994897Sopenharmony_ci void RemoveUser(User *user) 1023b1994897Sopenharmony_ci { 1024b1994897Sopenharmony_ci ASSERT(user); 1025b1994897Sopenharmony_ci ASSERT(HasUsers()); 1026b1994897Sopenharmony_ci if (user == first_user_) { 1027b1994897Sopenharmony_ci first_user_ = user->GetNext(); 1028b1994897Sopenharmony_ci } 1029b1994897Sopenharmony_ci user->Remove(); 1030b1994897Sopenharmony_ci } 1031b1994897Sopenharmony_ci 1032b1994897Sopenharmony_ci /** 1033b1994897Sopenharmony_ci * Set input instruction in specified index. 1034b1994897Sopenharmony_ci * Old input will be removed. 1035b1994897Sopenharmony_ci * @param index - index of input to be set 1036b1994897Sopenharmony_ci * @param inst - new input instruction TODO sherstennikov: currently it can be nullptr, is it correct? 1037b1994897Sopenharmony_ci */ 1038b1994897Sopenharmony_ci void SetInput(unsigned index, Inst *inst) 1039b1994897Sopenharmony_ci { 1040b1994897Sopenharmony_ci CHECK_LT(index, GetInputsCount()); 1041b1994897Sopenharmony_ci auto &input = GetInputs()[index]; 1042b1994897Sopenharmony_ci auto user = GetUser(index); 1043b1994897Sopenharmony_ci if (input.GetInst() != nullptr && input.GetInst()->HasUsers()) { 1044b1994897Sopenharmony_ci input.GetInst()->RemoveUser(user); 1045b1994897Sopenharmony_ci } 1046b1994897Sopenharmony_ci if (inst != nullptr) { 1047b1994897Sopenharmony_ci inst->AddUser(user); 1048b1994897Sopenharmony_ci } 1049b1994897Sopenharmony_ci input = Input(inst); 1050b1994897Sopenharmony_ci } 1051b1994897Sopenharmony_ci 1052b1994897Sopenharmony_ci /** 1053b1994897Sopenharmony_ci * Replace all inputs that points to specified instruction by new one. 1054b1994897Sopenharmony_ci * @param old_input - instruction that should be replaced 1055b1994897Sopenharmony_ci * @param new_input - new input instruction 1056b1994897Sopenharmony_ci */ 1057b1994897Sopenharmony_ci void ReplaceInput(Inst *old_input, Inst *new_input) 1058b1994897Sopenharmony_ci { 1059b1994897Sopenharmony_ci unsigned index = 0; 1060b1994897Sopenharmony_ci for (auto input : GetInputs()) { 1061b1994897Sopenharmony_ci if (input.GetInst() == old_input) { 1062b1994897Sopenharmony_ci SetInput(index, new_input); 1063b1994897Sopenharmony_ci } 1064b1994897Sopenharmony_ci index++; 1065b1994897Sopenharmony_ci } 1066b1994897Sopenharmony_ci } 1067b1994897Sopenharmony_ci 1068b1994897Sopenharmony_ci /** 1069b1994897Sopenharmony_ci * Replace inputs that point to this instruction by given instruction. 1070b1994897Sopenharmony_ci * @param inst - new input instruction 1071b1994897Sopenharmony_ci */ 1072b1994897Sopenharmony_ci void ReplaceUsers(Inst *inst) 1073b1994897Sopenharmony_ci { 1074b1994897Sopenharmony_ci ASSERT(inst != this); 1075b1994897Sopenharmony_ci ASSERT(inst != nullptr); 1076b1994897Sopenharmony_ci for (auto it = GetUsers().begin(); it != GetUsers().end(); it = GetUsers().begin()) { 1077b1994897Sopenharmony_ci it->GetInst()->SetInput(it->GetIndex(), inst); 1078b1994897Sopenharmony_ci } 1079b1994897Sopenharmony_ci } 1080b1994897Sopenharmony_ci 1081b1994897Sopenharmony_ci /** 1082b1994897Sopenharmony_ci * Append input instruction. 1083b1994897Sopenharmony_ci * Available only for variadic inputs instructions, such as PHI. 1084b1994897Sopenharmony_ci * @param input - input instruction 1085b1994897Sopenharmony_ci * @return index in inputs container where new input is placed 1086b1994897Sopenharmony_ci */ 1087b1994897Sopenharmony_ci unsigned AppendInput(Inst *input) 1088b1994897Sopenharmony_ci { 1089b1994897Sopenharmony_ci CHECK_NOT_NULL(input); 1090b1994897Sopenharmony_ci ASSERT(IsOperandsDynamic()); 1091b1994897Sopenharmony_ci DynamicOperands *operands = GetDynamicOperands(); 1092b1994897Sopenharmony_ci return operands->Append(input); 1093b1994897Sopenharmony_ci } 1094b1994897Sopenharmony_ci 1095b1994897Sopenharmony_ci unsigned AppendInput(Input input) 1096b1994897Sopenharmony_ci { 1097b1994897Sopenharmony_ci static_assert(sizeof(Input) <= sizeof(uintptr_t)); // Input become larger, so pass it by reference then 1098b1994897Sopenharmony_ci return AppendInput(input.GetInst()); 1099b1994897Sopenharmony_ci } 1100b1994897Sopenharmony_ci 1101b1994897Sopenharmony_ci /** 1102b1994897Sopenharmony_ci * Remove input from inputs container 1103b1994897Sopenharmony_ci * Available only for variadic inputs instructions, such as PHI. 1104b1994897Sopenharmony_ci * @param index - index of input in inputs container 1105b1994897Sopenharmony_ci */ 1106b1994897Sopenharmony_ci virtual void RemoveInput(unsigned index) 1107b1994897Sopenharmony_ci { 1108b1994897Sopenharmony_ci ASSERT(IsOperandsDynamic()); 1109b1994897Sopenharmony_ci DynamicOperands *operands = GetDynamicOperands(); 1110b1994897Sopenharmony_ci ASSERT(index < operands->Size()); 1111b1994897Sopenharmony_ci operands->Remove(index); 1112b1994897Sopenharmony_ci } 1113b1994897Sopenharmony_ci 1114b1994897Sopenharmony_ci /** 1115b1994897Sopenharmony_ci * Remove all inputs 1116b1994897Sopenharmony_ci */ 1117b1994897Sopenharmony_ci void RemoveInputs() 1118b1994897Sopenharmony_ci { 1119b1994897Sopenharmony_ci if (UNLIKELY(IsOperandsDynamic())) { 1120b1994897Sopenharmony_ci for (auto inputs_count = GetInputsCount(); inputs_count != 0; --inputs_count) { 1121b1994897Sopenharmony_ci RemoveInput(inputs_count - 1); 1122b1994897Sopenharmony_ci } 1123b1994897Sopenharmony_ci } else { 1124b1994897Sopenharmony_ci for (size_t i = 0; i < GetInputsCount(); ++i) { 1125b1994897Sopenharmony_ci SetInput(i, nullptr); 1126b1994897Sopenharmony_ci } 1127b1994897Sopenharmony_ci } 1128b1994897Sopenharmony_ci } 1129b1994897Sopenharmony_ci 1130b1994897Sopenharmony_ci /** 1131b1994897Sopenharmony_ci * Remove all users 1132b1994897Sopenharmony_ci */ 1133b1994897Sopenharmony_ci template <bool with_inputs = false> 1134b1994897Sopenharmony_ci void RemoveUsers() 1135b1994897Sopenharmony_ci { 1136b1994897Sopenharmony_ci auto users = GetUsers(); 1137b1994897Sopenharmony_ci while (!users.Empty()) { 1138b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) 1139b1994897Sopenharmony_ci if constexpr (with_inputs) { 1140b1994897Sopenharmony_ci auto &user = users.Front(); 1141b1994897Sopenharmony_ci user.GetInst()->RemoveInput(user.GetIndex()); 1142b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-misleading-indentation) 1143b1994897Sopenharmony_ci } else { 1144b1994897Sopenharmony_ci RemoveUser(&users.Front()); 1145b1994897Sopenharmony_ci } 1146b1994897Sopenharmony_ci } 1147b1994897Sopenharmony_ci } 1148b1994897Sopenharmony_ci 1149b1994897Sopenharmony_ci /** 1150b1994897Sopenharmony_ci * Get input by index 1151b1994897Sopenharmony_ci * @param index - index of input 1152b1994897Sopenharmony_ci * @return input instruction 1153b1994897Sopenharmony_ci */ 1154b1994897Sopenharmony_ci Input GetInput(unsigned index) 1155b1994897Sopenharmony_ci { 1156b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 1157b1994897Sopenharmony_ci return GetInputs()[index]; 1158b1994897Sopenharmony_ci } 1159b1994897Sopenharmony_ci 1160b1994897Sopenharmony_ci Input GetInput(unsigned index) const 1161b1994897Sopenharmony_ci { 1162b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 1163b1994897Sopenharmony_ci return GetInputs()[index]; 1164b1994897Sopenharmony_ci } 1165b1994897Sopenharmony_ci 1166b1994897Sopenharmony_ci Span<Input> GetInputs() 1167b1994897Sopenharmony_ci { 1168b1994897Sopenharmony_ci if (UNLIKELY(IsOperandsDynamic())) { 1169b1994897Sopenharmony_ci DynamicOperands *operands = GetDynamicOperands(); 1170b1994897Sopenharmony_ci return Span<Input>(operands->Inputs(), operands->Size()); 1171b1994897Sopenharmony_ci } 1172b1994897Sopenharmony_ci 1173b1994897Sopenharmony_ci auto inputs_count {GetField<InputsCount>()}; 1174b1994897Sopenharmony_ci return Span<Input>( 1175b1994897Sopenharmony_ci reinterpret_cast<Input *>(reinterpret_cast<uintptr_t>(this) - 1176b1994897Sopenharmony_ci (inputs_count + Input::GetPadding(RUNTIME_ARCH, inputs_count)) * sizeof(Input)), 1177b1994897Sopenharmony_ci inputs_count); 1178b1994897Sopenharmony_ci } 1179b1994897Sopenharmony_ci Span<const Input> GetInputs() const 1180b1994897Sopenharmony_ci { 1181b1994897Sopenharmony_ci return Span<const Input>(const_cast<Inst *>(this)->GetInputs()); 1182b1994897Sopenharmony_ci } 1183b1994897Sopenharmony_ci 1184b1994897Sopenharmony_ci virtual DataType::Type GetInputType([[maybe_unused]] size_t index) const 1185b1994897Sopenharmony_ci { 1186b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 1187b1994897Sopenharmony_ci return GetType(); 1188b1994897Sopenharmony_ci } 1189b1994897Sopenharmony_ci 1190b1994897Sopenharmony_ci UserList<User> GetUsers() 1191b1994897Sopenharmony_ci { 1192b1994897Sopenharmony_ci return UserList<User>(&first_user_); 1193b1994897Sopenharmony_ci } 1194b1994897Sopenharmony_ci UserList<const User> GetUsers() const 1195b1994897Sopenharmony_ci { 1196b1994897Sopenharmony_ci return UserList<const User>(&first_user_); 1197b1994897Sopenharmony_ci } 1198b1994897Sopenharmony_ci 1199b1994897Sopenharmony_ci size_t GetInputsCount() const 1200b1994897Sopenharmony_ci { 1201b1994897Sopenharmony_ci if (UNLIKELY(IsOperandsDynamic())) { 1202b1994897Sopenharmony_ci return GetDynamicOperands()->Size(); 1203b1994897Sopenharmony_ci } 1204b1994897Sopenharmony_ci return GetInputs().Size(); 1205b1994897Sopenharmony_ci } 1206b1994897Sopenharmony_ci 1207b1994897Sopenharmony_ci bool HasUsers() const 1208b1994897Sopenharmony_ci { 1209b1994897Sopenharmony_ci return first_user_ != nullptr; 1210b1994897Sopenharmony_ci }; 1211b1994897Sopenharmony_ci 1212b1994897Sopenharmony_ci bool HasSingleUser() const 1213b1994897Sopenharmony_ci { 1214b1994897Sopenharmony_ci return first_user_ != nullptr && first_user_->GetNext() == nullptr; 1215b1994897Sopenharmony_ci } 1216b1994897Sopenharmony_ci 1217b1994897Sopenharmony_ci /// Reserve space in dataflow storage for specified inputs count 1218b1994897Sopenharmony_ci void ReserveInputs(size_t capacity); 1219b1994897Sopenharmony_ci 1220b1994897Sopenharmony_ci virtual void SetLocation([[maybe_unused]] size_t index, [[maybe_unused]] Location location) {} 1221b1994897Sopenharmony_ci 1222b1994897Sopenharmony_ci virtual Location GetLocation([[maybe_unused]] size_t index) const 1223b1994897Sopenharmony_ci { 1224b1994897Sopenharmony_ci return Location::RequireRegister(); 1225b1994897Sopenharmony_ci } 1226b1994897Sopenharmony_ci 1227b1994897Sopenharmony_ci virtual Location GetDstLocation() const 1228b1994897Sopenharmony_ci { 1229b1994897Sopenharmony_ci return Location::MakeRegister(GetDstReg(), GetType()); 1230b1994897Sopenharmony_ci } 1231b1994897Sopenharmony_ci 1232b1994897Sopenharmony_ci template <typename Accessor> 1233b1994897Sopenharmony_ci typename Accessor::ValueType GetField() const 1234b1994897Sopenharmony_ci { 1235b1994897Sopenharmony_ci return Accessor::Get(bit_fields_); 1236b1994897Sopenharmony_ci } 1237b1994897Sopenharmony_ci 1238b1994897Sopenharmony_ci template <typename Accessor> 1239b1994897Sopenharmony_ci void SetField(typename Accessor::ValueType value) 1240b1994897Sopenharmony_ci { 1241b1994897Sopenharmony_ci Accessor::Set(value, &bit_fields_); 1242b1994897Sopenharmony_ci } 1243b1994897Sopenharmony_ci 1244b1994897Sopenharmony_ci uint64_t GetAllFields() const 1245b1994897Sopenharmony_ci { 1246b1994897Sopenharmony_ci return bit_fields_; 1247b1994897Sopenharmony_ci } 1248b1994897Sopenharmony_ci 1249b1994897Sopenharmony_ci bool IsPhi() const 1250b1994897Sopenharmony_ci { 1251b1994897Sopenharmony_ci return opcode_ == Opcode::Phi; 1252b1994897Sopenharmony_ci } 1253b1994897Sopenharmony_ci 1254b1994897Sopenharmony_ci bool IsCatchPhi() const 1255b1994897Sopenharmony_ci { 1256b1994897Sopenharmony_ci return opcode_ == Opcode::CatchPhi; 1257b1994897Sopenharmony_ci } 1258b1994897Sopenharmony_ci 1259b1994897Sopenharmony_ci bool IsConst() const 1260b1994897Sopenharmony_ci { 1261b1994897Sopenharmony_ci return opcode_ == Opcode::Constant; 1262b1994897Sopenharmony_ci } 1263b1994897Sopenharmony_ci 1264b1994897Sopenharmony_ci bool IsParameter() const 1265b1994897Sopenharmony_ci { 1266b1994897Sopenharmony_ci return opcode_ == Opcode::Parameter; 1267b1994897Sopenharmony_ci } 1268b1994897Sopenharmony_ci 1269b1994897Sopenharmony_ci virtual bool IsBoolConst() const 1270b1994897Sopenharmony_ci { 1271b1994897Sopenharmony_ci return false; 1272b1994897Sopenharmony_ci } 1273b1994897Sopenharmony_ci 1274b1994897Sopenharmony_ci bool IsSaveState() const 1275b1994897Sopenharmony_ci { 1276b1994897Sopenharmony_ci return opcode_ == Opcode::SaveState; 1277b1994897Sopenharmony_ci } 1278b1994897Sopenharmony_ci 1279b1994897Sopenharmony_ci bool IsTry() const 1280b1994897Sopenharmony_ci { 1281b1994897Sopenharmony_ci return opcode_ == Opcode::Try; 1282b1994897Sopenharmony_ci } 1283b1994897Sopenharmony_ci 1284b1994897Sopenharmony_ci virtual void SetVnObject([[maybe_unused]] VnObject *vn_obj) {} 1285b1994897Sopenharmony_ci 1286b1994897Sopenharmony_ci Register GetDstReg() const 1287b1994897Sopenharmony_ci { 1288b1994897Sopenharmony_ci return dst_reg_; 1289b1994897Sopenharmony_ci } 1290b1994897Sopenharmony_ci 1291b1994897Sopenharmony_ci void SetDstReg(Register reg) 1292b1994897Sopenharmony_ci { 1293b1994897Sopenharmony_ci dst_reg_ = reg; 1294b1994897Sopenharmony_ci } 1295b1994897Sopenharmony_ci 1296b1994897Sopenharmony_ci uint32_t GetVN() const 1297b1994897Sopenharmony_ci { 1298b1994897Sopenharmony_ci return vn_; 1299b1994897Sopenharmony_ci } 1300b1994897Sopenharmony_ci 1301b1994897Sopenharmony_ci void SetVN(uint32_t vn) 1302b1994897Sopenharmony_ci { 1303b1994897Sopenharmony_ci vn_ = vn; 1304b1994897Sopenharmony_ci } 1305b1994897Sopenharmony_ci void Dump(std::ostream *out, bool new_line = true) const; 1306b1994897Sopenharmony_ci virtual bool DumpInputs(std::ostream *out) const; 1307b1994897Sopenharmony_ci virtual void DumpOpcode(std::ostream *out) const; 1308b1994897Sopenharmony_ci 1309b1994897Sopenharmony_ci virtual void SetDstReg([[maybe_unused]] unsigned index, Register reg) 1310b1994897Sopenharmony_ci { 1311b1994897Sopenharmony_ci ASSERT(index == 0); 1312b1994897Sopenharmony_ci SetDstReg(reg); 1313b1994897Sopenharmony_ci } 1314b1994897Sopenharmony_ci 1315b1994897Sopenharmony_ci virtual Register GetDstReg([[maybe_unused]] unsigned index) const 1316b1994897Sopenharmony_ci { 1317b1994897Sopenharmony_ci ASSERT(index == 0); 1318b1994897Sopenharmony_ci return GetDstReg(); 1319b1994897Sopenharmony_ci } 1320b1994897Sopenharmony_ci 1321b1994897Sopenharmony_ci virtual size_t GetDstCount() const 1322b1994897Sopenharmony_ci { 1323b1994897Sopenharmony_ci return 1; 1324b1994897Sopenharmony_ci } 1325b1994897Sopenharmony_ci 1326b1994897Sopenharmony_ci virtual uint32_t GetSrcRegIndex() const 1327b1994897Sopenharmony_ci { 1328b1994897Sopenharmony_ci return 0; 1329b1994897Sopenharmony_ci } 1330b1994897Sopenharmony_ci 1331b1994897Sopenharmony_ci virtual void SetSrcReg([[maybe_unused]] unsigned index, [[maybe_unused]] Register reg) {} 1332b1994897Sopenharmony_ci 1333b1994897Sopenharmony_ci virtual Register GetSrcReg([[maybe_unused]] unsigned index) const 1334b1994897Sopenharmony_ci { 1335b1994897Sopenharmony_ci return INVALID_REG; 1336b1994897Sopenharmony_ci } 1337b1994897Sopenharmony_ci 1338b1994897Sopenharmony_ci User *GetFirstUser() const 1339b1994897Sopenharmony_ci { 1340b1994897Sopenharmony_ci return first_user_; 1341b1994897Sopenharmony_ci } 1342b1994897Sopenharmony_ci 1343b1994897Sopenharmony_ciprotected: 1344b1994897Sopenharmony_ci using InstBase::InstBase; 1345b1994897Sopenharmony_ci static constexpr int INPUT_COUNT = 0; 1346b1994897Sopenharmony_ci 1347b1994897Sopenharmony_ci Inst() = default; 1348b1994897Sopenharmony_ci 1349b1994897Sopenharmony_ci explicit Inst(Opcode opcode) : Inst(opcode, DataType::Type::NO_TYPE, INVALID_PC) {} 1350b1994897Sopenharmony_ci 1351b1994897Sopenharmony_ci explicit Inst(Opcode opcode, DataType::Type type, uint32_t pc) : pc_(pc), opcode_(opcode) 1352b1994897Sopenharmony_ci { 1353b1994897Sopenharmony_ci bit_fields_ = inst_flags::GetFlagsMask(opcode); 1354b1994897Sopenharmony_ci SetField<FieldType>(type); 1355b1994897Sopenharmony_ci } 1356b1994897Sopenharmony_ci 1357b1994897Sopenharmony_ciprotected: 1358b1994897Sopenharmony_ci using FieldFlags = BitField<uint32_t, 0, MinimumBitsToStore(1U << inst_flags::FLAGS_COUNT)>; 1359b1994897Sopenharmony_ci using FieldType = FieldFlags::NextField<DataType::Type, MinimumBitsToStore(DataType::LAST)>; 1360b1994897Sopenharmony_ci using InputsCount = FieldType::NextField<uint32_t, BITS_PER_INPUTS_NUM>; 1361b1994897Sopenharmony_ci using LastField = InputsCount; 1362b1994897Sopenharmony_ci 1363b1994897Sopenharmony_ci DynamicOperands *GetDynamicOperands() const 1364b1994897Sopenharmony_ci { 1365b1994897Sopenharmony_ci return reinterpret_cast<DynamicOperands *>(reinterpret_cast<uintptr_t>(this) - sizeof(DynamicOperands)); 1366b1994897Sopenharmony_ci } 1367b1994897Sopenharmony_ci 1368b1994897Sopenharmony_ciprivate: 1369b1994897Sopenharmony_ci User *GetUser(unsigned index) 1370b1994897Sopenharmony_ci { 1371b1994897Sopenharmony_ci if (UNLIKELY(IsOperandsDynamic())) { 1372b1994897Sopenharmony_ci return GetDynamicOperands()->GetUser(index); 1373b1994897Sopenharmony_ci } 1374b1994897Sopenharmony_ci auto inputs_count {GetField<InputsCount>()}; 1375b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 1376b1994897Sopenharmony_ci return reinterpret_cast<User *>(reinterpret_cast<Input *>(this) - 1377b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 1378b1994897Sopenharmony_ci (inputs_count + Input::GetPadding(RUNTIME_ARCH, inputs_count))) - 1379b1994897Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 1380b1994897Sopenharmony_ci index - 1; 1381b1994897Sopenharmony_ci } 1382b1994897Sopenharmony_ci 1383b1994897Sopenharmony_ci size_t OperandsStorageSize() const 1384b1994897Sopenharmony_ci { 1385b1994897Sopenharmony_ci if (UNLIKELY(IsOperandsDynamic())) { 1386b1994897Sopenharmony_ci return sizeof(DynamicOperands); 1387b1994897Sopenharmony_ci } 1388b1994897Sopenharmony_ci 1389b1994897Sopenharmony_ci auto inputs_count {GetField<InputsCount>()}; 1390b1994897Sopenharmony_ci return inputs_count * (sizeof(Input) + sizeof(User)) + 1391b1994897Sopenharmony_ci Input::GetPadding(RUNTIME_ARCH, inputs_count) * sizeof(Input); 1392b1994897Sopenharmony_ci } 1393b1994897Sopenharmony_ci 1394b1994897Sopenharmony_ciprivate: 1395b1994897Sopenharmony_ci /// Basic block this instruction belongs to 1396b1994897Sopenharmony_ci BasicBlock *bb_ {nullptr}; 1397b1994897Sopenharmony_ci 1398b1994897Sopenharmony_ci /// Next instruction within basic block 1399b1994897Sopenharmony_ci Inst *next_ {nullptr}; 1400b1994897Sopenharmony_ci 1401b1994897Sopenharmony_ci /// Previous instruction within basic block 1402b1994897Sopenharmony_ci Inst *prev_ {nullptr}; 1403b1994897Sopenharmony_ci 1404b1994897Sopenharmony_ci /// First user in users chain 1405b1994897Sopenharmony_ci User *first_user_ {nullptr}; 1406b1994897Sopenharmony_ci 1407b1994897Sopenharmony_ci /// This value hold properties of the instruction. It accessed via BitField types(f.e. FieldType). 1408b1994897Sopenharmony_ci uint64_t bit_fields_ {0}; 1409b1994897Sopenharmony_ci 1410b1994897Sopenharmony_ci /// Unique id of instruction 1411b1994897Sopenharmony_ci uint32_t id_ {INVALID_ID}; 1412b1994897Sopenharmony_ci 1413b1994897Sopenharmony_ci /// Unique id of instruction 1414b1994897Sopenharmony_ci uint32_t vn_ {INVALID_VN}; 1415b1994897Sopenharmony_ci 1416b1994897Sopenharmony_ci /// Bytecode pc 1417b1994897Sopenharmony_ci uint32_t pc_ {INVALID_PC}; 1418b1994897Sopenharmony_ci 1419b1994897Sopenharmony_ci /// Number used in cloning 1420b1994897Sopenharmony_ci uint32_t clone_number_ {0}; 1421b1994897Sopenharmony_ci 1422b1994897Sopenharmony_ci /// Instruction number getting while visiting graph 1423b1994897Sopenharmony_ci LinearNumber linear_number_ {INVALID_LINEAR_NUM}; 1424b1994897Sopenharmony_ci 1425b1994897Sopenharmony_ci ObjectTypeInfo object_type_info_ {}; 1426b1994897Sopenharmony_ci 1427b1994897Sopenharmony_ci /// Opcode, see opcodes.def 1428b1994897Sopenharmony_ci Opcode opcode_ {Opcode::INVALID}; 1429b1994897Sopenharmony_ci 1430b1994897Sopenharmony_ci // Destination register type - defined in FieldType 1431b1994897Sopenharmony_ci Register dst_reg_ {INVALID_REG}; 1432b1994897Sopenharmony_ci}; 1433b1994897Sopenharmony_ci 1434b1994897Sopenharmony_ci/** 1435b1994897Sopenharmony_ci * Proxy class that injects new field - type of the source operands - into property field of the instruction. 1436b1994897Sopenharmony_ci * Should be used when instruction has sources of the same type and type of the instruction is not match to type of 1437b1994897Sopenharmony_ci * sources. Examples: Cmp, Compare 1438b1994897Sopenharmony_ci * @tparam T Base instruction class after which this mixin is injected 1439b1994897Sopenharmony_ci */ 1440b1994897Sopenharmony_citemplate <typename T> 1441b1994897Sopenharmony_ciclass InstWithOperandsType : public T { 1442b1994897Sopenharmony_cipublic: 1443b1994897Sopenharmony_ci using T::T; 1444b1994897Sopenharmony_ci 1445b1994897Sopenharmony_ci void SetOperandsType(DataType::Type type) 1446b1994897Sopenharmony_ci { 1447b1994897Sopenharmony_ci T::template SetField<FieldOperandsType>(type); 1448b1994897Sopenharmony_ci } 1449b1994897Sopenharmony_ci virtual DataType::Type GetOperandsType() const 1450b1994897Sopenharmony_ci { 1451b1994897Sopenharmony_ci return T::template GetField<FieldOperandsType>(); 1452b1994897Sopenharmony_ci } 1453b1994897Sopenharmony_ci 1454b1994897Sopenharmony_ciprotected: 1455b1994897Sopenharmony_ci using FieldOperandsType = 1456b1994897Sopenharmony_ci typename T::LastField::template NextField<DataType::Type, MinimumBitsToStore(DataType::LAST)>; 1457b1994897Sopenharmony_ci using LastField = FieldOperandsType; 1458b1994897Sopenharmony_ci}; 1459b1994897Sopenharmony_ci 1460b1994897Sopenharmony_ci/** 1461b1994897Sopenharmony_ci * Mixin for NeedBarrier flag. 1462b1994897Sopenharmony_ci * @tparam T Base instruction class after which this mixin is injected 1463b1994897Sopenharmony_ci */ 1464b1994897Sopenharmony_citemplate <typename T> 1465b1994897Sopenharmony_ciclass NeedBarrierMixin : public T { 1466b1994897Sopenharmony_cipublic: 1467b1994897Sopenharmony_ci using T::T; 1468b1994897Sopenharmony_ci 1469b1994897Sopenharmony_ci void SetNeedBarrier(bool v) 1470b1994897Sopenharmony_ci { 1471b1994897Sopenharmony_ci T::template SetField<NeedBarrierFlag>(v); 1472b1994897Sopenharmony_ci } 1473b1994897Sopenharmony_ci bool GetNeedBarrier() const 1474b1994897Sopenharmony_ci { 1475b1994897Sopenharmony_ci return T::template GetField<NeedBarrierFlag>(); 1476b1994897Sopenharmony_ci } 1477b1994897Sopenharmony_ci 1478b1994897Sopenharmony_ciprotected: 1479b1994897Sopenharmony_ci using NeedBarrierFlag = typename T::LastField::NextFlag; 1480b1994897Sopenharmony_ci using LastField = NeedBarrierFlag; 1481b1994897Sopenharmony_ci}; 1482b1994897Sopenharmony_ci 1483b1994897Sopenharmony_ci/** 1484b1994897Sopenharmony_ci * This mixin aims to implement type id accessors. 1485b1994897Sopenharmony_ci */ 1486b1994897Sopenharmony_ciclass TypeIdMixin { 1487b1994897Sopenharmony_cipublic: 1488b1994897Sopenharmony_ci TypeIdMixin() = default; 1489b1994897Sopenharmony_ci NO_COPY_SEMANTIC(TypeIdMixin); 1490b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(TypeIdMixin); 1491b1994897Sopenharmony_ci virtual ~TypeIdMixin() = default; 1492b1994897Sopenharmony_ci 1493b1994897Sopenharmony_ci void SetTypeId(uint32_t id) 1494b1994897Sopenharmony_ci { 1495b1994897Sopenharmony_ci type_id_ = id; 1496b1994897Sopenharmony_ci } 1497b1994897Sopenharmony_ci 1498b1994897Sopenharmony_ci auto GetTypeId() const 1499b1994897Sopenharmony_ci { 1500b1994897Sopenharmony_ci return type_id_; 1501b1994897Sopenharmony_ci } 1502b1994897Sopenharmony_ci 1503b1994897Sopenharmony_ci void SetMethod(RuntimeInterface::MethodPtr method) 1504b1994897Sopenharmony_ci { 1505b1994897Sopenharmony_ci method_ = method; 1506b1994897Sopenharmony_ci } 1507b1994897Sopenharmony_ci auto GetMethod() const 1508b1994897Sopenharmony_ci { 1509b1994897Sopenharmony_ci return method_; 1510b1994897Sopenharmony_ci } 1511b1994897Sopenharmony_ci 1512b1994897Sopenharmony_ciprivate: 1513b1994897Sopenharmony_ci uint32_t type_id_ {0}; 1514b1994897Sopenharmony_ci // The pointer to the method in which this instruction is executed(inlined method) 1515b1994897Sopenharmony_ci RuntimeInterface::MethodPtr method_ {nullptr}; 1516b1994897Sopenharmony_ci}; 1517b1994897Sopenharmony_ci 1518b1994897Sopenharmony_ci/** 1519b1994897Sopenharmony_ci * Mixin for Inlined calls/returns. 1520b1994897Sopenharmony_ci */ 1521b1994897Sopenharmony_citemplate <typename T> 1522b1994897Sopenharmony_ciclass InlinedInstMixin : public T { 1523b1994897Sopenharmony_cipublic: 1524b1994897Sopenharmony_ci using T::T; 1525b1994897Sopenharmony_ci 1526b1994897Sopenharmony_ci void SetInlined(bool v) 1527b1994897Sopenharmony_ci { 1528b1994897Sopenharmony_ci T::template SetField<IsInlinedFlag>(v); 1529b1994897Sopenharmony_ci } 1530b1994897Sopenharmony_ci bool IsInlined() const 1531b1994897Sopenharmony_ci { 1532b1994897Sopenharmony_ci return T::template GetField<IsInlinedFlag>(); 1533b1994897Sopenharmony_ci } 1534b1994897Sopenharmony_ci 1535b1994897Sopenharmony_ciprotected: 1536b1994897Sopenharmony_ci using IsInlinedFlag = typename T::LastField::NextFlag; 1537b1994897Sopenharmony_ci using LastField = IsInlinedFlag; 1538b1994897Sopenharmony_ci}; 1539b1994897Sopenharmony_ci 1540b1994897Sopenharmony_ci/** 1541b1994897Sopenharmony_ci * Mixin for instructions with immediate constant value 1542b1994897Sopenharmony_ci */ 1543b1994897Sopenharmony_ciclass ImmediateMixin { 1544b1994897Sopenharmony_cipublic: 1545b1994897Sopenharmony_ci explicit ImmediateMixin(uint64_t immediate) : immediate_(immediate) {} 1546b1994897Sopenharmony_ci 1547b1994897Sopenharmony_ci NO_COPY_SEMANTIC(ImmediateMixin); 1548b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(ImmediateMixin); 1549b1994897Sopenharmony_ci virtual ~ImmediateMixin() = default; 1550b1994897Sopenharmony_ci 1551b1994897Sopenharmony_ci void SetImm(uint64_t immediate) 1552b1994897Sopenharmony_ci { 1553b1994897Sopenharmony_ci immediate_ = immediate; 1554b1994897Sopenharmony_ci } 1555b1994897Sopenharmony_ci auto GetImm() const 1556b1994897Sopenharmony_ci { 1557b1994897Sopenharmony_ci return immediate_; 1558b1994897Sopenharmony_ci } 1559b1994897Sopenharmony_ci 1560b1994897Sopenharmony_ciprotected: 1561b1994897Sopenharmony_ci ImmediateMixin() = default; 1562b1994897Sopenharmony_ci 1563b1994897Sopenharmony_ciprivate: 1564b1994897Sopenharmony_ci uint64_t immediate_ {0}; 1565b1994897Sopenharmony_ci}; 1566b1994897Sopenharmony_ci 1567b1994897Sopenharmony_ci/** 1568b1994897Sopenharmony_ci * Mixin for instructions with ConditionCode 1569b1994897Sopenharmony_ci */ 1570b1994897Sopenharmony_citemplate <typename T> 1571b1994897Sopenharmony_ciclass ConditionMixin : public T { 1572b1994897Sopenharmony_cipublic: 1573b1994897Sopenharmony_ci enum class Prediction { NONE, LIKELY, UNLIKELY, SIZE = UNLIKELY }; 1574b1994897Sopenharmony_ci 1575b1994897Sopenharmony_ci using T::T; 1576b1994897Sopenharmony_ci explicit ConditionMixin(ConditionCode cc) 1577b1994897Sopenharmony_ci { 1578b1994897Sopenharmony_ci T::template SetField<CcFlag>(cc); 1579b1994897Sopenharmony_ci } 1580b1994897Sopenharmony_ci NO_COPY_SEMANTIC(ConditionMixin); 1581b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(ConditionMixin); 1582b1994897Sopenharmony_ci ~ConditionMixin() override = default; 1583b1994897Sopenharmony_ci 1584b1994897Sopenharmony_ci auto GetCc() const 1585b1994897Sopenharmony_ci { 1586b1994897Sopenharmony_ci return T::template GetField<CcFlag>(); 1587b1994897Sopenharmony_ci } 1588b1994897Sopenharmony_ci void SetCc(ConditionCode cc) 1589b1994897Sopenharmony_ci { 1590b1994897Sopenharmony_ci T::template SetField<CcFlag>(cc); 1591b1994897Sopenharmony_ci } 1592b1994897Sopenharmony_ci void InverseConditionCode() 1593b1994897Sopenharmony_ci { 1594b1994897Sopenharmony_ci SetCc(GetInverseConditionCode(GetCc())); 1595b1994897Sopenharmony_ci if (IsLikely()) { 1596b1994897Sopenharmony_ci SetUnlikely(); 1597b1994897Sopenharmony_ci } else if (IsUnlikely()) { 1598b1994897Sopenharmony_ci SetLikely(); 1599b1994897Sopenharmony_ci } 1600b1994897Sopenharmony_ci } 1601b1994897Sopenharmony_ci 1602b1994897Sopenharmony_ci bool IsLikely() const 1603b1994897Sopenharmony_ci { 1604b1994897Sopenharmony_ci return T::template GetField<PredictionFlag>() == Prediction::LIKELY; 1605b1994897Sopenharmony_ci } 1606b1994897Sopenharmony_ci bool IsUnlikely() const 1607b1994897Sopenharmony_ci { 1608b1994897Sopenharmony_ci return T::template GetField<PredictionFlag>() == Prediction::UNLIKELY; 1609b1994897Sopenharmony_ci } 1610b1994897Sopenharmony_ci void SetLikely() 1611b1994897Sopenharmony_ci { 1612b1994897Sopenharmony_ci T::template SetField<PredictionFlag>(Prediction::LIKELY); 1613b1994897Sopenharmony_ci } 1614b1994897Sopenharmony_ci void SetUnlikely() 1615b1994897Sopenharmony_ci { 1616b1994897Sopenharmony_ci T::template SetField<PredictionFlag>(Prediction::UNLIKELY); 1617b1994897Sopenharmony_ci } 1618b1994897Sopenharmony_ci 1619b1994897Sopenharmony_ciprotected: 1620b1994897Sopenharmony_ci ConditionMixin() = default; 1621b1994897Sopenharmony_ci 1622b1994897Sopenharmony_ci using CcFlag = typename T::LastField::template NextField<ConditionCode, MinimumBitsToStore(ConditionCode::CC_LAST)>; 1623b1994897Sopenharmony_ci using PredictionFlag = typename CcFlag::template NextField<Prediction, MinimumBitsToStore(Prediction::SIZE)>; 1624b1994897Sopenharmony_ci using LastField = PredictionFlag; 1625b1994897Sopenharmony_ci}; 1626b1994897Sopenharmony_ci 1627b1994897Sopenharmony_ci/** 1628b1994897Sopenharmony_ci * Instruction with fixed number of inputs. 1629b1994897Sopenharmony_ci * Shall not be instantiated directly, only through derived classes. 1630b1994897Sopenharmony_ci */ 1631b1994897Sopenharmony_citemplate <size_t N> 1632b1994897Sopenharmony_ciclass FixedInputsInst : public Inst { 1633b1994897Sopenharmony_cipublic: 1634b1994897Sopenharmony_ci using Inst::Inst; 1635b1994897Sopenharmony_ci 1636b1994897Sopenharmony_ci static constexpr int INPUT_COUNT = N; 1637b1994897Sopenharmony_ci 1638b1994897Sopenharmony_ci void SetSrcReg(unsigned index, Register reg) override 1639b1994897Sopenharmony_ci { 1640b1994897Sopenharmony_ci ASSERT(index < N); 1641b1994897Sopenharmony_ci src_regs_[index] = reg; 1642b1994897Sopenharmony_ci } 1643b1994897Sopenharmony_ci 1644b1994897Sopenharmony_ci Register GetSrcReg(unsigned index) const override 1645b1994897Sopenharmony_ci { 1646b1994897Sopenharmony_ci ASSERT(index < N); 1647b1994897Sopenharmony_ci return src_regs_[index]; 1648b1994897Sopenharmony_ci } 1649b1994897Sopenharmony_ci 1650b1994897Sopenharmony_ci Location GetLocation(size_t index) const override 1651b1994897Sopenharmony_ci { 1652b1994897Sopenharmony_ci return Location::MakeRegister(GetSrcReg(index), GetInputType(index)); 1653b1994897Sopenharmony_ci } 1654b1994897Sopenharmony_ci 1655b1994897Sopenharmony_ci void SetLocation(size_t index, Location location) override 1656b1994897Sopenharmony_ci { 1657b1994897Sopenharmony_ci SetSrcReg(index, location.GetValue()); 1658b1994897Sopenharmony_ci } 1659b1994897Sopenharmony_ci 1660b1994897Sopenharmony_ci void SetDstLocation(Location location) 1661b1994897Sopenharmony_ci { 1662b1994897Sopenharmony_ci SetDstReg(location.GetValue()); 1663b1994897Sopenharmony_ci } 1664b1994897Sopenharmony_ci 1665b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 1666b1994897Sopenharmony_ci 1667b1994897Sopenharmony_ciprivate: 1668b1994897Sopenharmony_ci template <typename T, std::size_t... Is> 1669b1994897Sopenharmony_ci constexpr auto CreateArray(T value, [[maybe_unused]] std::index_sequence<Is...> unused) 1670b1994897Sopenharmony_ci { 1671b1994897Sopenharmony_ci return std::array<T, sizeof...(Is)> {(static_cast<void>(Is), value)...}; 1672b1994897Sopenharmony_ci } 1673b1994897Sopenharmony_ci 1674b1994897Sopenharmony_ci std::array<Register, N> src_regs_ = CreateArray(INVALID_REG, std::make_index_sequence<INPUT_COUNT>()); 1675b1994897Sopenharmony_ci}; 1676b1994897Sopenharmony_ci 1677b1994897Sopenharmony_citemplate <size_t N> 1678b1994897Sopenharmony_ciInst *FixedInputsInst<N>::Clone(const Graph *targetGraph) const 1679b1994897Sopenharmony_ci{ 1680b1994897Sopenharmony_ci auto clone = static_cast<FixedInputsInst *>(Inst::Clone(targetGraph)); 1681b1994897Sopenharmony_ci#ifndef NDEBUG 1682b1994897Sopenharmony_ci for (size_t i = 0; i < INPUT_COUNT; ++i) { 1683b1994897Sopenharmony_ci clone->SetSrcReg(i, GetSrcReg(i)); 1684b1994897Sopenharmony_ci } 1685b1994897Sopenharmony_ci#endif 1686b1994897Sopenharmony_ci return clone; 1687b1994897Sopenharmony_ci} 1688b1994897Sopenharmony_ci 1689b1994897Sopenharmony_ci/** 1690b1994897Sopenharmony_ci * Instructions with fixed static inputs 1691b1994897Sopenharmony_ci * We need to explicitly declare these proxy classes because some code can't work with the templated inst classes, for 1692b1994897Sopenharmony_ci * example DEFINE_INST macro. 1693b1994897Sopenharmony_ci */ 1694b1994897Sopenharmony_ciclass FixedInputsInst0 : public FixedInputsInst<0> { 1695b1994897Sopenharmony_cipublic: 1696b1994897Sopenharmony_ci using FixedInputsInst::FixedInputsInst; 1697b1994897Sopenharmony_ci 1698b1994897Sopenharmony_ci NO_COPY_SEMANTIC(FixedInputsInst0); 1699b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(FixedInputsInst0); 1700b1994897Sopenharmony_ci ~FixedInputsInst0() override = default; 1701b1994897Sopenharmony_ci}; 1702b1994897Sopenharmony_ci 1703b1994897Sopenharmony_ciclass FixedInputsInst1 : public FixedInputsInst<1> { 1704b1994897Sopenharmony_cipublic: 1705b1994897Sopenharmony_ci using FixedInputsInst::FixedInputsInst; 1706b1994897Sopenharmony_ci 1707b1994897Sopenharmony_ci NO_COPY_SEMANTIC(FixedInputsInst1); 1708b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(FixedInputsInst1); 1709b1994897Sopenharmony_ci ~FixedInputsInst1() override = default; 1710b1994897Sopenharmony_ci}; 1711b1994897Sopenharmony_ci 1712b1994897Sopenharmony_ciclass FixedInputsInst2 : public FixedInputsInst<2U> { 1713b1994897Sopenharmony_cipublic: 1714b1994897Sopenharmony_ci using FixedInputsInst::FixedInputsInst; 1715b1994897Sopenharmony_ci 1716b1994897Sopenharmony_ci NO_COPY_SEMANTIC(FixedInputsInst2); 1717b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(FixedInputsInst2); 1718b1994897Sopenharmony_ci ~FixedInputsInst2() override = default; 1719b1994897Sopenharmony_ci}; 1720b1994897Sopenharmony_ci 1721b1994897Sopenharmony_ci/** 1722b1994897Sopenharmony_ci * Instruction with variable inputs count 1723b1994897Sopenharmony_ci */ 1724b1994897Sopenharmony_ciclass DynamicInputsInst : public Inst { 1725b1994897Sopenharmony_cipublic: 1726b1994897Sopenharmony_ci using Inst::Inst; 1727b1994897Sopenharmony_ci 1728b1994897Sopenharmony_ci static constexpr int INPUT_COUNT = MAX_STATIC_INPUTS; 1729b1994897Sopenharmony_ci 1730b1994897Sopenharmony_ci Location GetLocation(size_t index) const override 1731b1994897Sopenharmony_ci { 1732b1994897Sopenharmony_ci if (locations_ == nullptr) { 1733b1994897Sopenharmony_ci return Location::Invalid(); 1734b1994897Sopenharmony_ci } 1735b1994897Sopenharmony_ci return locations_->GetLocation(index); 1736b1994897Sopenharmony_ci } 1737b1994897Sopenharmony_ci 1738b1994897Sopenharmony_ci Location GetDstLocation() const override 1739b1994897Sopenharmony_ci { 1740b1994897Sopenharmony_ci if (locations_ == nullptr) { 1741b1994897Sopenharmony_ci return Location::Invalid(); 1742b1994897Sopenharmony_ci } 1743b1994897Sopenharmony_ci return locations_->GetDstLocation(); 1744b1994897Sopenharmony_ci } 1745b1994897Sopenharmony_ci 1746b1994897Sopenharmony_ci void SetLocation(size_t index, Location location) override 1747b1994897Sopenharmony_ci { 1748b1994897Sopenharmony_ci ASSERT(locations_ != nullptr); 1749b1994897Sopenharmony_ci locations_->SetLocation(index, location); 1750b1994897Sopenharmony_ci } 1751b1994897Sopenharmony_ci 1752b1994897Sopenharmony_ci void SetDstLocation(Location location) 1753b1994897Sopenharmony_ci { 1754b1994897Sopenharmony_ci ASSERT(locations_ != nullptr); 1755b1994897Sopenharmony_ci locations_->SetDstLocation(location); 1756b1994897Sopenharmony_ci } 1757b1994897Sopenharmony_ci 1758b1994897Sopenharmony_ci void SetLocationsInfo(LocationsInfo *info) 1759b1994897Sopenharmony_ci { 1760b1994897Sopenharmony_ci locations_ = info; 1761b1994897Sopenharmony_ci } 1762b1994897Sopenharmony_ci 1763b1994897Sopenharmony_ci Register GetSrcReg(unsigned index) const override 1764b1994897Sopenharmony_ci { 1765b1994897Sopenharmony_ci return GetLocation(index).GetValue(); 1766b1994897Sopenharmony_ci } 1767b1994897Sopenharmony_ci 1768b1994897Sopenharmony_ci void SetSrcReg(unsigned index, Register reg) override 1769b1994897Sopenharmony_ci { 1770b1994897Sopenharmony_ci SetLocation(index, Location::MakeRegister(reg, GetInputType(index))); 1771b1994897Sopenharmony_ci } 1772b1994897Sopenharmony_ci 1773b1994897Sopenharmony_ciprivate: 1774b1994897Sopenharmony_ci LocationsInfo *locations_ {nullptr}; 1775b1994897Sopenharmony_ci}; 1776b1994897Sopenharmony_ci 1777b1994897Sopenharmony_ciclass SpillFillInst; 1778b1994897Sopenharmony_ci 1779b1994897Sopenharmony_ci/** 1780b1994897Sopenharmony_ci * Mixin to hold location data 1781b1994897Sopenharmony_ci */ 1782b1994897Sopenharmony_ciclass LocationDataMixin { 1783b1994897Sopenharmony_cipublic: 1784b1994897Sopenharmony_ci void SetLocationData(SpillFillData location_data) 1785b1994897Sopenharmony_ci { 1786b1994897Sopenharmony_ci location_data_ = location_data; 1787b1994897Sopenharmony_ci } 1788b1994897Sopenharmony_ci 1789b1994897Sopenharmony_ci auto GetLocationData() const 1790b1994897Sopenharmony_ci { 1791b1994897Sopenharmony_ci return location_data_; 1792b1994897Sopenharmony_ci } 1793b1994897Sopenharmony_ci 1794b1994897Sopenharmony_ci auto &GetLocationData() 1795b1994897Sopenharmony_ci { 1796b1994897Sopenharmony_ci return location_data_; 1797b1994897Sopenharmony_ci } 1798b1994897Sopenharmony_ci 1799b1994897Sopenharmony_ciprotected: 1800b1994897Sopenharmony_ci LocationDataMixin() = default; 1801b1994897Sopenharmony_ci NO_COPY_SEMANTIC(LocationDataMixin); 1802b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(LocationDataMixin); 1803b1994897Sopenharmony_ci virtual ~LocationDataMixin() = default; 1804b1994897Sopenharmony_ci 1805b1994897Sopenharmony_ciprivate: 1806b1994897Sopenharmony_ci SpillFillData location_data_ {}; 1807b1994897Sopenharmony_ci}; 1808b1994897Sopenharmony_ci 1809b1994897Sopenharmony_ci/** 1810b1994897Sopenharmony_ci * Mixin to hold input types of call instruction 1811b1994897Sopenharmony_ci */ 1812b1994897Sopenharmony_ciclass InputTypesMixin { 1813b1994897Sopenharmony_cipublic: 1814b1994897Sopenharmony_ci InputTypesMixin() = default; 1815b1994897Sopenharmony_ci NO_COPY_SEMANTIC(InputTypesMixin); 1816b1994897Sopenharmony_ci NO_MOVE_SEMANTIC(InputTypesMixin); 1817b1994897Sopenharmony_ci virtual ~InputTypesMixin() = default; 1818b1994897Sopenharmony_ci 1819b1994897Sopenharmony_ci void AllocateInputTypes(ArenaAllocator *allocator, size_t capacity) 1820b1994897Sopenharmony_ci { 1821b1994897Sopenharmony_ci ASSERT(allocator != nullptr); 1822b1994897Sopenharmony_ci ASSERT(input_types_ == nullptr); 1823b1994897Sopenharmony_ci input_types_ = allocator->New<ArenaVector<DataType::Type>>(allocator->Adapter()); 1824b1994897Sopenharmony_ci ASSERT(input_types_ != nullptr); 1825b1994897Sopenharmony_ci input_types_->reserve(capacity); 1826b1994897Sopenharmony_ci ASSERT(input_types_->capacity() >= capacity); 1827b1994897Sopenharmony_ci } 1828b1994897Sopenharmony_ci void AddInputType(DataType::Type type) 1829b1994897Sopenharmony_ci { 1830b1994897Sopenharmony_ci ASSERT(input_types_ != nullptr); 1831b1994897Sopenharmony_ci input_types_->push_back(type); 1832b1994897Sopenharmony_ci } 1833b1994897Sopenharmony_ci ArenaVector<DataType::Type> *GetInputTypes() 1834b1994897Sopenharmony_ci { 1835b1994897Sopenharmony_ci return input_types_; 1836b1994897Sopenharmony_ci } 1837b1994897Sopenharmony_ci void CloneTypes(ArenaAllocator *allocator, InputTypesMixin *target_inst) const 1838b1994897Sopenharmony_ci { 1839b1994897Sopenharmony_ci if (UNLIKELY(input_types_ == nullptr)) { 1840b1994897Sopenharmony_ci return; 1841b1994897Sopenharmony_ci } 1842b1994897Sopenharmony_ci target_inst->AllocateInputTypes(allocator, input_types_->size()); 1843b1994897Sopenharmony_ci for (auto input_type : *input_types_) { 1844b1994897Sopenharmony_ci target_inst->AddInputType(input_type); 1845b1994897Sopenharmony_ci } 1846b1994897Sopenharmony_ci } 1847b1994897Sopenharmony_ci 1848b1994897Sopenharmony_ciprotected: 1849b1994897Sopenharmony_ci // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) 1850b1994897Sopenharmony_ci ArenaVector<DataType::Type> *input_types_ {nullptr}; 1851b1994897Sopenharmony_ci}; 1852b1994897Sopenharmony_ci 1853b1994897Sopenharmony_ci/** 1854b1994897Sopenharmony_ci * Compare instruction 1855b1994897Sopenharmony_ci */ 1856b1994897Sopenharmony_ci// NOLINTNEXTLINE(fuchsia-multiple-inheritance) 1857b1994897Sopenharmony_ciclass CompareInst : public InstWithOperandsType<ConditionMixin<FixedInputsInst2>> { 1858b1994897Sopenharmony_cipublic: 1859b1994897Sopenharmony_ci using BaseInst = InstWithOperandsType<ConditionMixin<FixedInputsInst2>>; 1860b1994897Sopenharmony_ci using BaseInst::BaseInst; 1861b1994897Sopenharmony_ci 1862b1994897Sopenharmony_ci CompareInst(Opcode opcode, DataType::Type type, uint32_t pc, ConditionCode cc) : BaseInst(opcode, type, pc) 1863b1994897Sopenharmony_ci { 1864b1994897Sopenharmony_ci SetCc(cc); 1865b1994897Sopenharmony_ci } 1866b1994897Sopenharmony_ci 1867b1994897Sopenharmony_ci DataType::Type GetInputType([[maybe_unused]] size_t index) const override 1868b1994897Sopenharmony_ci { 1869b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 1870b1994897Sopenharmony_ci return GetOperandsType(); 1871b1994897Sopenharmony_ci } 1872b1994897Sopenharmony_ci void DumpOpcode(std::ostream *out) const override; 1873b1994897Sopenharmony_ci 1874b1994897Sopenharmony_ci void SetVnObject(VnObject *vn_obj) override; 1875b1994897Sopenharmony_ci 1876b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 1877b1994897Sopenharmony_ci}; 1878b1994897Sopenharmony_ci 1879b1994897Sopenharmony_ci/** 1880b1994897Sopenharmony_ci * Mixin for AnyTypeMixin instructions 1881b1994897Sopenharmony_ci */ 1882b1994897Sopenharmony_citemplate <typename T> 1883b1994897Sopenharmony_ciclass AnyTypeMixin : public T { 1884b1994897Sopenharmony_cipublic: 1885b1994897Sopenharmony_ci using T::T; 1886b1994897Sopenharmony_ci 1887b1994897Sopenharmony_ci void SetAnyType(AnyBaseType any_type) 1888b1994897Sopenharmony_ci { 1889b1994897Sopenharmony_ci T::template SetField<AnyBaseTypeField>(any_type); 1890b1994897Sopenharmony_ci } 1891b1994897Sopenharmony_ci 1892b1994897Sopenharmony_ci AnyBaseType GetAnyType() const 1893b1994897Sopenharmony_ci { 1894b1994897Sopenharmony_ci return T::template GetField<AnyBaseTypeField>(); 1895b1994897Sopenharmony_ci } 1896b1994897Sopenharmony_ci 1897b1994897Sopenharmony_ciprotected: 1898b1994897Sopenharmony_ci using AnyBaseTypeField = 1899b1994897Sopenharmony_ci typename T::LastField::template NextField<AnyBaseType, MinimumBitsToStore(AnyBaseType::COUNT)>; 1900b1994897Sopenharmony_ci using LastField = AnyBaseTypeField; 1901b1994897Sopenharmony_ci}; 1902b1994897Sopenharmony_ci 1903b1994897Sopenharmony_ci/** 1904b1994897Sopenharmony_ci * CompareAnyTypeInst instruction 1905b1994897Sopenharmony_ci */ 1906b1994897Sopenharmony_ciclass CompareAnyTypeInst : public AnyTypeMixin<FixedInputsInst1> { 1907b1994897Sopenharmony_cipublic: 1908b1994897Sopenharmony_ci using BaseInst = AnyTypeMixin<FixedInputsInst1>; 1909b1994897Sopenharmony_ci using BaseInst::BaseInst; 1910b1994897Sopenharmony_ci 1911b1994897Sopenharmony_ci CompareAnyTypeInst(Opcode opcode, uint32_t pc, AnyBaseType any_type) : BaseInst(opcode, DataType::Type::BOOL, pc) 1912b1994897Sopenharmony_ci { 1913b1994897Sopenharmony_ci SetAnyType(any_type); 1914b1994897Sopenharmony_ci } 1915b1994897Sopenharmony_ci 1916b1994897Sopenharmony_ci DataType::Type GetInputType(size_t index) const override 1917b1994897Sopenharmony_ci { 1918b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 1919b1994897Sopenharmony_ci return GetInput(index).GetInst()->GetType(); 1920b1994897Sopenharmony_ci } 1921b1994897Sopenharmony_ci 1922b1994897Sopenharmony_ci void DumpOpcode(std::ostream *out) const override; 1923b1994897Sopenharmony_ci 1924b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override 1925b1994897Sopenharmony_ci { 1926b1994897Sopenharmony_ci auto clone = FixedInputsInst::Clone(targetGraph); 1927b1994897Sopenharmony_ci clone->CastToCompareAnyType()->SetAnyType(GetAnyType()); 1928b1994897Sopenharmony_ci return clone; 1929b1994897Sopenharmony_ci } 1930b1994897Sopenharmony_ci}; 1931b1994897Sopenharmony_ci 1932b1994897Sopenharmony_ci/** 1933b1994897Sopenharmony_ci * CastAnyTypeValueInst instruction 1934b1994897Sopenharmony_ci */ 1935b1994897Sopenharmony_ciclass CastAnyTypeValueInst : public AnyTypeMixin<FixedInputsInst1> { 1936b1994897Sopenharmony_cipublic: 1937b1994897Sopenharmony_ci using BaseInst = AnyTypeMixin<FixedInputsInst1>; 1938b1994897Sopenharmony_ci using BaseInst::BaseInst; 1939b1994897Sopenharmony_ci 1940b1994897Sopenharmony_ci CastAnyTypeValueInst(Opcode opcode, uint32_t pc, AnyBaseType any_type) 1941b1994897Sopenharmony_ci : BaseInst(opcode, AnyBaseTypeToDataType(any_type), pc) 1942b1994897Sopenharmony_ci { 1943b1994897Sopenharmony_ci SetAnyType(any_type); 1944b1994897Sopenharmony_ci } 1945b1994897Sopenharmony_ci 1946b1994897Sopenharmony_ci DataType::Type GetInputType(size_t index) const override 1947b1994897Sopenharmony_ci { 1948b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 1949b1994897Sopenharmony_ci return GetInput(index).GetInst()->GetType(); 1950b1994897Sopenharmony_ci } 1951b1994897Sopenharmony_ci 1952b1994897Sopenharmony_ci DataType::Type GetDeducedType() const 1953b1994897Sopenharmony_ci { 1954b1994897Sopenharmony_ci return AnyBaseTypeToDataType(GetAnyType()); 1955b1994897Sopenharmony_ci } 1956b1994897Sopenharmony_ci 1957b1994897Sopenharmony_ci void DumpOpcode(std::ostream *out) const override; 1958b1994897Sopenharmony_ci 1959b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override 1960b1994897Sopenharmony_ci { 1961b1994897Sopenharmony_ci auto targetGraphClone = FixedInputsInst::Clone(targetGraph); 1962b1994897Sopenharmony_ci CHECK_NOT_NULL(targetGraphClone); 1963b1994897Sopenharmony_ci auto clone = targetGraphClone->CastToCastAnyTypeValue(); 1964b1994897Sopenharmony_ci AnyBaseType any_type = GetAnyType(); 1965b1994897Sopenharmony_ci clone->SetAnyType(any_type); 1966b1994897Sopenharmony_ci clone->SetType(GetType()); 1967b1994897Sopenharmony_ci return clone; 1968b1994897Sopenharmony_ci } 1969b1994897Sopenharmony_ci}; 1970b1994897Sopenharmony_ci 1971b1994897Sopenharmony_ci/** 1972b1994897Sopenharmony_ci * CastValueToAnyTypeInst instruction 1973b1994897Sopenharmony_ci */ 1974b1994897Sopenharmony_ciclass CastValueToAnyTypeInst : public AnyTypeMixin<FixedInputsInst1> { 1975b1994897Sopenharmony_cipublic: 1976b1994897Sopenharmony_ci using BaseInst = AnyTypeMixin<FixedInputsInst1>; 1977b1994897Sopenharmony_ci using BaseInst::BaseInst; 1978b1994897Sopenharmony_ci 1979b1994897Sopenharmony_ci CastValueToAnyTypeInst(Opcode opcode, uint32_t pc) : BaseInst(opcode, DataType::ANY, pc) {} 1980b1994897Sopenharmony_ci 1981b1994897Sopenharmony_ci DataType::Type GetInputType(size_t index) const override 1982b1994897Sopenharmony_ci { 1983b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 1984b1994897Sopenharmony_ci return GetInput(index).GetInst()->GetType(); 1985b1994897Sopenharmony_ci } 1986b1994897Sopenharmony_ci 1987b1994897Sopenharmony_ci void DumpOpcode(std::ostream *out) const override; 1988b1994897Sopenharmony_ci 1989b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override 1990b1994897Sopenharmony_ci { 1991b1994897Sopenharmony_ci auto clone = FixedInputsInst::Clone(targetGraph)->CastToCastValueToAnyType(); 1992b1994897Sopenharmony_ci auto any_type = GetAnyType(); 1993b1994897Sopenharmony_ci clone->SetAnyType(any_type); 1994b1994897Sopenharmony_ci clone->SetType(GetType()); 1995b1994897Sopenharmony_ci return clone; 1996b1994897Sopenharmony_ci } 1997b1994897Sopenharmony_ci}; 1998b1994897Sopenharmony_ci 1999b1994897Sopenharmony_ci/** 2000b1994897Sopenharmony_ci * ConstantInst represent constant value. 2001b1994897Sopenharmony_ci * 2002b1994897Sopenharmony_ci * Available types: INT64, FLOAT32, FLOAT64, ANY. All integer types are stored as INT64 value. 2003b1994897Sopenharmony_ci * Once type of constant is set, it can't be changed anymore. 2004b1994897Sopenharmony_ci */ 2005b1994897Sopenharmony_ciclass ConstantInst : public Inst { 2006b1994897Sopenharmony_cipublic: 2007b1994897Sopenharmony_ci using Inst::Inst; 2008b1994897Sopenharmony_ci 2009b1994897Sopenharmony_ci template <typename T> 2010b1994897Sopenharmony_ci explicit ConstantInst(Opcode /* unused */, T value, bool support_int32 = false) : Inst(Opcode::Constant) 2011b1994897Sopenharmony_ci { 2012b1994897Sopenharmony_ci ASSERT(GetTypeFromCType<T>() != DataType::NO_TYPE); 2013b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-branch-clone) 2014b1994897Sopenharmony_ci if constexpr (GetTypeFromCType<T>() == DataType::FLOAT64) { 2015b1994897Sopenharmony_ci value_ = bit_cast<uint64_t, double>(value); 2016b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 2017b1994897Sopenharmony_ci } else if constexpr (GetTypeFromCType<T>() == DataType::FLOAT32) { 2018b1994897Sopenharmony_ci value_ = bit_cast<uint32_t, float>(value); 2019b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 2020b1994897Sopenharmony_ci } else if constexpr (GetTypeFromCType<T>() == DataType::ANY) { 2021b1994897Sopenharmony_ci value_ = value.Raw(); 2022b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 2023b1994897Sopenharmony_ci } else if (GetTypeFromCType<T>(support_int32) == DataType::INT32) { 2024b1994897Sopenharmony_ci value_ = static_cast<int32_t>(value); 2025b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 2026b1994897Sopenharmony_ci } else { 2027b1994897Sopenharmony_ci value_ = value; 2028b1994897Sopenharmony_ci } 2029b1994897Sopenharmony_ci 2030b1994897Sopenharmony_ci SetType(GetTypeFromCType<T>(support_int32)); 2031b1994897Sopenharmony_ci } 2032b1994897Sopenharmony_ci 2033b1994897Sopenharmony_ci uint64_t GetRawValue() const 2034b1994897Sopenharmony_ci { 2035b1994897Sopenharmony_ci return value_; 2036b1994897Sopenharmony_ci } 2037b1994897Sopenharmony_ci 2038b1994897Sopenharmony_ci uint32_t GetInt32Value() const 2039b1994897Sopenharmony_ci { 2040b1994897Sopenharmony_ci ASSERT(GetType() == DataType::INT32); 2041b1994897Sopenharmony_ci return static_cast<uint32_t>(value_); 2042b1994897Sopenharmony_ci } 2043b1994897Sopenharmony_ci 2044b1994897Sopenharmony_ci uint64_t GetInt64Value() const 2045b1994897Sopenharmony_ci { 2046b1994897Sopenharmony_ci ASSERT(GetType() == DataType::INT64); 2047b1994897Sopenharmony_ci return value_; 2048b1994897Sopenharmony_ci } 2049b1994897Sopenharmony_ci 2050b1994897Sopenharmony_ci uint64_t GetIntValue() const 2051b1994897Sopenharmony_ci { 2052b1994897Sopenharmony_ci ASSERT(GetType() == DataType::INT64 || GetType() == DataType::INT32); 2053b1994897Sopenharmony_ci return value_; 2054b1994897Sopenharmony_ci } 2055b1994897Sopenharmony_ci 2056b1994897Sopenharmony_ci float GetFloatValue() const 2057b1994897Sopenharmony_ci { 2058b1994897Sopenharmony_ci ASSERT(GetType() == DataType::FLOAT32); 2059b1994897Sopenharmony_ci return bit_cast<float, uint32_t>(static_cast<uint32_t>(value_)); 2060b1994897Sopenharmony_ci } 2061b1994897Sopenharmony_ci 2062b1994897Sopenharmony_ci double GetDoubleValue() const 2063b1994897Sopenharmony_ci { 2064b1994897Sopenharmony_ci ASSERT(GetType() == DataType::FLOAT64); 2065b1994897Sopenharmony_ci return bit_cast<double, uint64_t>(value_); 2066b1994897Sopenharmony_ci } 2067b1994897Sopenharmony_ci 2068b1994897Sopenharmony_ci ConstantInst *GetNextConst() 2069b1994897Sopenharmony_ci { 2070b1994897Sopenharmony_ci return next_const_; 2071b1994897Sopenharmony_ci } 2072b1994897Sopenharmony_ci void SetNextConst(ConstantInst *next_const) 2073b1994897Sopenharmony_ci { 2074b1994897Sopenharmony_ci next_const_ = next_const; 2075b1994897Sopenharmony_ci } 2076b1994897Sopenharmony_ci 2077b1994897Sopenharmony_ci template <typename T> 2078b1994897Sopenharmony_ci static constexpr DataType::Type GetTypeFromCType(bool support_int32 = false) 2079b1994897Sopenharmony_ci { 2080b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-branch-clone) 2081b1994897Sopenharmony_ci if constexpr (std::is_integral_v<T>) { 2082b1994897Sopenharmony_ci if (support_int32 && sizeof(T) == sizeof(uint32_t)) { 2083b1994897Sopenharmony_ci return DataType::INT32; 2084b1994897Sopenharmony_ci } 2085b1994897Sopenharmony_ci return DataType::INT64; 2086b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 2087b1994897Sopenharmony_ci } else if constexpr (std::is_same_v<T, float>) { 2088b1994897Sopenharmony_ci return DataType::FLOAT32; 2089b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 2090b1994897Sopenharmony_ci } else if constexpr (std::is_same_v<T, double>) { 2091b1994897Sopenharmony_ci return DataType::FLOAT64; 2092b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 2093b1994897Sopenharmony_ci } else if constexpr (std::is_same_v<T, DataType::Any>) { 2094b1994897Sopenharmony_ci return DataType::ANY; 2095b1994897Sopenharmony_ci } 2096b1994897Sopenharmony_ci return DataType::NO_TYPE; 2097b1994897Sopenharmony_ci } 2098b1994897Sopenharmony_ci 2099b1994897Sopenharmony_ci inline bool IsEqualConst(double value, [[maybe_unused]] bool support_int32 = false) 2100b1994897Sopenharmony_ci { 2101b1994897Sopenharmony_ci return IsEqualConst(DataType::FLOAT64, bit_cast<uint64_t, double>(value)); 2102b1994897Sopenharmony_ci } 2103b1994897Sopenharmony_ci inline bool IsEqualConst(float value, [[maybe_unused]] bool support_int32 = false) 2104b1994897Sopenharmony_ci { 2105b1994897Sopenharmony_ci return IsEqualConst(DataType::FLOAT32, bit_cast<uint32_t, float>(value)); 2106b1994897Sopenharmony_ci } 2107b1994897Sopenharmony_ci inline bool IsEqualConst(DataType::Any value, [[maybe_unused]] bool support_int32 = false) 2108b1994897Sopenharmony_ci { 2109b1994897Sopenharmony_ci return IsEqualConst(DataType::ANY, value.Raw()); 2110b1994897Sopenharmony_ci } 2111b1994897Sopenharmony_ci inline bool IsEqualConst(DataType::Type type, uint64_t value) 2112b1994897Sopenharmony_ci { 2113b1994897Sopenharmony_ci return GetType() == type && value_ == value; 2114b1994897Sopenharmony_ci } 2115b1994897Sopenharmony_ci template <typename T> 2116b1994897Sopenharmony_ci inline bool IsEqualConst(T value, bool support_int32 = false) 2117b1994897Sopenharmony_ci { 2118b1994897Sopenharmony_ci static_assert(GetTypeFromCType<T>() == DataType::INT64); 2119b1994897Sopenharmony_ci if (support_int32 && sizeof(T) == sizeof(uint32_t)) { 2120b1994897Sopenharmony_ci return (GetType() == DataType::INT32 && static_cast<int32_t>(value_) == static_cast<int32_t>(value)); 2121b1994897Sopenharmony_ci } 2122b1994897Sopenharmony_ci return (GetType() == DataType::INT64 && value_ == static_cast<uint64_t>(value)); 2123b1994897Sopenharmony_ci } 2124b1994897Sopenharmony_ci 2125b1994897Sopenharmony_ci inline bool IsEqualConstAllTypes(int64_t value, bool support_int32 = false) 2126b1994897Sopenharmony_ci { 2127b1994897Sopenharmony_ci return IsEqualConst(value, support_int32) || IsEqualConst(static_cast<float>(value)) || 2128b1994897Sopenharmony_ci IsEqualConst(static_cast<double>(value)); 2129b1994897Sopenharmony_ci } 2130b1994897Sopenharmony_ci 2131b1994897Sopenharmony_ci bool IsBoolConst() const override 2132b1994897Sopenharmony_ci { 2133b1994897Sopenharmony_ci ASSERT(IsConst()); 2134b1994897Sopenharmony_ci return GetType() == DataType::INT64 && (GetIntValue() == 0 || GetIntValue() == 1); 2135b1994897Sopenharmony_ci } 2136b1994897Sopenharmony_ci 2137b1994897Sopenharmony_ci void SetImmTableSlot(ImmTableSlot imm_slot) 2138b1994897Sopenharmony_ci { 2139b1994897Sopenharmony_ci imm_slot_ = imm_slot; 2140b1994897Sopenharmony_ci } 2141b1994897Sopenharmony_ci 2142b1994897Sopenharmony_ci auto GetImmTableSlot() const 2143b1994897Sopenharmony_ci { 2144b1994897Sopenharmony_ci return imm_slot_; 2145b1994897Sopenharmony_ci } 2146b1994897Sopenharmony_ci 2147b1994897Sopenharmony_ci bool DumpInputs(std::ostream *out) const override; 2148b1994897Sopenharmony_ci 2149b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 2150b1994897Sopenharmony_ci 2151b1994897Sopenharmony_ciprivate: 2152b1994897Sopenharmony_ci uint64_t value_ {0}; 2153b1994897Sopenharmony_ci ConstantInst *next_const_ {nullptr}; 2154b1994897Sopenharmony_ci ImmTableSlot imm_slot_ {INVALID_IMM_TABLE_SLOT}; 2155b1994897Sopenharmony_ci}; 2156b1994897Sopenharmony_ci 2157b1994897Sopenharmony_ci// Type describing the purpose of the SpillFillInst. 2158b1994897Sopenharmony_ci// RegAlloc may use this information to preserve correct order of several SpillFillInst 2159b1994897Sopenharmony_ci// instructions placed along each other in the graph. 2160b1994897Sopenharmony_cienum SpillFillType { 2161b1994897Sopenharmony_ci UNKNOWN, 2162b1994897Sopenharmony_ci INPUT_FILL, 2163b1994897Sopenharmony_ci CONNECT_SPLIT_SIBLINGS, 2164b1994897Sopenharmony_ci SPLIT_MOVE, 2165b1994897Sopenharmony_ci}; 2166b1994897Sopenharmony_ci 2167b1994897Sopenharmony_ciclass SpillFillInst : public FixedInputsInst0 { 2168b1994897Sopenharmony_cipublic: 2169b1994897Sopenharmony_ci explicit SpillFillInst(ArenaAllocator *allocator, Opcode opcode) 2170b1994897Sopenharmony_ci : FixedInputsInst0(opcode), spill_fills_(allocator->Adapter()) 2171b1994897Sopenharmony_ci { 2172b1994897Sopenharmony_ci } 2173b1994897Sopenharmony_ci 2174b1994897Sopenharmony_ci void AddMove(Register src, Register dst, DataType::Type type) 2175b1994897Sopenharmony_ci { 2176b1994897Sopenharmony_ci AddSpillFill(Location::MakeRegister(src, type), Location::MakeRegister(dst, type), type); 2177b1994897Sopenharmony_ci } 2178b1994897Sopenharmony_ci 2179b1994897Sopenharmony_ci void AddSpill(Register src, StackSlot dst, DataType::Type type) 2180b1994897Sopenharmony_ci { 2181b1994897Sopenharmony_ci AddSpillFill(Location::MakeRegister(src, type), Location::MakeStackSlot(dst), type); 2182b1994897Sopenharmony_ci } 2183b1994897Sopenharmony_ci 2184b1994897Sopenharmony_ci void AddFill(StackSlot src, Register dst, DataType::Type type) 2185b1994897Sopenharmony_ci { 2186b1994897Sopenharmony_ci AddSpillFill(Location::MakeStackSlot(src), Location::MakeRegister(dst, type), type); 2187b1994897Sopenharmony_ci } 2188b1994897Sopenharmony_ci 2189b1994897Sopenharmony_ci void AddMemCopy(StackSlot src, StackSlot dst, DataType::Type type) 2190b1994897Sopenharmony_ci { 2191b1994897Sopenharmony_ci AddSpillFill(Location::MakeStackSlot(src), Location::MakeStackSlot(dst), type); 2192b1994897Sopenharmony_ci } 2193b1994897Sopenharmony_ci 2194b1994897Sopenharmony_ci void AddSpillFill(const SpillFillData &spill_fill) 2195b1994897Sopenharmony_ci { 2196b1994897Sopenharmony_ci spill_fills_.emplace_back(spill_fill); 2197b1994897Sopenharmony_ci } 2198b1994897Sopenharmony_ci 2199b1994897Sopenharmony_ci void AddSpillFill(const Location &src, const Location &dst, DataType::Type type) 2200b1994897Sopenharmony_ci { 2201b1994897Sopenharmony_ci spill_fills_.emplace_back(SpillFillData {src.GetKind(), dst.GetKind(), src.GetValue(), dst.GetValue(), type}); 2202b1994897Sopenharmony_ci } 2203b1994897Sopenharmony_ci 2204b1994897Sopenharmony_ci const ArenaVector<SpillFillData> &GetSpillFills() const 2205b1994897Sopenharmony_ci { 2206b1994897Sopenharmony_ci return spill_fills_; 2207b1994897Sopenharmony_ci } 2208b1994897Sopenharmony_ci 2209b1994897Sopenharmony_ci ArenaVector<SpillFillData> &GetSpillFills() 2210b1994897Sopenharmony_ci { 2211b1994897Sopenharmony_ci return spill_fills_; 2212b1994897Sopenharmony_ci } 2213b1994897Sopenharmony_ci 2214b1994897Sopenharmony_ci const SpillFillData &GetSpillFill(size_t n) const 2215b1994897Sopenharmony_ci { 2216b1994897Sopenharmony_ci ASSERT(n < spill_fills_.size()); 2217b1994897Sopenharmony_ci return spill_fills_[n]; 2218b1994897Sopenharmony_ci } 2219b1994897Sopenharmony_ci 2220b1994897Sopenharmony_ci SpillFillData &GetSpillFill(size_t n) 2221b1994897Sopenharmony_ci { 2222b1994897Sopenharmony_ci ASSERT(n < spill_fills_.size()); 2223b1994897Sopenharmony_ci return spill_fills_[n]; 2224b1994897Sopenharmony_ci } 2225b1994897Sopenharmony_ci 2226b1994897Sopenharmony_ci void RemoveSpillFill(size_t n) 2227b1994897Sopenharmony_ci { 2228b1994897Sopenharmony_ci ASSERT(n < spill_fills_.size()); 2229b1994897Sopenharmony_ci spill_fills_.erase(spill_fills_.begin() + n); 2230b1994897Sopenharmony_ci } 2231b1994897Sopenharmony_ci 2232b1994897Sopenharmony_ci // Get register number, holded by n-th spill-fill 2233b1994897Sopenharmony_ci Register GetInputReg(size_t n) const 2234b1994897Sopenharmony_ci { 2235b1994897Sopenharmony_ci ASSERT(n < spill_fills_.size()); 2236b1994897Sopenharmony_ci ASSERT(spill_fills_[n].SrcType() == LocationType::REGISTER); 2237b1994897Sopenharmony_ci return spill_fills_[n].SrcValue(); 2238b1994897Sopenharmony_ci } 2239b1994897Sopenharmony_ci 2240b1994897Sopenharmony_ci void ClearSpillFills() 2241b1994897Sopenharmony_ci { 2242b1994897Sopenharmony_ci spill_fills_.clear(); 2243b1994897Sopenharmony_ci } 2244b1994897Sopenharmony_ci 2245b1994897Sopenharmony_ci SpillFillType GetSpillFillType() const 2246b1994897Sopenharmony_ci { 2247b1994897Sopenharmony_ci return sf_type_; 2248b1994897Sopenharmony_ci } 2249b1994897Sopenharmony_ci 2250b1994897Sopenharmony_ci void SetSpillFillType(SpillFillType type) 2251b1994897Sopenharmony_ci { 2252b1994897Sopenharmony_ci sf_type_ = type; 2253b1994897Sopenharmony_ci } 2254b1994897Sopenharmony_ci 2255b1994897Sopenharmony_ci bool DumpInputs(std::ostream *out) const override; 2256b1994897Sopenharmony_ci 2257b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 2258b1994897Sopenharmony_ci 2259b1994897Sopenharmony_ciprivate: 2260b1994897Sopenharmony_ci ArenaVector<SpillFillData> spill_fills_; 2261b1994897Sopenharmony_ci SpillFillType sf_type_ {UNKNOWN}; 2262b1994897Sopenharmony_ci}; 2263b1994897Sopenharmony_ci 2264b1994897Sopenharmony_ci// NOLINTNEXTLINE(fuchsia-multiple-inheritance) 2265b1994897Sopenharmony_ciclass ParameterInst : public Inst, public LocationDataMixin { 2266b1994897Sopenharmony_cipublic: 2267b1994897Sopenharmony_ci using Inst::Inst; 2268b1994897Sopenharmony_ci 2269b1994897Sopenharmony_ci explicit ParameterInst(Opcode /* unused */, uint16_t arg_number) : Inst(Opcode::Parameter), arg_number_(arg_number) 2270b1994897Sopenharmony_ci { 2271b1994897Sopenharmony_ci } 2272b1994897Sopenharmony_ci uint16_t GetArgNumber() const 2273b1994897Sopenharmony_ci { 2274b1994897Sopenharmony_ci return arg_number_; 2275b1994897Sopenharmony_ci } 2276b1994897Sopenharmony_ci 2277b1994897Sopenharmony_ci void SetArgNumber(uint16_t arg_number) 2278b1994897Sopenharmony_ci { 2279b1994897Sopenharmony_ci arg_number_ = arg_number; 2280b1994897Sopenharmony_ci } 2281b1994897Sopenharmony_ci 2282b1994897Sopenharmony_ci bool DumpInputs(std::ostream *out) const override; 2283b1994897Sopenharmony_ci 2284b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 2285b1994897Sopenharmony_ci 2286b1994897Sopenharmony_ciprivate: 2287b1994897Sopenharmony_ci uint16_t arg_number_ {0}; 2288b1994897Sopenharmony_ci}; 2289b1994897Sopenharmony_ci 2290b1994897Sopenharmony_ciinline bool IsZeroConstant(const Inst *inst) 2291b1994897Sopenharmony_ci{ 2292b1994897Sopenharmony_ci return inst->IsConst() && inst->GetType() == DataType::INT64 && inst->CastToConstant()->GetIntValue() == 0; 2293b1994897Sopenharmony_ci} 2294b1994897Sopenharmony_ci 2295b1994897Sopenharmony_ciinline bool IsZeroConstantOrNullPtr(const Inst *inst) 2296b1994897Sopenharmony_ci{ 2297b1994897Sopenharmony_ci return IsZeroConstant(inst); 2298b1994897Sopenharmony_ci} 2299b1994897Sopenharmony_ci 2300b1994897Sopenharmony_ci/** 2301b1994897Sopenharmony_ci * Phi instruction 2302b1994897Sopenharmony_ci */ 2303b1994897Sopenharmony_ciclass PhiInst : public AnyTypeMixin<DynamicInputsInst> { 2304b1994897Sopenharmony_cipublic: 2305b1994897Sopenharmony_ci using BaseInst = AnyTypeMixin<DynamicInputsInst>; 2306b1994897Sopenharmony_ci using BaseInst::BaseInst; 2307b1994897Sopenharmony_ci /// Get basic block corresponding to given input index. Returned pointer to basic block, can't be nullptr 2308b1994897Sopenharmony_ci BasicBlock *GetPhiInputBb(unsigned index); 2309b1994897Sopenharmony_ci const BasicBlock *GetPhiInputBb(unsigned index) const 2310b1994897Sopenharmony_ci { 2311b1994897Sopenharmony_ci return (const_cast<PhiInst *>(this))->GetPhiInputBb(index); 2312b1994897Sopenharmony_ci } 2313b1994897Sopenharmony_ci 2314b1994897Sopenharmony_ci uint32_t GetPhiInputBbNum(unsigned index) const 2315b1994897Sopenharmony_ci { 2316b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2317b1994897Sopenharmony_ci return GetDynamicOperands()->GetUser(index)->GetBbNum(); 2318b1994897Sopenharmony_ci } 2319b1994897Sopenharmony_ci 2320b1994897Sopenharmony_ci void SetPhiInputBbNum(unsigned index, uint32_t bb_num) 2321b1994897Sopenharmony_ci { 2322b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2323b1994897Sopenharmony_ci GetDynamicOperands()->GetUser(index)->SetBbNum(bb_num); 2324b1994897Sopenharmony_ci } 2325b1994897Sopenharmony_ci 2326b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override 2327b1994897Sopenharmony_ci { 2328b1994897Sopenharmony_ci auto clone = DynamicInputsInst::Clone(targetGraph); 2329b1994897Sopenharmony_ci clone->CastToPhi()->SetAnyType(GetAnyType()); 2330b1994897Sopenharmony_ci return clone; 2331b1994897Sopenharmony_ci } 2332b1994897Sopenharmony_ci 2333b1994897Sopenharmony_ci AnyBaseType GetAssumedAnyType() 2334b1994897Sopenharmony_ci { 2335b1994897Sopenharmony_ci return GetAnyType(); 2336b1994897Sopenharmony_ci } 2337b1994897Sopenharmony_ci 2338b1994897Sopenharmony_ci /// Get input instruction corresponding to the given basic block, can't be null. 2339b1994897Sopenharmony_ci Inst *GetPhiInput(BasicBlock *bb); 2340b1994897Sopenharmony_ci Inst *GetPhiDataflowInput(BasicBlock *bb); 2341b1994897Sopenharmony_ci bool DumpInputs(std::ostream *out) const override; 2342b1994897Sopenharmony_ci 2343b1994897Sopenharmony_ci // Get index of the given block in phi inputs 2344b1994897Sopenharmony_ci size_t GetPredBlockIndex(const BasicBlock *block) const; 2345b1994897Sopenharmony_ci 2346b1994897Sopenharmony_ciprotected: 2347b1994897Sopenharmony_ci using FlagIsLive = LastField::NextFlag; 2348b1994897Sopenharmony_ci using LastField = FlagIsLive; 2349b1994897Sopenharmony_ci}; 2350b1994897Sopenharmony_ci 2351b1994897Sopenharmony_ci/** 2352b1994897Sopenharmony_ci * Immediate for SavaState: 2353b1994897Sopenharmony_ci * value - constant value to be stored 2354b1994897Sopenharmony_ci * vreg - virtual register number 2355b1994897Sopenharmony_ci */ 2356b1994897Sopenharmony_cistruct SaveStateImm { 2357b1994897Sopenharmony_ci uint64_t value; 2358b1994897Sopenharmony_ci uint16_t vreg; 2359b1994897Sopenharmony_ci DataType::Type type; 2360b1994897Sopenharmony_ci bool is_acc; 2361b1994897Sopenharmony_ci}; 2362b1994897Sopenharmony_ci 2363b1994897Sopenharmony_ci/** 2364b1994897Sopenharmony_ci * Frame state saving instruction 2365b1994897Sopenharmony_ci * Aims to save pbc registers before calling something that can raise exception 2366b1994897Sopenharmony_ci */ 2367b1994897Sopenharmony_ci// NOLINTNEXTLINE(fuchsia-multiple-inheritance) 2368b1994897Sopenharmony_ciclass SaveStateInst : public DynamicInputsInst { 2369b1994897Sopenharmony_cipublic: 2370b1994897Sopenharmony_ci using DynamicInputsInst::DynamicInputsInst; 2371b1994897Sopenharmony_ci 2372b1994897Sopenharmony_ci bool DumpInputs(std::ostream *out) const override; 2373b1994897Sopenharmony_ci 2374b1994897Sopenharmony_ci void SetVirtualRegister(size_t index, VirtualRegister reg) 2375b1994897Sopenharmony_ci { 2376b1994897Sopenharmony_ci static_assert(sizeof(reg) <= sizeof(uintptr_t), "Consider passing the register by reference"); 2377b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2378b1994897Sopenharmony_ci GetDynamicOperands()->GetUser(index)->SetVirtualRegister(reg); 2379b1994897Sopenharmony_ci } 2380b1994897Sopenharmony_ci 2381b1994897Sopenharmony_ci VirtualRegister GetVirtualRegister(size_t index) const 2382b1994897Sopenharmony_ci { 2383b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2384b1994897Sopenharmony_ci return GetDynamicOperands()->GetUser(index)->GetVirtualRegister(); 2385b1994897Sopenharmony_ci } 2386b1994897Sopenharmony_ci 2387b1994897Sopenharmony_ci bool Verify() const 2388b1994897Sopenharmony_ci { 2389b1994897Sopenharmony_ci for (size_t i {0}; i < GetInputsCount(); ++i) { 2390b1994897Sopenharmony_ci if (static_cast<uint16_t>(GetVirtualRegister(i)) == VirtualRegister::INVALID) { 2391b1994897Sopenharmony_ci return false; 2392b1994897Sopenharmony_ci } 2393b1994897Sopenharmony_ci } 2394b1994897Sopenharmony_ci return true; 2395b1994897Sopenharmony_ci } 2396b1994897Sopenharmony_ci 2397b1994897Sopenharmony_ci bool RemoveNumericInputs() 2398b1994897Sopenharmony_ci { 2399b1994897Sopenharmony_ci size_t idx = 0; 2400b1994897Sopenharmony_ci size_t inputs_count = GetInputsCount(); 2401b1994897Sopenharmony_ci bool removed = false; 2402b1994897Sopenharmony_ci while (idx < inputs_count) { 2403b1994897Sopenharmony_ci auto input_inst = GetInput(idx).GetInst(); 2404b1994897Sopenharmony_ci if (DataType::IsTypeNumeric(input_inst->GetType())) { 2405b1994897Sopenharmony_ci RemoveInput(idx); 2406b1994897Sopenharmony_ci inputs_count--; 2407b1994897Sopenharmony_ci removed = true; 2408b1994897Sopenharmony_ci } else { 2409b1994897Sopenharmony_ci idx++; 2410b1994897Sopenharmony_ci } 2411b1994897Sopenharmony_ci } 2412b1994897Sopenharmony_ci return removed; 2413b1994897Sopenharmony_ci } 2414b1994897Sopenharmony_ci 2415b1994897Sopenharmony_ci DataType::Type GetInputType([[maybe_unused]] size_t index) const override 2416b1994897Sopenharmony_ci { 2417b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2418b1994897Sopenharmony_ci return DataType::NO_TYPE; 2419b1994897Sopenharmony_ci } 2420b1994897Sopenharmony_ci auto GetMethod() const 2421b1994897Sopenharmony_ci { 2422b1994897Sopenharmony_ci return method_; 2423b1994897Sopenharmony_ci } 2424b1994897Sopenharmony_ci auto SetMethod(void *method) 2425b1994897Sopenharmony_ci { 2426b1994897Sopenharmony_ci method_ = method; 2427b1994897Sopenharmony_ci } 2428b1994897Sopenharmony_ci 2429b1994897Sopenharmony_ci void AppendImmediate(uint64_t imm, uint16_t vreg, DataType::Type type, bool is_acc); 2430b1994897Sopenharmony_ci 2431b1994897Sopenharmony_ci const ArenaVector<SaveStateImm> *GetImmediates() const 2432b1994897Sopenharmony_ci { 2433b1994897Sopenharmony_ci return immediates_; 2434b1994897Sopenharmony_ci } 2435b1994897Sopenharmony_ci 2436b1994897Sopenharmony_ci const SaveStateImm &GetImmediate(size_t index) const 2437b1994897Sopenharmony_ci { 2438b1994897Sopenharmony_ci ASSERT(immediates_ != nullptr && index < immediates_->size()); 2439b1994897Sopenharmony_ci return (*immediates_)[index]; 2440b1994897Sopenharmony_ci } 2441b1994897Sopenharmony_ci 2442b1994897Sopenharmony_ci void AllocateImmediates(ArenaAllocator *allocator, size_t size = 0); 2443b1994897Sopenharmony_ci 2444b1994897Sopenharmony_ci size_t GetImmediatesCount() const 2445b1994897Sopenharmony_ci { 2446b1994897Sopenharmony_ci if (immediates_ == nullptr) { 2447b1994897Sopenharmony_ci return 0; 2448b1994897Sopenharmony_ci } 2449b1994897Sopenharmony_ci return immediates_->size(); 2450b1994897Sopenharmony_ci } 2451b1994897Sopenharmony_ci 2452b1994897Sopenharmony_ci void SetRootsRegMaskBit(size_t reg) 2453b1994897Sopenharmony_ci { 2454b1994897Sopenharmony_ci ASSERT(reg < roots_regs_mask_.size()); 2455b1994897Sopenharmony_ci roots_regs_mask_.set(reg); 2456b1994897Sopenharmony_ci } 2457b1994897Sopenharmony_ci 2458b1994897Sopenharmony_ci void SetRootsStackMaskBit(size_t slot) 2459b1994897Sopenharmony_ci { 2460b1994897Sopenharmony_ci if (roots_stack_mask_ != nullptr) { 2461b1994897Sopenharmony_ci roots_stack_mask_->SetBit(slot); 2462b1994897Sopenharmony_ci } 2463b1994897Sopenharmony_ci } 2464b1994897Sopenharmony_ci 2465b1994897Sopenharmony_ci ArenaBitVector *GetRootsStackMask() 2466b1994897Sopenharmony_ci { 2467b1994897Sopenharmony_ci return roots_stack_mask_; 2468b1994897Sopenharmony_ci } 2469b1994897Sopenharmony_ci 2470b1994897Sopenharmony_ci auto &GetRootsRegsMask() 2471b1994897Sopenharmony_ci { 2472b1994897Sopenharmony_ci return roots_regs_mask_; 2473b1994897Sopenharmony_ci } 2474b1994897Sopenharmony_ci 2475b1994897Sopenharmony_ci void CreateRootsStackMask(ArenaAllocator *allocator) 2476b1994897Sopenharmony_ci { 2477b1994897Sopenharmony_ci ASSERT(roots_stack_mask_ == nullptr); 2478b1994897Sopenharmony_ci roots_stack_mask_ = allocator->New<ArenaBitVector>(allocator); 2479b1994897Sopenharmony_ci CHECK_NOT_NULL(roots_stack_mask_); 2480b1994897Sopenharmony_ci roots_stack_mask_->Reset(); 2481b1994897Sopenharmony_ci } 2482b1994897Sopenharmony_ci 2483b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 2484b1994897Sopenharmony_ci#ifndef NDEBUG 2485b1994897Sopenharmony_ci void SetInputsWereDeleted() 2486b1994897Sopenharmony_ci { 2487b1994897Sopenharmony_ci SetField<FlagInputsWereDeleted>(true); 2488b1994897Sopenharmony_ci } 2489b1994897Sopenharmony_ci 2490b1994897Sopenharmony_ci bool GetInputsWereDeleted() 2491b1994897Sopenharmony_ci { 2492b1994897Sopenharmony_ci return GetField<FlagInputsWereDeleted>(); 2493b1994897Sopenharmony_ci } 2494b1994897Sopenharmony_ci#endif 2495b1994897Sopenharmony_ci 2496b1994897Sopenharmony_ciprotected: 2497b1994897Sopenharmony_ci#ifndef NDEBUG 2498b1994897Sopenharmony_ci using FlagInputsWereDeleted = LastField::NextFlag; 2499b1994897Sopenharmony_ci using LastField = FlagInputsWereDeleted; 2500b1994897Sopenharmony_ci#endif 2501b1994897Sopenharmony_ci 2502b1994897Sopenharmony_ciprivate: 2503b1994897Sopenharmony_ci ArenaVector<SaveStateImm> *immediates_ {nullptr}; 2504b1994897Sopenharmony_ci void *method_ {nullptr}; 2505b1994897Sopenharmony_ci /// If instruction is in the inlined graph, this variable points to the inliner's call instruction. 2506b1994897Sopenharmony_ci ArenaBitVector *roots_stack_mask_ {nullptr}; 2507b1994897Sopenharmony_ci std::bitset<BITS_PER_UINT32> roots_regs_mask_ {0}; 2508b1994897Sopenharmony_ci}; 2509b1994897Sopenharmony_ci 2510b1994897Sopenharmony_ci// NOLINTNEXTLINE(fuchsia-multiple-inheritance) 2511b1994897Sopenharmony_ciclass IntrinsicInst : public InlinedInstMixin<DynamicInputsInst>, public InputTypesMixin { 2512b1994897Sopenharmony_cipublic: 2513b1994897Sopenharmony_ci using Base = InlinedInstMixin<DynamicInputsInst>; 2514b1994897Sopenharmony_ci using Base::Base; 2515b1994897Sopenharmony_ci using IntrinsicId = RuntimeInterface::IntrinsicId; 2516b1994897Sopenharmony_ci 2517b1994897Sopenharmony_ci IntrinsicInst(Opcode opcode, IntrinsicId intrinsic_id) : Base(opcode), intrinsic_id_(intrinsic_id) {} 2518b1994897Sopenharmony_ci 2519b1994897Sopenharmony_ci IntrinsicInst(Opcode opcode, DataType::Type type, uint32_t pc, IntrinsicId intrinsic_id) 2520b1994897Sopenharmony_ci : Base(opcode, type, pc), intrinsic_id_(intrinsic_id) {} 2521b1994897Sopenharmony_ci 2522b1994897Sopenharmony_ci IntrinsicId GetIntrinsicId() const 2523b1994897Sopenharmony_ci { 2524b1994897Sopenharmony_ci return intrinsic_id_; 2525b1994897Sopenharmony_ci } 2526b1994897Sopenharmony_ci 2527b1994897Sopenharmony_ci void SetIntrinsicId(IntrinsicId intrinsic_id) 2528b1994897Sopenharmony_ci { 2529b1994897Sopenharmony_ci intrinsic_id_ = intrinsic_id; 2530b1994897Sopenharmony_ci } 2531b1994897Sopenharmony_ci 2532b1994897Sopenharmony_ci DataType::Type GetInputType(size_t index) const override 2533b1994897Sopenharmony_ci { 2534b1994897Sopenharmony_ci ASSERT(input_types_ != nullptr); 2535b1994897Sopenharmony_ci ASSERT(index < input_types_->size()); 2536b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2537b1994897Sopenharmony_ci return (*input_types_)[index]; 2538b1994897Sopenharmony_ci } 2539b1994897Sopenharmony_ci 2540b1994897Sopenharmony_ci const ArenaVector<uint32_t> &GetImms() 2541b1994897Sopenharmony_ci { 2542b1994897Sopenharmony_ci return *imms_; 2543b1994897Sopenharmony_ci } 2544b1994897Sopenharmony_ci 2545b1994897Sopenharmony_ci const ArenaVector<uint32_t> &GetImms() const 2546b1994897Sopenharmony_ci { 2547b1994897Sopenharmony_ci return *imms_; 2548b1994897Sopenharmony_ci } 2549b1994897Sopenharmony_ci 2550b1994897Sopenharmony_ci bool HasImms() const 2551b1994897Sopenharmony_ci { 2552b1994897Sopenharmony_ci return imms_ != nullptr; 2553b1994897Sopenharmony_ci } 2554b1994897Sopenharmony_ci 2555b1994897Sopenharmony_ci void AddImm(ArenaAllocator *allocator, uint32_t imm) 2556b1994897Sopenharmony_ci { 2557b1994897Sopenharmony_ci if (imms_ == nullptr) { 2558b1994897Sopenharmony_ci imms_ = allocator->New<ArenaVector<uint32_t>>(allocator->Adapter()); 2559b1994897Sopenharmony_ci CHECK_NOT_NULL(imms_); 2560b1994897Sopenharmony_ci } 2561b1994897Sopenharmony_ci imms_->push_back(imm); 2562b1994897Sopenharmony_ci } 2563b1994897Sopenharmony_ci 2564b1994897Sopenharmony_ci bool IsNativeCall() const; 2565b1994897Sopenharmony_ci 2566b1994897Sopenharmony_ci bool HasArgumentsOnStack() const 2567b1994897Sopenharmony_ci { 2568b1994897Sopenharmony_ci return GetField<ArgumentsOnStack>(); 2569b1994897Sopenharmony_ci } 2570b1994897Sopenharmony_ci 2571b1994897Sopenharmony_ci void SetArgumentsOnStack() 2572b1994897Sopenharmony_ci { 2573b1994897Sopenharmony_ci SetField<ArgumentsOnStack>(true); 2574b1994897Sopenharmony_ci } 2575b1994897Sopenharmony_ci 2576b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 2577b1994897Sopenharmony_ci 2578b1994897Sopenharmony_ci bool CanBeInlined() 2579b1994897Sopenharmony_ci { 2580b1994897Sopenharmony_ci return IsInlined(); 2581b1994897Sopenharmony_ci } 2582b1994897Sopenharmony_ci 2583b1994897Sopenharmony_ci void SetRelocate() 2584b1994897Sopenharmony_ci { 2585b1994897Sopenharmony_ci SetField<Relocate>(true); 2586b1994897Sopenharmony_ci } 2587b1994897Sopenharmony_ci 2588b1994897Sopenharmony_ci bool GetRelocate() const 2589b1994897Sopenharmony_ci { 2590b1994897Sopenharmony_ci return GetField<Relocate>(); 2591b1994897Sopenharmony_ci } 2592b1994897Sopenharmony_ci 2593b1994897Sopenharmony_ci void DumpOpcode(std::ostream *out) const override; 2594b1994897Sopenharmony_ci 2595b1994897Sopenharmony_ciprotected: 2596b1994897Sopenharmony_ci using ArgumentsOnStack = LastField::NextFlag; 2597b1994897Sopenharmony_ci using Relocate = ArgumentsOnStack::NextFlag; 2598b1994897Sopenharmony_ci using LastField = Relocate; 2599b1994897Sopenharmony_ci 2600b1994897Sopenharmony_ciprivate: 2601b1994897Sopenharmony_ci std::string GetIntrinsicOpcodeName() const; 2602b1994897Sopenharmony_ci 2603b1994897Sopenharmony_ci IntrinsicId intrinsic_id_ {RuntimeInterface::IntrinsicId::COUNT}; 2604b1994897Sopenharmony_ci ArenaVector<uint32_t> *imms_ {nullptr}; // record imms appeared in intrinsics 2605b1994897Sopenharmony_ci}; 2606b1994897Sopenharmony_ci 2607b1994897Sopenharmony_ci#include <ecma_intrinsics_enum.inl> 2608b1994897Sopenharmony_ci 2609b1994897Sopenharmony_ci/** 2610b1994897Sopenharmony_ci * Cmp instruction 2611b1994897Sopenharmony_ci */ 2612b1994897Sopenharmony_ciclass CmpInst : public InstWithOperandsType<FixedInputsInst2> { 2613b1994897Sopenharmony_cipublic: 2614b1994897Sopenharmony_ci using BaseInst = InstWithOperandsType<FixedInputsInst2>; 2615b1994897Sopenharmony_ci using BaseInst::BaseInst; 2616b1994897Sopenharmony_ci 2617b1994897Sopenharmony_ci bool IsFcmpg() const 2618b1994897Sopenharmony_ci { 2619b1994897Sopenharmony_ci ASSERT(DataType::IsFloatType(GetOperandsType())); 2620b1994897Sopenharmony_ci return GetField<Fcmpg>(); 2621b1994897Sopenharmony_ci } 2622b1994897Sopenharmony_ci bool IsFcmpl() const 2623b1994897Sopenharmony_ci { 2624b1994897Sopenharmony_ci ASSERT(DataType::IsFloatType(GetOperandsType())); 2625b1994897Sopenharmony_ci return !GetField<Fcmpg>(); 2626b1994897Sopenharmony_ci } 2627b1994897Sopenharmony_ci void SetFcmpg() 2628b1994897Sopenharmony_ci { 2629b1994897Sopenharmony_ci ASSERT(DataType::IsFloatType(GetOperandsType())); 2630b1994897Sopenharmony_ci SetField<Fcmpg>(true); 2631b1994897Sopenharmony_ci } 2632b1994897Sopenharmony_ci void SetFcmpg(bool v) 2633b1994897Sopenharmony_ci { 2634b1994897Sopenharmony_ci ASSERT(DataType::IsFloatType(GetOperandsType())); 2635b1994897Sopenharmony_ci SetField<Fcmpg>(v); 2636b1994897Sopenharmony_ci } 2637b1994897Sopenharmony_ci void SetFcmpl() 2638b1994897Sopenharmony_ci { 2639b1994897Sopenharmony_ci ASSERT(DataType::IsFloatType(GetOperandsType())); 2640b1994897Sopenharmony_ci SetField<Fcmpg>(false); 2641b1994897Sopenharmony_ci } 2642b1994897Sopenharmony_ci void SetFcmpl(bool v) 2643b1994897Sopenharmony_ci { 2644b1994897Sopenharmony_ci ASSERT(DataType::IsFloatType(GetOperandsType())); 2645b1994897Sopenharmony_ci SetField<Fcmpg>(!v); 2646b1994897Sopenharmony_ci } 2647b1994897Sopenharmony_ci 2648b1994897Sopenharmony_ci DataType::Type GetInputType([[maybe_unused]] size_t index) const override 2649b1994897Sopenharmony_ci { 2650b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2651b1994897Sopenharmony_ci return GetOperandsType(); 2652b1994897Sopenharmony_ci } 2653b1994897Sopenharmony_ci 2654b1994897Sopenharmony_ci void SetVnObject(VnObject *vn_obj) override; 2655b1994897Sopenharmony_ci 2656b1994897Sopenharmony_ci void DumpOpcode(std::ostream *out) const override; 2657b1994897Sopenharmony_ci 2658b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 2659b1994897Sopenharmony_ci 2660b1994897Sopenharmony_ciprotected: 2661b1994897Sopenharmony_ci using Fcmpg = LastField::NextFlag; 2662b1994897Sopenharmony_ci using LastField = Fcmpg; 2663b1994897Sopenharmony_ci}; 2664b1994897Sopenharmony_ci 2665b1994897Sopenharmony_ci// NOLINTNEXTLINE(fuchsia-multiple-inheritance) 2666b1994897Sopenharmony_ciclass LoadFromPool : public NeedBarrierMixin<FixedInputsInst1>, public TypeIdMixin { 2667b1994897Sopenharmony_cipublic: 2668b1994897Sopenharmony_ci using Base = NeedBarrierMixin<FixedInputsInst1>; 2669b1994897Sopenharmony_ci using Base::Base; 2670b1994897Sopenharmony_ci 2671b1994897Sopenharmony_ci DataType::Type GetInputType([[maybe_unused]] size_t index) const override 2672b1994897Sopenharmony_ci { 2673b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2674b1994897Sopenharmony_ci return DataType::NO_TYPE; 2675b1994897Sopenharmony_ci } 2676b1994897Sopenharmony_ci 2677b1994897Sopenharmony_ci void DumpOpcode(std::ostream *out) const override; 2678b1994897Sopenharmony_ci 2679b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override 2680b1994897Sopenharmony_ci { 2681b1994897Sopenharmony_ci auto clone = FixedInputsInst::Clone(targetGraph); 2682b1994897Sopenharmony_ci static_cast<LoadFromPool *>(clone)->SetTypeId(GetTypeId()); 2683b1994897Sopenharmony_ci static_cast<LoadFromPool *>(clone)->SetMethod(GetMethod()); 2684b1994897Sopenharmony_ci return clone; 2685b1994897Sopenharmony_ci } 2686b1994897Sopenharmony_ci}; 2687b1994897Sopenharmony_ci 2688b1994897Sopenharmony_ci/** 2689b1994897Sopenharmony_ci * Conditional jump instruction 2690b1994897Sopenharmony_ci */ 2691b1994897Sopenharmony_ci// NOLINTNEXTLINE(fuchsia-multiple-inheritance) 2692b1994897Sopenharmony_ciclass IfInst : public InstWithOperandsType<ConditionMixin<FixedInputsInst2>> { 2693b1994897Sopenharmony_cipublic: 2694b1994897Sopenharmony_ci using Base = InstWithOperandsType<ConditionMixin<FixedInputsInst2>>; 2695b1994897Sopenharmony_ci using Base::Base; 2696b1994897Sopenharmony_ci 2697b1994897Sopenharmony_ci IfInst(Opcode opcode, DataType::Type type, uint32_t pc, ConditionCode cc) : Base(opcode, type, pc) 2698b1994897Sopenharmony_ci { 2699b1994897Sopenharmony_ci SetCc(cc); 2700b1994897Sopenharmony_ci } 2701b1994897Sopenharmony_ci 2702b1994897Sopenharmony_ci DataType::Type GetInputType([[maybe_unused]] size_t index) const override 2703b1994897Sopenharmony_ci { 2704b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2705b1994897Sopenharmony_ci return GetOperandsType(); 2706b1994897Sopenharmony_ci } 2707b1994897Sopenharmony_ci 2708b1994897Sopenharmony_ci void DumpOpcode(std::ostream *out) const override; 2709b1994897Sopenharmony_ci 2710b1994897Sopenharmony_ci void SetVnObject(VnObject *vn_obj) override; 2711b1994897Sopenharmony_ci 2712b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 2713b1994897Sopenharmony_ci 2714b1994897Sopenharmony_ci void SetMethod(RuntimeInterface::MethodPtr method) 2715b1994897Sopenharmony_ci { 2716b1994897Sopenharmony_ci method_ = method; 2717b1994897Sopenharmony_ci } 2718b1994897Sopenharmony_ci 2719b1994897Sopenharmony_ci RuntimeInterface::MethodPtr GetMethod() const 2720b1994897Sopenharmony_ci { 2721b1994897Sopenharmony_ci return method_; 2722b1994897Sopenharmony_ci } 2723b1994897Sopenharmony_ci 2724b1994897Sopenharmony_ciprivate: 2725b1994897Sopenharmony_ci RuntimeInterface::MethodPtr method_ {nullptr}; 2726b1994897Sopenharmony_ci}; 2727b1994897Sopenharmony_ci 2728b1994897Sopenharmony_ci/** 2729b1994897Sopenharmony_ci * IfImm instruction with immediate 2730b1994897Sopenharmony_ci */ 2731b1994897Sopenharmony_ci// NOLINTNEXTLINE(fuchsia-multiple-inheritance) 2732b1994897Sopenharmony_ciclass IfImmInst : public InstWithOperandsType<ConditionMixin<FixedInputsInst1>>, public ImmediateMixin { 2733b1994897Sopenharmony_cipublic: 2734b1994897Sopenharmony_ci using Base = InstWithOperandsType<ConditionMixin<FixedInputsInst1>>; 2735b1994897Sopenharmony_ci using Base::Base; 2736b1994897Sopenharmony_ci 2737b1994897Sopenharmony_ci IfImmInst(Opcode opcode, DataType::Type type, uint32_t pc, ConditionCode cc, uint64_t imm) 2738b1994897Sopenharmony_ci : Base(opcode, type, pc), ImmediateMixin(imm) 2739b1994897Sopenharmony_ci { 2740b1994897Sopenharmony_ci SetCc(cc); 2741b1994897Sopenharmony_ci } 2742b1994897Sopenharmony_ci 2743b1994897Sopenharmony_ci DataType::Type GetInputType([[maybe_unused]] size_t index) const override 2744b1994897Sopenharmony_ci { 2745b1994897Sopenharmony_ci ASSERT(index < GetInputsCount()); 2746b1994897Sopenharmony_ci return GetOperandsType(); 2747b1994897Sopenharmony_ci } 2748b1994897Sopenharmony_ci 2749b1994897Sopenharmony_ci void DumpOpcode(std::ostream *out) const override; 2750b1994897Sopenharmony_ci bool DumpInputs(std::ostream *out) const override; 2751b1994897Sopenharmony_ci void SetVnObject(VnObject *vn_obj) override; 2752b1994897Sopenharmony_ci 2753b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override 2754b1994897Sopenharmony_ci { 2755b1994897Sopenharmony_ci auto clone = FixedInputsInst::Clone(targetGraph); 2756b1994897Sopenharmony_ci clone->CastToIfImm()->SetCc(GetCc()); 2757b1994897Sopenharmony_ci clone->CastToIfImm()->SetImm(GetImm()); 2758b1994897Sopenharmony_ci clone->CastToIfImm()->SetOperandsType(GetOperandsType()); 2759b1994897Sopenharmony_ci clone->CastToIfImm()->SetMethod(GetMethod()); 2760b1994897Sopenharmony_ci return clone; 2761b1994897Sopenharmony_ci } 2762b1994897Sopenharmony_ci 2763b1994897Sopenharmony_ci BasicBlock *GetEdgeIfInputTrue(); 2764b1994897Sopenharmony_ci BasicBlock *GetEdgeIfInputFalse(); 2765b1994897Sopenharmony_ci 2766b1994897Sopenharmony_ci void SetMethod(RuntimeInterface::MethodPtr method) 2767b1994897Sopenharmony_ci { 2768b1994897Sopenharmony_ci method_ = method; 2769b1994897Sopenharmony_ci } 2770b1994897Sopenharmony_ci 2771b1994897Sopenharmony_ci RuntimeInterface::MethodPtr GetMethod() const 2772b1994897Sopenharmony_ci { 2773b1994897Sopenharmony_ci return method_; 2774b1994897Sopenharmony_ci } 2775b1994897Sopenharmony_ci 2776b1994897Sopenharmony_ciprivate: 2777b1994897Sopenharmony_ci size_t GetTrueInputEdgeIdx(); 2778b1994897Sopenharmony_ci RuntimeInterface::MethodPtr method_ {nullptr}; 2779b1994897Sopenharmony_ci}; 2780b1994897Sopenharmony_ci 2781b1994897Sopenharmony_ci/** 2782b1994897Sopenharmony_ci * CatchPhiInst instruction 2783b1994897Sopenharmony_ci */ 2784b1994897Sopenharmony_ciclass CatchPhiInst : public DynamicInputsInst { 2785b1994897Sopenharmony_cipublic: 2786b1994897Sopenharmony_ci using DynamicInputsInst::DynamicInputsInst; 2787b1994897Sopenharmony_ci 2788b1994897Sopenharmony_ci const ArenaVector<const Inst *> *GetThrowableInsts() const 2789b1994897Sopenharmony_ci { 2790b1994897Sopenharmony_ci return throw_insts_; 2791b1994897Sopenharmony_ci } 2792b1994897Sopenharmony_ci 2793b1994897Sopenharmony_ci const Inst *GetThrowableInst(size_t i) const 2794b1994897Sopenharmony_ci { 2795b1994897Sopenharmony_ci ASSERT(throw_insts_ != nullptr && i < throw_insts_->size()); 2796b1994897Sopenharmony_ci return throw_insts_->at(i); 2797b1994897Sopenharmony_ci } 2798b1994897Sopenharmony_ci 2799b1994897Sopenharmony_ci void AppendThrowableInst(const Inst *inst); 2800b1994897Sopenharmony_ci void ReplaceThrowableInst(const Inst *old_inst, const Inst *new_inst); 2801b1994897Sopenharmony_ci void RemoveInput(unsigned index) override; 2802b1994897Sopenharmony_ci 2803b1994897Sopenharmony_ci bool IsAcc() const 2804b1994897Sopenharmony_ci { 2805b1994897Sopenharmony_ci return GetField<IsAccFlag>(); 2806b1994897Sopenharmony_ci } 2807b1994897Sopenharmony_ci 2808b1994897Sopenharmony_ci void SetIsAcc() 2809b1994897Sopenharmony_ci { 2810b1994897Sopenharmony_ci SetField<IsAccFlag>(true); 2811b1994897Sopenharmony_ci } 2812b1994897Sopenharmony_ci 2813b1994897Sopenharmony_ciprotected: 2814b1994897Sopenharmony_ci using IsAccFlag = LastField::NextFlag; 2815b1994897Sopenharmony_ci using LastField = IsAccFlag; 2816b1994897Sopenharmony_ci 2817b1994897Sopenharmony_ciprivate: 2818b1994897Sopenharmony_ci size_t GetThrowableInstIndex(const Inst *inst) 2819b1994897Sopenharmony_ci { 2820b1994897Sopenharmony_ci ASSERT(throw_insts_ != nullptr); 2821b1994897Sopenharmony_ci auto it = std::find(throw_insts_->begin(), throw_insts_->end(), inst); 2822b1994897Sopenharmony_ci ASSERT(it != throw_insts_->end()); 2823b1994897Sopenharmony_ci return std::distance(throw_insts_->begin(), it); 2824b1994897Sopenharmony_ci } 2825b1994897Sopenharmony_ci 2826b1994897Sopenharmony_ciprivate: 2827b1994897Sopenharmony_ci ArenaVector<const Inst *> *throw_insts_ {nullptr}; 2828b1994897Sopenharmony_ci}; 2829b1994897Sopenharmony_ci 2830b1994897Sopenharmony_ciclass TryInst : public FixedInputsInst0 { 2831b1994897Sopenharmony_cipublic: 2832b1994897Sopenharmony_ci using FixedInputsInst0::FixedInputsInst0; 2833b1994897Sopenharmony_ci 2834b1994897Sopenharmony_ci void AppendCatchTypeId(uint32_t id, uint32_t catch_edge_index); 2835b1994897Sopenharmony_ci 2836b1994897Sopenharmony_ci const ArenaVector<uint32_t> *GetCatchTypeIds() const 2837b1994897Sopenharmony_ci { 2838b1994897Sopenharmony_ci return catch_type_ids_; 2839b1994897Sopenharmony_ci } 2840b1994897Sopenharmony_ci 2841b1994897Sopenharmony_ci const ArenaVector<uint32_t> *GetCatchEdgeIndexes() const 2842b1994897Sopenharmony_ci { 2843b1994897Sopenharmony_ci return catch_edge_indexes_; 2844b1994897Sopenharmony_ci } 2845b1994897Sopenharmony_ci 2846b1994897Sopenharmony_ci size_t GetCatchTypeIdsCount() const 2847b1994897Sopenharmony_ci { 2848b1994897Sopenharmony_ci return (catch_type_ids_ == nullptr ? 0 : catch_type_ids_->size()); 2849b1994897Sopenharmony_ci } 2850b1994897Sopenharmony_ci 2851b1994897Sopenharmony_ci Inst *Clone(const Graph *targetGraph) const override; 2852b1994897Sopenharmony_ci 2853b1994897Sopenharmony_ci void SetTryEndBlock(BasicBlock *try_end_bb) 2854b1994897Sopenharmony_ci { 2855b1994897Sopenharmony_ci try_end_bb_ = try_end_bb; 2856b1994897Sopenharmony_ci } 2857b1994897Sopenharmony_ci 2858b1994897Sopenharmony_ci BasicBlock *GetTryEndBlock() const 2859b1994897Sopenharmony_ci { 2860b1994897Sopenharmony_ci return try_end_bb_; 2861b1994897Sopenharmony_ci } 2862b1994897Sopenharmony_ci 2863b1994897Sopenharmony_ciprivate: 2864b1994897Sopenharmony_ci ArenaVector<uint32_t> *catch_type_ids_ {nullptr}; 2865b1994897Sopenharmony_ci ArenaVector<uint32_t> *catch_edge_indexes_ {nullptr}; 2866b1994897Sopenharmony_ci BasicBlock *try_end_bb_ {nullptr}; 2867b1994897Sopenharmony_ci}; 2868b1994897Sopenharmony_ci 2869b1994897Sopenharmony_ciTryInst *GetTryBeginInst(const BasicBlock *try_begin_bb); 2870b1994897Sopenharmony_ci 2871b1994897Sopenharmony_citemplate <typename InstType, typename... Args> 2872b1994897Sopenharmony_ciInstType *Inst::New(ArenaAllocator *allocator, Args &&... args) 2873b1994897Sopenharmony_ci{ 2874b1994897Sopenharmony_ci static_assert(alignof(InstType) >= alignof(uintptr_t)); 2875b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-branch-clone) 2876b1994897Sopenharmony_ci if constexpr (std::is_same_v<InstType, SpillFillInst>) { 2877b1994897Sopenharmony_ci auto data = reinterpret_cast<uintptr_t>(allocator->Alloc(sizeof(InstType), DEFAULT_ALIGNMENT)); 2878b1994897Sopenharmony_ci CHECK(data != 0); 2879b1994897Sopenharmony_ci return new (reinterpret_cast<void *>(data)) InstType(allocator, std::forward<Args>(args)...); 2880b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 2881b1994897Sopenharmony_ci } else if constexpr (InstType::INPUT_COUNT == 0) { 2882b1994897Sopenharmony_ci auto data = reinterpret_cast<uintptr_t>(allocator->Alloc(sizeof(InstType), DEFAULT_ALIGNMENT)); 2883b1994897Sopenharmony_ci CHECK(data != 0); 2884b1994897Sopenharmony_ci return new (reinterpret_cast<void *>(data)) InstType(std::forward<Args>(args)...); 2885b1994897Sopenharmony_ci // NOLINTNEXTLINE(readability-braces-around-statements, readability-misleading-indentation) 2886b1994897Sopenharmony_ci } else if constexpr (InstType::INPUT_COUNT == MAX_STATIC_INPUTS) { 2887b1994897Sopenharmony_ci constexpr size_t OPERANDS_SIZE = sizeof(DynamicOperands); 2888b1994897Sopenharmony_ci static_assert((OPERANDS_SIZE % alignof(InstType)) == 0); 2889b1994897Sopenharmony_ci auto data = reinterpret_cast<uintptr_t>(allocator->Alloc(OPERANDS_SIZE + sizeof(InstType), DEFAULT_ALIGNMENT)); 2890b1994897Sopenharmony_ci CHECK(data != 0); 2891b1994897Sopenharmony_ci auto inst = new (reinterpret_cast<void *>(data + OPERANDS_SIZE)) InstType(std::forward<Args>(args)...); 2892b1994897Sopenharmony_ci [[maybe_unused]] auto operands = new (reinterpret_cast<void *>(data)) DynamicOperands(allocator); 2893b1994897Sopenharmony_ci static_cast<Inst *>(inst)->SetField<InputsCount>(InstType::INPUT_COUNT); 2894b1994897Sopenharmony_ci return inst; 2895b1994897Sopenharmony_ci } else { // NOLINT(readability-misleading-indentation) 2896b1994897Sopenharmony_ci constexpr size_t OPERANDS_SIZE = sizeof(Operands<InstType::INPUT_COUNT>); 2897b1994897Sopenharmony_ci constexpr auto ALIGNMENT {GetLogAlignment(alignof(Operands<InstType::INPUT_COUNT>))}; 2898b1994897Sopenharmony_ci static_assert((OPERANDS_SIZE % alignof(InstType)) == 0); 2899b1994897Sopenharmony_ci auto data = reinterpret_cast<uintptr_t>(allocator->Alloc(OPERANDS_SIZE + sizeof(InstType), ALIGNMENT)); 2900b1994897Sopenharmony_ci CHECK(data != 0); 2901b1994897Sopenharmony_ci auto inst = new (reinterpret_cast<void *>(data + OPERANDS_SIZE)) InstType(std::forward<Args>(args)...); 2902b1994897Sopenharmony_ci auto operands = new (reinterpret_cast<void *>(data)) Operands<InstType::INPUT_COUNT>; 2903b1994897Sopenharmony_ci static_cast<Inst *>(inst)->SetField<InputsCount>(InstType::INPUT_COUNT); 2904b1994897Sopenharmony_ci unsigned idx = InstType::INPUT_COUNT - 1; 2905b1994897Sopenharmony_ci for (auto &user : operands->users) { 2906b1994897Sopenharmony_ci new (&user) User(true, idx--, InstType::INPUT_COUNT); 2907b1994897Sopenharmony_ci } 2908b1994897Sopenharmony_ci return inst; 2909b1994897Sopenharmony_ci } 2910b1994897Sopenharmony_ci} 2911b1994897Sopenharmony_ci 2912b1994897Sopenharmony_ciinline Inst *User::GetInput() 2913b1994897Sopenharmony_ci{ 2914b1994897Sopenharmony_ci return GetInst()->GetInput(GetIndex()).GetInst(); 2915b1994897Sopenharmony_ci} 2916b1994897Sopenharmony_ci 2917b1994897Sopenharmony_ciinline const Inst *User::GetInput() const 2918b1994897Sopenharmony_ci{ 2919b1994897Sopenharmony_ci return GetInst()->GetInput(GetIndex()).GetInst(); 2920b1994897Sopenharmony_ci} 2921b1994897Sopenharmony_ci 2922b1994897Sopenharmony_ciinline std::ostream &operator<<(std::ostream &os, const Inst &inst) 2923b1994897Sopenharmony_ci{ 2924b1994897Sopenharmony_ci inst.Dump(&os, false); 2925b1994897Sopenharmony_ci return os; 2926b1994897Sopenharmony_ci} 2927b1994897Sopenharmony_ci 2928b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 2929b1994897Sopenharmony_ci#define INST_DEF(opcode, base, ...) \ 2930b1994897Sopenharmony_ci inline const base *Inst::CastTo##opcode() const \ 2931b1994897Sopenharmony_ci { \ 2932b1994897Sopenharmony_ci ASSERT(GetOpcode() == Opcode::opcode); \ 2933b1994897Sopenharmony_ci return static_cast<const base *>(this); \ 2934b1994897Sopenharmony_ci } 2935b1994897Sopenharmony_ciOPCODE_LIST(INST_DEF) 2936b1994897Sopenharmony_ci#undef INST_DEF 2937b1994897Sopenharmony_ci 2938b1994897Sopenharmony_ci// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 2939b1994897Sopenharmony_ci#define INST_DEF(opcode, base, ...) \ 2940b1994897Sopenharmony_ci inline base *Inst::CastTo##opcode() \ 2941b1994897Sopenharmony_ci { \ 2942b1994897Sopenharmony_ci ASSERT(GetOpcode() == Opcode::opcode); \ 2943b1994897Sopenharmony_ci return static_cast<base *>(this); \ 2944b1994897Sopenharmony_ci } 2945b1994897Sopenharmony_ciOPCODE_LIST(INST_DEF) 2946b1994897Sopenharmony_ci#undef INST_DEF 2947b1994897Sopenharmony_ci} // namespace panda::compiler 2948b1994897Sopenharmony_ci 2949b1994897Sopenharmony_ci#endif // COMPILER_OPTIMIZER_IR_INST_H 2950