1 /* 2 * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include "common.h" 17 #include "compiler/optimizer/ir/basicblock.h" 18 #include "compiler/optimizer/ir/graph.h" 19 20 namespace ark::bytecodeopt { 21 AccReadIndex(const compiler::Inst * inst)22uint8_t AccReadIndex(const compiler::Inst *inst) 23 { 24 // For calls we cannot tell static index for acc position, thus 25 // ensure that we don't invoke this for calls 26 ASSERT(!inst->IsCallOrIntrinsic() || (inst->GetBasicBlock()->GetGraph()->IsAbcKit() && !inst->IsCall())); 27 28 switch (inst->GetOpcode()) { 29 case compiler::Opcode::LoadArray: 30 case compiler::Opcode::StoreObject: 31 case compiler::Opcode::StoreStatic: 32 case compiler::Opcode::NewArray: 33 return 1U; 34 case compiler::Opcode::StoreArray: 35 return 2U; 36 default: { 37 if (inst->IsIntrinsic() && inst->IsAccRead()) { 38 if (inst->GetBasicBlock()->GetGraph()->IsAbcKit()) { 39 ASSERT(inst->GetInputsCount() >= 1U); 40 return 0U; 41 } 42 ASSERT(inst->GetBasicBlock()->GetGraph()->IsDynamicMethod()); 43 ASSERT(inst->GetInputsCount() >= 2U); 44 return inst->GetInputsCount() - 2L; 45 } 46 return 0U; 47 } 48 } 49 } 50 51 #ifdef ENABLE_LIBABCKIT 52 #include "generated/abckit_intrinsics.inl" 53 #else IsAbcKitIntrinsicRange(compiler::RuntimeInterface::IntrinsicId intrinsicId)54bool IsAbcKitIntrinsicRange([[maybe_unused]] compiler::RuntimeInterface::IntrinsicId intrinsicId) 55 { 56 UNREACHABLE(); 57 } IsAbcKitIntrinsic(compiler::RuntimeInterface::IntrinsicId intrinsicId)58bool IsAbcKitIntrinsic([[maybe_unused]] compiler::RuntimeInterface::IntrinsicId intrinsicId) 59 { 60 UNREACHABLE(); 61 } 62 #endif 63 64 // This method is used by bytecode optimizer's codegen. CanConvertToIncI(const compiler::BinaryImmOperation * binop)65bool CanConvertToIncI(const compiler::BinaryImmOperation *binop) 66 { 67 ASSERT(binop->GetBasicBlock()->GetGraph()->IsRegAllocApplied()); 68 ASSERT(binop->GetOpcode() == compiler::Opcode::AddI || binop->GetOpcode() == compiler::Opcode::SubI); 69 70 // IncI works on the same register. 71 if (binop->GetSrcReg(0U) != binop->GetDstReg()) { 72 return false; 73 } 74 75 // IncI cannot write accumulator. 76 if (binop->GetSrcReg(0U) == compiler::GetAccReg()) { 77 return false; 78 } 79 80 // IncI users cannot read from accumulator. 81 // While Addi/SubI stores the output in accumulator, IncI works directly on registers. 82 for (const auto &user : binop->GetUsers()) { 83 const auto *uinst = user.GetInst(); 84 85 if (uinst->IsCallOrIntrinsic()) { 86 continue; 87 } 88 89 const uint8_t index = AccReadIndex(uinst); 90 if (uinst->GetInput(index).GetInst() == binop && uinst->GetSrcReg(index) == compiler::GetAccReg()) { 91 return false; 92 } 93 } 94 95 constexpr uint64_t BITMASK = 0xffffffff; 96 // Define min and max values of i4 type. 97 // NOLINTNEXTLINE(readability-identifier-naming) 98 constexpr int32_t min = -8; 99 // NOLINTNEXTLINE(readability-identifier-naming) 100 constexpr int32_t max = 7; 101 102 int32_t imm = binop->GetImm() & BITMASK; 103 // Note: subi 3 is the same as inci v2, -3. 104 if (binop->GetOpcode() == compiler::Opcode::SubI) { 105 imm = -imm; 106 } 107 108 // IncI works only with 4 bits immediates. 109 return imm >= min && imm <= max; 110 } 111 IsCall(compiler::Inst * inst)112bool IsCall(compiler::Inst *inst) 113 { 114 if (inst->GetBasicBlock()->GetGraph()->IsAbcKit()) { 115 if (inst->IsCall()) { 116 return true; 117 } 118 } else { 119 if (inst->IsCallOrIntrinsic()) { 120 return true; 121 } 122 } 123 return false; 124 } 125 126 } // namespace ark::bytecodeopt 127