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#include "inst.h"
17b1994897Sopenharmony_ci#include "graph.h"
18b1994897Sopenharmony_ci#include "graph_visitor.h"
19b1994897Sopenharmony_ci#include "optimizer/optimizations/vn.h"
20b1994897Sopenharmony_ci
21b1994897Sopenharmony_cinamespace panda::compiler {
22b1994897Sopenharmony_ci
23b1994897Sopenharmony_civoid Inst::ReserveInputs(size_t capacity)
24b1994897Sopenharmony_ci{
25b1994897Sopenharmony_ci    ASSERT(IsOperandsDynamic());
26b1994897Sopenharmony_ci    GetDynamicOperands()->Reallocate(capacity);
27b1994897Sopenharmony_ci}
28b1994897Sopenharmony_ci
29b1994897Sopenharmony_ciInst *User::GetInst()
30b1994897Sopenharmony_ci{
31b1994897Sopenharmony_ci    if (UNLIKELY(IsDynamic())) {
32b1994897Sopenharmony_ci        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
33b1994897Sopenharmony_ci        return *reinterpret_cast<Inst **>(this + GetIndex() + 1);
34b1994897Sopenharmony_ci    }
35b1994897Sopenharmony_ci    auto p = reinterpret_cast<uintptr_t>(this);
36b1994897Sopenharmony_ci    p += (GetIndex() + 1) * sizeof(User);
37b1994897Sopenharmony_ci
38b1994897Sopenharmony_ci    auto inputs_count {SizeField::Decode(properties_)};
39b1994897Sopenharmony_ci    p += (inputs_count + Input::GetPadding(RUNTIME_ARCH, inputs_count)) * sizeof(Input);
40b1994897Sopenharmony_ci    return reinterpret_cast<Inst *>(p);
41b1994897Sopenharmony_ci}
42b1994897Sopenharmony_ci
43b1994897Sopenharmony_civoid Inst::InsertBefore(Inst *inst)
44b1994897Sopenharmony_ci{
45b1994897Sopenharmony_ci    ASSERT(bb_ != nullptr);
46b1994897Sopenharmony_ci    bb_->InsertBefore(inst, this);
47b1994897Sopenharmony_ci}
48b1994897Sopenharmony_ci
49b1994897Sopenharmony_civoid Inst::InsertAfter(Inst *inst)
50b1994897Sopenharmony_ci{
51b1994897Sopenharmony_ci    ASSERT(bb_ != nullptr);
52b1994897Sopenharmony_ci    bb_->InsertAfter(inst, this);
53b1994897Sopenharmony_ci}
54b1994897Sopenharmony_ci
55b1994897Sopenharmony_civoid DynamicOperands::Reallocate([[maybe_unused]] size_t new_capacity /* =0 */)
56b1994897Sopenharmony_ci{
57b1994897Sopenharmony_ci    if (new_capacity == 0) {
58b1994897Sopenharmony_ci        constexpr auto IMM_2 = 2;
59b1994897Sopenharmony_ci        new_capacity = (((capacity_ != 0U) ? capacity_ : 1U) << 1U) + IMM_2;
60b1994897Sopenharmony_ci    } else if (new_capacity <= capacity_) {
61b1994897Sopenharmony_ci        return;
62b1994897Sopenharmony_ci    }
63b1994897Sopenharmony_ci    auto size = new_capacity * (sizeof(User) + sizeof(Inst *)) + sizeof(Inst *);
64b1994897Sopenharmony_ci    auto new_stor = reinterpret_cast<uintptr_t>(allocator_->Alloc(size));
65b1994897Sopenharmony_ci    CHECK(new_stor != 0);
66b1994897Sopenharmony_ci
67b1994897Sopenharmony_ci    auto owner_inst {GetOwnerInst()};
68b1994897Sopenharmony_ci    // Set pointer to owned instruction into new storage NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
69b1994897Sopenharmony_ci    *reinterpret_cast<Inst **>(reinterpret_cast<User *>(new_stor) + new_capacity) = owner_inst;
70b1994897Sopenharmony_ci
71b1994897Sopenharmony_ci    if (users_ == nullptr) {
72b1994897Sopenharmony_ci        users_ = reinterpret_cast<User *>(new_stor);
73b1994897Sopenharmony_ci        capacity_ = new_capacity;
74b1994897Sopenharmony_ci        return;
75b1994897Sopenharmony_ci    }
76b1994897Sopenharmony_ci    Input *old_inputs = Inputs();
77b1994897Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
78b1994897Sopenharmony_ci    auto *new_inputs = reinterpret_cast<Input *>(new_stor + sizeof(User) * new_capacity) + 1;
79b1994897Sopenharmony_ci
80b1994897Sopenharmony_ci    for (size_t i = 0; i < size_; i++) {
81b1994897Sopenharmony_ci        Inst *old_input = old_inputs[i].GetInst();  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
82b1994897Sopenharmony_ci        ASSERT(old_input);
83b1994897Sopenharmony_ci        // Initialize new User in container. Since users are placed from end of array, i.e. zero index element
84b1994897Sopenharmony_ci        // will be at the end of array, we need to add capacity and substitute index.
85b1994897Sopenharmony_ci        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
86b1994897Sopenharmony_ci        User *new_user = new (reinterpret_cast<User *>(new_stor) + new_capacity - i - 1) User(false, i, new_capacity);
87b1994897Sopenharmony_ci        auto old_user {GetUser(i)};
88b1994897Sopenharmony_ci        if (owner_inst->IsSaveState()) {
89b1994897Sopenharmony_ci            new_user->SetVirtualRegister(old_user->GetVirtualRegister());
90b1994897Sopenharmony_ci        } else if (owner_inst->IsPhi()) {
91b1994897Sopenharmony_ci            new_user->SetBbNum(old_user->GetBbNum());
92b1994897Sopenharmony_ci        }
93b1994897Sopenharmony_ci        old_input->RemoveUser(old_user);
94b1994897Sopenharmony_ci        old_input->AddUser(new_user);
95b1994897Sopenharmony_ci        new_inputs[i] = Input(old_input);  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
96b1994897Sopenharmony_ci    }
97b1994897Sopenharmony_ci    capacity_ = new_capacity;
98b1994897Sopenharmony_ci    users_ = reinterpret_cast<User *>(new_stor);
99b1994897Sopenharmony_ci}
100b1994897Sopenharmony_ci
101b1994897Sopenharmony_ciunsigned DynamicOperands::Append(Inst *inst)
102b1994897Sopenharmony_ci{
103b1994897Sopenharmony_ci    ASSERT(capacity_ >= size_);
104b1994897Sopenharmony_ci    if (capacity_ == size_) {
105b1994897Sopenharmony_ci        Reallocate();
106b1994897Sopenharmony_ci    }
107b1994897Sopenharmony_ci    SetInput(size_, Input(inst));
108b1994897Sopenharmony_ci    // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
109b1994897Sopenharmony_ci    new (users_ + capacity_ - size_ - 1) User(false, size_, capacity_);
110b1994897Sopenharmony_ci    auto user {GetUser(size_)};
111b1994897Sopenharmony_ci    if (GetOwnerInst()->IsPhi()) {
112b1994897Sopenharmony_ci        user->SetBbNum(size_);
113b1994897Sopenharmony_ci    }
114b1994897Sopenharmony_ci    inst->AddUser(user);
115b1994897Sopenharmony_ci    return size_++;
116b1994897Sopenharmony_ci}
117b1994897Sopenharmony_ci
118b1994897Sopenharmony_civoid DynamicOperands::Remove(unsigned index)
119b1994897Sopenharmony_ci{
120b1994897Sopenharmony_ci    size_--;
121b1994897Sopenharmony_ci    auto *curr_input = GetInput(index)->GetInst();
122b1994897Sopenharmony_ci    if (curr_input->GetBasicBlock() != nullptr && curr_input->HasUsers()) {
123b1994897Sopenharmony_ci        curr_input->RemoveUser(GetUser(index));
124b1994897Sopenharmony_ci    }
125b1994897Sopenharmony_ci
126b1994897Sopenharmony_ci    auto bb_num {GetUser(index)->GetBbNum()};
127b1994897Sopenharmony_ci    auto owner_inst {GetOwnerInst()};
128b1994897Sopenharmony_ci
129b1994897Sopenharmony_ci    if (index != size_) {
130b1994897Sopenharmony_ci        auto *last_input = GetInput(size_)->GetInst();
131b1994897Sopenharmony_ci        if (last_input->HasUsers()) {
132b1994897Sopenharmony_ci            last_input->RemoveUser(GetUser(size_));
133b1994897Sopenharmony_ci            last_input->AddUser(GetUser(index));
134b1994897Sopenharmony_ci        }
135b1994897Sopenharmony_ci        SetInput(index, *GetInput(size_));
136b1994897Sopenharmony_ci        if (owner_inst->IsSaveState()) {
137b1994897Sopenharmony_ci            GetUser(index)->SetVirtualRegister(GetUser(size_)->GetVirtualRegister());
138b1994897Sopenharmony_ci        } else if (owner_inst->IsPhi()) {
139b1994897Sopenharmony_ci            GetUser(index)->SetBbNum(GetUser(size_)->GetBbNum());
140b1994897Sopenharmony_ci        }
141b1994897Sopenharmony_ci    }
142b1994897Sopenharmony_ci
143b1994897Sopenharmony_ci    if (owner_inst->IsPhi()) {
144b1994897Sopenharmony_ci        for (size_t i {0}; i < size_; ++i) {
145b1994897Sopenharmony_ci            if (GetUser(i)->GetBbNum() == size_) {
146b1994897Sopenharmony_ci                GetUser(i)->SetBbNum(bb_num);
147b1994897Sopenharmony_ci                break;
148b1994897Sopenharmony_ci            }
149b1994897Sopenharmony_ci        }
150b1994897Sopenharmony_ci    }
151b1994897Sopenharmony_ci}
152b1994897Sopenharmony_ci
153b1994897Sopenharmony_civoid CompareInst::SetVnObject(VnObject *vn_obj)
154b1994897Sopenharmony_ci{
155b1994897Sopenharmony_ci    vn_obj->Add(static_cast<uint32_t>(GetCc()));
156b1994897Sopenharmony_ci}
157b1994897Sopenharmony_ci
158b1994897Sopenharmony_civoid IfInst::SetVnObject(VnObject *vn_obj)
159b1994897Sopenharmony_ci{
160b1994897Sopenharmony_ci    vn_obj->Add(static_cast<uint32_t>(GetCc()));
161b1994897Sopenharmony_ci}
162b1994897Sopenharmony_ci
163b1994897Sopenharmony_civoid IfImmInst::SetVnObject(VnObject *vn_obj)
164b1994897Sopenharmony_ci{
165b1994897Sopenharmony_ci    vn_obj->Add(static_cast<uint32_t>(GetCc()));
166b1994897Sopenharmony_ci}
167b1994897Sopenharmony_ci
168b1994897Sopenharmony_civoid CmpInst::SetVnObject(VnObject *vn_obj)
169b1994897Sopenharmony_ci{
170b1994897Sopenharmony_ci    if (DataType::IsFloatType(GetOperandsType())) {
171b1994897Sopenharmony_ci        vn_obj->Add(static_cast<uint32_t>(IsFcmpg()));
172b1994897Sopenharmony_ci    }
173b1994897Sopenharmony_ci    vn_obj->Add(static_cast<uint32_t>(GetInputType(0)));
174b1994897Sopenharmony_ci}
175b1994897Sopenharmony_ci
176b1994897Sopenharmony_ciBasicBlock *PhiInst::GetPhiInputBb(unsigned index)
177b1994897Sopenharmony_ci{
178b1994897Sopenharmony_ci    ASSERT(index < GetInputsCount());
179b1994897Sopenharmony_ci
180b1994897Sopenharmony_ci    auto bb_num {GetPhiInputBbNum(index)};
181b1994897Sopenharmony_ci    ASSERT(bb_num < GetBasicBlock()->GetPredsBlocks().size());
182b1994897Sopenharmony_ci    return GetBasicBlock()->GetPredsBlocks()[bb_num];
183b1994897Sopenharmony_ci}
184b1994897Sopenharmony_ci
185b1994897Sopenharmony_ciInst *PhiInst::GetPhiInput(BasicBlock *bb)
186b1994897Sopenharmony_ci{
187b1994897Sopenharmony_ci    auto index = GetPredBlockIndex(bb);
188b1994897Sopenharmony_ci    ASSERT(index < GetInputs().size());
189b1994897Sopenharmony_ci    return GetInput(index).GetInst();
190b1994897Sopenharmony_ci}
191b1994897Sopenharmony_ci
192b1994897Sopenharmony_ciInst *PhiInst::GetPhiDataflowInput(BasicBlock *bb)
193b1994897Sopenharmony_ci{
194b1994897Sopenharmony_ci    auto index = GetPredBlockIndex(bb);
195b1994897Sopenharmony_ci    ASSERT(index < GetInputs().size());
196b1994897Sopenharmony_ci    return GetDataFlowInput(index);
197b1994897Sopenharmony_ci}
198b1994897Sopenharmony_ci
199b1994897Sopenharmony_cisize_t PhiInst::GetPredBlockIndex(const BasicBlock *block) const
200b1994897Sopenharmony_ci{
201b1994897Sopenharmony_ci    for (size_t i {0}; i < GetInputsCount(); ++i) {
202b1994897Sopenharmony_ci        if (GetPhiInputBb(i) == block) {
203b1994897Sopenharmony_ci            return i;
204b1994897Sopenharmony_ci        }
205b1994897Sopenharmony_ci    }
206b1994897Sopenharmony_ci    UNREACHABLE();
207b1994897Sopenharmony_ci}
208b1994897Sopenharmony_ci
209b1994897Sopenharmony_citemplate <Opcode opc, size_t input_idx>
210b1994897Sopenharmony_ciInst *SkipInstructions(Inst *input_inst)
211b1994897Sopenharmony_ci{
212b1994897Sopenharmony_ci    // NOLINTNEXTLINE(readability-magic-numbers)
213b1994897Sopenharmony_ci    for (Opcode opcode = input_inst->GetOpcode(); opcode == opc; opcode = input_inst->GetOpcode()) {
214b1994897Sopenharmony_ci        input_inst = input_inst->GetInput(input_idx).GetInst();
215b1994897Sopenharmony_ci    }
216b1994897Sopenharmony_ci    return input_inst;
217b1994897Sopenharmony_ci}
218b1994897Sopenharmony_ci/*
219b1994897Sopenharmony_ci * For instructions LoadArray, StoreArray, LoadArrayPair, StoreArrayPair, LoadArrayI, StoreArrayI, LoadArrayPairI,
220b1994897Sopenharmony_ci * StoreArrayPairI, LenArray, LoadObject, StoreObject, CallVirtual, Monitor with NullCheck input the dataflow user
221b1994897Sopenharmony_ci * is object, which is the first input of NullCheck instruction.
222b1994897Sopenharmony_ci * For instructions LoadArray, StoreArray, LoadArrayPair, StoreArrayPair with BoundsCheck input the dataflow user is
223b1994897Sopenharmony_ci * array index, which is the second input of BoundsCheck instruction
224b1994897Sopenharmony_ci * For instructions Div and Mod with ZeroCheck input the dataflow user is the first input of ZeroCheck
225b1994897Sopenharmony_ci */
226b1994897Sopenharmony_ciInst *Inst::GetDataFlowInput(Inst *input_inst) const
227b1994897Sopenharmony_ci{
228b1994897Sopenharmony_ci    return input_inst;
229b1994897Sopenharmony_ci}
230b1994897Sopenharmony_ci
231b1994897Sopenharmony_cibool Inst::IsPrecedingInSameBlock(const Inst *other) const
232b1994897Sopenharmony_ci{
233b1994897Sopenharmony_ci    ASSERT(other != nullptr && GetBasicBlock() == other->GetBasicBlock());
234b1994897Sopenharmony_ci    if (this == other) {
235b1994897Sopenharmony_ci        return true;
236b1994897Sopenharmony_ci    }
237b1994897Sopenharmony_ci    auto next = GetNext();
238b1994897Sopenharmony_ci    while (next != nullptr) {
239b1994897Sopenharmony_ci        if (next == other) {
240b1994897Sopenharmony_ci            return true;
241b1994897Sopenharmony_ci        }
242b1994897Sopenharmony_ci        next = next->GetNext();
243b1994897Sopenharmony_ci    }
244b1994897Sopenharmony_ci    return false;
245b1994897Sopenharmony_ci}
246b1994897Sopenharmony_ci
247b1994897Sopenharmony_cibool Inst::IsDominate(const Inst *other) const
248b1994897Sopenharmony_ci{
249b1994897Sopenharmony_ci    ASSERT(other != nullptr);
250b1994897Sopenharmony_ci    if (this == other) {
251b1994897Sopenharmony_ci        return true;
252b1994897Sopenharmony_ci    }
253b1994897Sopenharmony_ci    auto this_bb = GetBasicBlock();
254b1994897Sopenharmony_ci    auto other_bb = other->GetBasicBlock();
255b1994897Sopenharmony_ci    return this_bb == other_bb ? IsPrecedingInSameBlock(other) : this_bb->IsDominate(other_bb);
256b1994897Sopenharmony_ci}
257b1994897Sopenharmony_ci
258b1994897Sopenharmony_cibool Inst::InSameBlockOrDominate(const Inst *other) const
259b1994897Sopenharmony_ci{
260b1994897Sopenharmony_ci    return GetBasicBlock() == other->GetBasicBlock() || IsDominate(other);
261b1994897Sopenharmony_ci}
262b1994897Sopenharmony_ci
263b1994897Sopenharmony_ciInst *Inst::Clone(const Graph *targetGraph) const
264b1994897Sopenharmony_ci{
265b1994897Sopenharmony_ci    ASSERT(targetGraph != nullptr);
266b1994897Sopenharmony_ci    auto clone = targetGraph->CreateInst(GetOpcode());
267b1994897Sopenharmony_ci    CHECK_NOT_NULL(clone);
268b1994897Sopenharmony_ci    clone->bit_fields_ = GetAllFields();
269b1994897Sopenharmony_ci    clone->pc_ = GetPc();
270b1994897Sopenharmony_ci#ifndef NDEBUG
271b1994897Sopenharmony_ci    clone->SetDstReg(GetDstReg());
272b1994897Sopenharmony_ci#endif
273b1994897Sopenharmony_ci    if (IsOperandsDynamic()) {
274b1994897Sopenharmony_ci        clone->ReserveInputs(GetInputsCount());
275b1994897Sopenharmony_ci    }
276b1994897Sopenharmony_ci    return clone;
277b1994897Sopenharmony_ci}
278b1994897Sopenharmony_ci
279b1994897Sopenharmony_ci#if PANDA_TARGET_MACOS
280b1994897Sopenharmony_citemplate class FixedInputsInst<0>;
281b1994897Sopenharmony_citemplate class FixedInputsInst<1>;
282b1994897Sopenharmony_citemplate class FixedInputsInst<2U>;
283b1994897Sopenharmony_ci#endif
284b1994897Sopenharmony_ci
285b1994897Sopenharmony_ciInst *SpillFillInst::Clone(const Graph *targetGraph) const
286b1994897Sopenharmony_ci{
287b1994897Sopenharmony_ci    auto clone = FixedInputsInst::Clone(targetGraph)->CastToSpillFill();
288b1994897Sopenharmony_ci    for (auto spill_fill : spill_fills_) {
289b1994897Sopenharmony_ci        clone->AddSpillFill(spill_fill);
290b1994897Sopenharmony_ci    }
291b1994897Sopenharmony_ci    return clone;
292b1994897Sopenharmony_ci}
293b1994897Sopenharmony_ci
294b1994897Sopenharmony_ciInst *CompareInst::Clone(const Graph *targetGraph) const
295b1994897Sopenharmony_ci{
296b1994897Sopenharmony_ci    auto clone = FixedInputsInst::Clone(targetGraph);
297b1994897Sopenharmony_ci    clone->CastToCompare()->SetCc(GetCc());
298b1994897Sopenharmony_ci    clone->CastToCompare()->SetOperandsType(GetOperandsType());
299b1994897Sopenharmony_ci    return clone;
300b1994897Sopenharmony_ci}
301b1994897Sopenharmony_ci
302b1994897Sopenharmony_ciInst *CmpInst::Clone(const Graph *targetGraph) const
303b1994897Sopenharmony_ci{
304b1994897Sopenharmony_ci    auto clone = FixedInputsInst::Clone(targetGraph);
305b1994897Sopenharmony_ci    clone->CastToCmp()->SetOperandsType(GetOperandsType());
306b1994897Sopenharmony_ci    return clone;
307b1994897Sopenharmony_ci}
308b1994897Sopenharmony_ci
309b1994897Sopenharmony_ciInst *IfInst::Clone(const Graph *targetGraph) const
310b1994897Sopenharmony_ci{
311b1994897Sopenharmony_ci    auto clone = FixedInputsInst::Clone(targetGraph);
312b1994897Sopenharmony_ci    static_cast<IfInst *>(clone)->SetCc(GetCc());
313b1994897Sopenharmony_ci    static_cast<IfInst *>(clone)->SetOperandsType(GetOperandsType());
314b1994897Sopenharmony_ci    static_cast<IfInst *>(clone)->SetMethod(GetMethod());
315b1994897Sopenharmony_ci    return clone;
316b1994897Sopenharmony_ci}
317b1994897Sopenharmony_ci
318b1994897Sopenharmony_ciInst *IntrinsicInst::Clone(const Graph *targetGraph) const
319b1994897Sopenharmony_ci{
320b1994897Sopenharmony_ci    ASSERT(targetGraph != nullptr);
321b1994897Sopenharmony_ci    auto intrinsicClone = Inst::Clone(targetGraph)->CastToIntrinsic();
322b1994897Sopenharmony_ci    intrinsicClone->SetIntrinsicId(GetIntrinsicId());
323b1994897Sopenharmony_ci    CloneTypes(targetGraph->GetAllocator(), intrinsicClone);
324b1994897Sopenharmony_ci    if (HasImms()) {
325b1994897Sopenharmony_ci        for (auto imm : GetImms()) {
326b1994897Sopenharmony_ci            intrinsicClone->AddImm(targetGraph->GetAllocator(), imm);
327b1994897Sopenharmony_ci        }
328b1994897Sopenharmony_ci    }
329b1994897Sopenharmony_ci    return intrinsicClone;
330b1994897Sopenharmony_ci}
331b1994897Sopenharmony_ci
332b1994897Sopenharmony_ciInst *ConstantInst::Clone(const Graph *targetGraph) const
333b1994897Sopenharmony_ci{
334b1994897Sopenharmony_ci    Inst *new_cnst = nullptr;
335b1994897Sopenharmony_ci    bool is_support_int32 = GetBasicBlock()->GetGraph()->IsBytecodeOptimizer();
336b1994897Sopenharmony_ci    switch (GetType()) {
337b1994897Sopenharmony_ci        case DataType::INT32:
338b1994897Sopenharmony_ci            new_cnst = targetGraph->CreateInstConstant(static_cast<int32_t>(GetIntValue()), is_support_int32);
339b1994897Sopenharmony_ci            break;
340b1994897Sopenharmony_ci        case DataType::INT64:
341b1994897Sopenharmony_ci            new_cnst = targetGraph->CreateInstConstant(GetIntValue(), is_support_int32);
342b1994897Sopenharmony_ci            break;
343b1994897Sopenharmony_ci        case DataType::FLOAT32:
344b1994897Sopenharmony_ci            new_cnst = targetGraph->CreateInstConstant(GetFloatValue(), is_support_int32);
345b1994897Sopenharmony_ci            break;
346b1994897Sopenharmony_ci        case DataType::FLOAT64:
347b1994897Sopenharmony_ci            new_cnst = targetGraph->CreateInstConstant(GetDoubleValue(), is_support_int32);
348b1994897Sopenharmony_ci            break;
349b1994897Sopenharmony_ci        case DataType::ANY:
350b1994897Sopenharmony_ci            new_cnst = targetGraph->CreateInstConstant(GetRawValue(), is_support_int32);
351b1994897Sopenharmony_ci            new_cnst->SetType(DataType::ANY);
352b1994897Sopenharmony_ci            break;
353b1994897Sopenharmony_ci        default:
354b1994897Sopenharmony_ci            UNREACHABLE();
355b1994897Sopenharmony_ci    }
356b1994897Sopenharmony_ci#ifndef NDEBUG
357b1994897Sopenharmony_ci    new_cnst->SetDstReg(GetDstReg());
358b1994897Sopenharmony_ci#endif
359b1994897Sopenharmony_ci    return new_cnst;
360b1994897Sopenharmony_ci}
361b1994897Sopenharmony_ci
362b1994897Sopenharmony_ciInst *ParameterInst::Clone(const Graph *targetGraph) const
363b1994897Sopenharmony_ci{
364b1994897Sopenharmony_ci    auto clone = Inst::Clone(targetGraph)->CastToParameter();
365b1994897Sopenharmony_ci    clone->SetArgNumber(GetArgNumber());
366b1994897Sopenharmony_ci    clone->SetLocationData(GetLocationData());
367b1994897Sopenharmony_ci    return clone;
368b1994897Sopenharmony_ci}
369b1994897Sopenharmony_ci
370b1994897Sopenharmony_ciInst *SaveStateInst::Clone(const Graph *targetGraph) const
371b1994897Sopenharmony_ci{
372b1994897Sopenharmony_ci    auto clone = static_cast<SaveStateInst *>(Inst::Clone(targetGraph));
373b1994897Sopenharmony_ci    if (GetImmediatesCount() > 0) {
374b1994897Sopenharmony_ci        clone->AllocateImmediates(targetGraph->GetAllocator(), GetImmediatesCount());
375b1994897Sopenharmony_ci        std::copy(immediates_->begin(), immediates_->end(), clone->immediates_->begin());
376b1994897Sopenharmony_ci    }
377b1994897Sopenharmony_ci    clone->method_ = method_;
378b1994897Sopenharmony_ci    return clone;
379b1994897Sopenharmony_ci}
380b1994897Sopenharmony_ci
381b1994897Sopenharmony_civoid SaveStateInst::AppendImmediate(uint64_t imm, uint16_t vreg, DataType::Type type, bool is_acc)
382b1994897Sopenharmony_ci{
383b1994897Sopenharmony_ci    if (immediates_ == nullptr) {
384b1994897Sopenharmony_ci        ASSERT(GetBasicBlock() != nullptr);
385b1994897Sopenharmony_ci        AllocateImmediates(GetBasicBlock()->GetGraph()->GetAllocator(), 0);
386b1994897Sopenharmony_ci    }
387b1994897Sopenharmony_ci    immediates_->emplace_back(SaveStateImm {imm, vreg, type, is_acc});
388b1994897Sopenharmony_ci}
389b1994897Sopenharmony_ci
390b1994897Sopenharmony_civoid SaveStateInst::AllocateImmediates(ArenaAllocator *allocator, size_t size)
391b1994897Sopenharmony_ci{
392b1994897Sopenharmony_ci    immediates_ = allocator->New<ArenaVector<SaveStateImm>>(allocator->Adapter());
393b1994897Sopenharmony_ci    CHECK_NOT_NULL(immediates_);
394b1994897Sopenharmony_ci    immediates_->resize(size);
395b1994897Sopenharmony_ci}
396b1994897Sopenharmony_ci
397b1994897Sopenharmony_civoid TryInst::AppendCatchTypeId(uint32_t id, uint32_t catch_edge_index)
398b1994897Sopenharmony_ci{
399b1994897Sopenharmony_ci    if (catch_type_ids_ == nullptr) {
400b1994897Sopenharmony_ci        ASSERT(catch_edge_indexes_ == nullptr);
401b1994897Sopenharmony_ci        ASSERT(GetBasicBlock() != nullptr);
402b1994897Sopenharmony_ci        auto allocator = GetBasicBlock()->GetGraph()->GetAllocator();
403b1994897Sopenharmony_ci        catch_type_ids_ = allocator->New<ArenaVector<uint32_t>>(allocator->Adapter());
404b1994897Sopenharmony_ci        catch_edge_indexes_ = allocator->New<ArenaVector<uint32_t>>(allocator->Adapter());
405b1994897Sopenharmony_ci        CHECK_NOT_NULL(catch_type_ids_);
406b1994897Sopenharmony_ci        CHECK_NOT_NULL(catch_edge_indexes_);
407b1994897Sopenharmony_ci    }
408b1994897Sopenharmony_ci    catch_type_ids_->push_back(id);
409b1994897Sopenharmony_ci    catch_edge_indexes_->push_back(catch_edge_index);
410b1994897Sopenharmony_ci}
411b1994897Sopenharmony_ci
412b1994897Sopenharmony_civoid CatchPhiInst::AppendThrowableInst(const Inst *inst)
413b1994897Sopenharmony_ci{
414b1994897Sopenharmony_ci    if (throw_insts_ == nullptr) {
415b1994897Sopenharmony_ci        ASSERT(GetBasicBlock() != nullptr);
416b1994897Sopenharmony_ci        auto allocator = GetBasicBlock()->GetGraph()->GetAllocator();
417b1994897Sopenharmony_ci        throw_insts_ = allocator->New<ArenaVector<const Inst *>>(allocator->Adapter());
418b1994897Sopenharmony_ci        CHECK_NOT_NULL(throw_insts_);
419b1994897Sopenharmony_ci    }
420b1994897Sopenharmony_ci    throw_insts_->push_back(inst);
421b1994897Sopenharmony_ci}
422b1994897Sopenharmony_ci
423b1994897Sopenharmony_civoid CatchPhiInst::ReplaceThrowableInst(const Inst *old_inst, const Inst *new_inst)
424b1994897Sopenharmony_ci{
425b1994897Sopenharmony_ci    auto index = GetThrowableInstIndex(old_inst);
426b1994897Sopenharmony_ci    throw_insts_->at(index) = new_inst;
427b1994897Sopenharmony_ci}
428b1994897Sopenharmony_ci
429b1994897Sopenharmony_civoid CatchPhiInst::RemoveInput(unsigned index)
430b1994897Sopenharmony_ci{
431b1994897Sopenharmony_ci    Inst::RemoveInput(index);
432b1994897Sopenharmony_ci    if (throw_insts_ != nullptr) {
433b1994897Sopenharmony_ci        throw_insts_->at(index) = throw_insts_->back();
434b1994897Sopenharmony_ci        throw_insts_->pop_back();
435b1994897Sopenharmony_ci    }
436b1994897Sopenharmony_ci}
437b1994897Sopenharmony_ci
438b1994897Sopenharmony_ciInst *TryInst::Clone(const Graph *targetGraph) const
439b1994897Sopenharmony_ci{
440b1994897Sopenharmony_ci    auto clone = FixedInputsInst::Clone(targetGraph)->CastToTry();
441b1994897Sopenharmony_ci    if (auto ids_count = this->GetCatchTypeIdsCount(); ids_count > 0) {
442b1994897Sopenharmony_ci        if (clone->catch_type_ids_ == nullptr) {
443b1994897Sopenharmony_ci            auto allocator = targetGraph->GetAllocator();
444b1994897Sopenharmony_ci            clone->catch_type_ids_ = allocator->New<ArenaVector<uint32_t>>(allocator->Adapter());
445b1994897Sopenharmony_ci            clone->catch_edge_indexes_ = allocator->New<ArenaVector<uint32_t>>(allocator->Adapter());
446b1994897Sopenharmony_ci            CHECK_NOT_NULL(clone->catch_edge_indexes_);
447b1994897Sopenharmony_ci        }
448b1994897Sopenharmony_ci        clone->catch_type_ids_->resize(ids_count);
449b1994897Sopenharmony_ci        clone->catch_edge_indexes_->resize(ids_count);
450b1994897Sopenharmony_ci        std::copy(this->catch_type_ids_->begin(), this->catch_type_ids_->end(), clone->catch_type_ids_->begin());
451b1994897Sopenharmony_ci        std::copy(this->catch_edge_indexes_->begin(), this->catch_edge_indexes_->end(),
452b1994897Sopenharmony_ci                  clone->catch_edge_indexes_->begin());
453b1994897Sopenharmony_ci    }
454b1994897Sopenharmony_ci    return clone;
455b1994897Sopenharmony_ci}
456b1994897Sopenharmony_ci
457b1994897Sopenharmony_ciBasicBlock *IfImmInst::GetEdgeIfInputTrue()
458b1994897Sopenharmony_ci{
459b1994897Sopenharmony_ci    return GetBasicBlock()->GetSuccessor(GetTrueInputEdgeIdx());
460b1994897Sopenharmony_ci}
461b1994897Sopenharmony_ci
462b1994897Sopenharmony_ciBasicBlock *IfImmInst::GetEdgeIfInputFalse()
463b1994897Sopenharmony_ci{
464b1994897Sopenharmony_ci    return GetBasicBlock()->GetSuccessor(1 - GetTrueInputEdgeIdx());
465b1994897Sopenharmony_ci}
466b1994897Sopenharmony_ci
467b1994897Sopenharmony_ci/**
468b1994897Sopenharmony_ci * NB! Can be called before Lowering pass only
469b1994897Sopenharmony_ci * Return if_imm's block successor index when input is true
470b1994897Sopenharmony_ci */
471b1994897Sopenharmony_cisize_t IfImmInst::GetTrueInputEdgeIdx()
472b1994897Sopenharmony_ci{
473b1994897Sopenharmony_ci    ASSERT(GetBasicBlock() != nullptr);
474b1994897Sopenharmony_ci    ASSERT(GetBasicBlock()->GetSuccsBlocks().size() == MAX_SUCCS_NUM);
475b1994897Sopenharmony_ci    ASSERT(GetCc() == ConditionCode::CC_NE || GetCc() == ConditionCode::CC_EQ);
476b1994897Sopenharmony_ci    ASSERT(GetImm() == 0);
477b1994897Sopenharmony_ci    return GetCc() == CC_NE ? 0 : 1;
478b1994897Sopenharmony_ci}
479b1994897Sopenharmony_ci
480b1994897Sopenharmony_cibool Inst::IsPropagateLiveness() const
481b1994897Sopenharmony_ci{
482b1994897Sopenharmony_ci    return (CanThrow() && GetBasicBlock()->IsTry()) || CanDeoptimize();
483b1994897Sopenharmony_ci}
484b1994897Sopenharmony_ci
485b1994897Sopenharmony_cibool Inst::RequireRegMap() const
486b1994897Sopenharmony_ci{
487b1994897Sopenharmony_ci    return CanThrow() && GetBasicBlock()->IsTry();
488b1994897Sopenharmony_ci}
489b1994897Sopenharmony_ci
490b1994897Sopenharmony_cibool Inst::IsZeroRegInst() const
491b1994897Sopenharmony_ci{
492b1994897Sopenharmony_ci    ASSERT(GetBasicBlock() != nullptr);
493b1994897Sopenharmony_ci    ASSERT(GetBasicBlock()->GetGraph() != nullptr);
494b1994897Sopenharmony_ci    return false;
495b1994897Sopenharmony_ci}
496b1994897Sopenharmony_ci
497b1994897Sopenharmony_cibool Inst::IsAccRead() const
498b1994897Sopenharmony_ci{
499b1994897Sopenharmony_ci    return GetFlag(inst_flags::ACC_READ);
500b1994897Sopenharmony_ci}
501b1994897Sopenharmony_ci
502b1994897Sopenharmony_cibool Inst::IsAccWrite() const
503b1994897Sopenharmony_ci{
504b1994897Sopenharmony_ci    if (IsConst()) {
505b1994897Sopenharmony_ci        return true;
506b1994897Sopenharmony_ci    }
507b1994897Sopenharmony_ci    return GetFlag(inst_flags::ACC_WRITE);
508b1994897Sopenharmony_ci}
509b1994897Sopenharmony_ci
510b1994897Sopenharmony_ciTryInst *GetTryBeginInst(const BasicBlock *try_begin_bb)
511b1994897Sopenharmony_ci{
512b1994897Sopenharmony_ci    ASSERT(try_begin_bb != nullptr && try_begin_bb->IsTryBegin());
513b1994897Sopenharmony_ci    for (auto inst : try_begin_bb->AllInsts()) {
514b1994897Sopenharmony_ci        if (inst->GetOpcode() == Opcode::Try) {
515b1994897Sopenharmony_ci            return inst->CastToTry();
516b1994897Sopenharmony_ci        }
517b1994897Sopenharmony_ci    }
518b1994897Sopenharmony_ci    UNREACHABLE();
519b1994897Sopenharmony_ci    return nullptr;
520b1994897Sopenharmony_ci}
521b1994897Sopenharmony_ci
522b1994897Sopenharmony_ci/**
523b1994897Sopenharmony_ci * Regalloc's helper to checks if intrinsic's arguments should be located on the registers according to
524b1994897Sopenharmony_ci * calling-convention
525b1994897Sopenharmony_ci */
526b1994897Sopenharmony_cibool IntrinsicInst::IsNativeCall() const
527b1994897Sopenharmony_ci{
528b1994897Sopenharmony_ci    return false;
529b1994897Sopenharmony_ci}
530b1994897Sopenharmony_ci
531b1994897Sopenharmony_ci}  // namespace panda::compiler
532