1 /*
2 * Copyright (c) 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 "ic_slot_allocator.h"
17
18 #include "generated/ic_info.h"
19
20 namespace libabckit {
21
22 // CC-OFFNXT(WordsTool.95) sensitive word conflict
23 // NOLINTNEXTLINE(google-build-using-namespace)
24 using namespace ark;
25
RunImpl()26 bool ICSlotAllocator::RunImpl()
27 {
28 if (!Allocate8BitIcSlots()) {
29 return false;
30 }
31
32 if (!Allocate8Or16BitIcSlots()) {
33 return false;
34 }
35
36 if (!Allocate16BitIcSlots()) {
37 return false;
38 }
39
40 return true;
41 }
42
43 template <typename Callback>
VisitInstructions(const Callback & callback)44 void ICSlotAllocator::VisitInstructions(const Callback &callback)
45 {
46 for (auto bb : GetGraph()->GetBlocksRPO()) {
47 for (auto inst : bb->AllInsts()) {
48 callback(inst);
49 }
50 }
51 }
52
Allocate8BitIcSlots()53 bool ICSlotAllocator::Allocate8BitIcSlots()
54 {
55 VisitInstructions([this](compiler::Inst *inst) {
56 if (inst->GetOpcode() != compiler::Opcode::Intrinsic) {
57 return;
58 }
59
60 auto intrinsicInst = inst->CastToIntrinsic();
61 auto intrinsicId = intrinsicInst->GetIntrinsicId();
62 auto icFlags = GetIcFlags(intrinsicId);
63 if ((icFlags & IcFlags::EIGHT_BIT_IC) == 0) {
64 return;
65 }
66
67 if ((icFlags & IcFlags::ONE_SLOT) != 0 && nextFree8BitSlot_ < INVALID_8_BIT_SLOT) {
68 intrinsicInst->SetImm(0, nextFree8BitSlot_);
69 nextFree8BitSlot_ += 1U;
70 (*icSlotNumber_)++;
71 } else if ((icFlags & IcFlags::TWO_SLOT) != 0 && nextFree8BitSlot_ < INVALID_8_BIT_SLOT - 1U) {
72 intrinsicInst->SetImm(0, nextFree8BitSlot_);
73 nextFree8BitSlot_ += 2U;
74 (*icSlotNumber_) += 2U;
75 } else {
76 intrinsicInst->SetImm(0, INVALID_8_BIT_SLOT);
77 }
78 });
79
80 return true;
81 }
82
Allocate8Or16BitIcSlots()83 bool ICSlotAllocator::Allocate8Or16BitIcSlots()
84 {
85 VisitInstructions([this](compiler::Inst *inst) {
86 if (inst->GetOpcode() != compiler::Opcode::Intrinsic) {
87 return;
88 }
89
90 auto intrinsicInst = inst->CastToIntrinsic();
91 auto intrinsicId = intrinsicInst->GetIntrinsicId();
92 auto icFlags = GetIcFlags(intrinsicId);
93 if ((icFlags & IcFlags::EIGHT_SIXTEEN_BIT_IC) == 0) {
94 return;
95 }
96
97 if ((icFlags & IcFlags::ONE_SLOT) != 0 && nextFree8BitSlot_ < INVALID_8_BIT_SLOT) {
98 if (!HasInstWith8Or16BitSignature8BitIcSlot(intrinsicId)) {
99 intrinsicInst->SetIntrinsicId(GetIdWithInvertedIcImm(intrinsicId));
100 }
101 intrinsicInst->SetImm(0, nextFree8BitSlot_);
102 nextFree8BitSlot_ += 1U;
103 (*icSlotNumber_)++;
104 } else if ((icFlags & IcFlags::TWO_SLOT) != 0 && nextFree8BitSlot_ < INVALID_8_BIT_SLOT - 1U) {
105 if (!HasInstWith8Or16BitSignature8BitIcSlot(intrinsicId)) {
106 intrinsicInst->SetIntrinsicId(GetIdWithInvertedIcImm(intrinsicId));
107 }
108 intrinsicInst->SetImm(0, nextFree8BitSlot_);
109 nextFree8BitSlot_ += 2U;
110 (*icSlotNumber_) += 2U;
111 } else if ((icFlags & IcFlags::ONE_SLOT) != 0 && nextFree16BitSlot_ < INVALID_16_BIT_SLOT) {
112 if (HasInstWith8Or16BitSignature8BitIcSlot(intrinsicId)) {
113 intrinsicInst->SetIntrinsicId(GetIdWithInvertedIcImm(intrinsicId));
114 }
115 intrinsicInst->SetImm(0, nextFree16BitSlot_);
116 nextFree16BitSlot_ += 1U;
117 (*icSlotNumber_)++;
118 } else if ((icFlags & IcFlags::TWO_SLOT) != 0 && nextFree16BitSlot_ < INVALID_16_BIT_SLOT - 1U) {
119 if (HasInstWith8Or16BitSignature8BitIcSlot(intrinsicId)) {
120 intrinsicInst->SetIntrinsicId(GetIdWithInvertedIcImm(intrinsicId));
121 }
122 intrinsicInst->SetImm(0, nextFree16BitSlot_);
123 nextFree16BitSlot_ += 2U;
124 (*icSlotNumber_) += 2U;
125 } else {
126 if (!HasInstWith8Or16BitSignature8BitIcSlot(intrinsicId)) {
127 intrinsicInst->SetIntrinsicId(GetIdWithInvertedIcImm(intrinsicId));
128 }
129 intrinsicInst->SetImm(0, INVALID_8_BIT_SLOT);
130 }
131 });
132
133 return true;
134 }
135
Allocate16BitIcSlots()136 bool ICSlotAllocator::Allocate16BitIcSlots()
137 {
138 VisitInstructions([this](compiler::Inst *inst) {
139 if (inst->GetOpcode() != compiler::Opcode::Intrinsic) {
140 return;
141 }
142
143 auto intrinsicInst = inst->CastToIntrinsic();
144 auto intrinsicId = intrinsicInst->GetIntrinsicId();
145 auto icFlags = GetIcFlags(intrinsicId);
146 if ((icFlags & IcFlags::SIXTEEN_BIT_IC) == 0) {
147 return;
148 }
149
150 if ((icFlags & IcFlags::ONE_SLOT) != 0 && nextFree16BitSlot_ < INVALID_16_BIT_SLOT) {
151 intrinsicInst->SetImm(0, nextFree16BitSlot_);
152 nextFree16BitSlot_ += 1U;
153 (*icSlotNumber_)++;
154 } else if ((icFlags & IcFlags::TWO_SLOT) != 0 && nextFree16BitSlot_ < INVALID_16_BIT_SLOT - 1U) {
155 intrinsicInst->SetImm(0, nextFree16BitSlot_);
156 nextFree16BitSlot_ += 2U;
157 (*icSlotNumber_) += 2U;
158 } else {
159 intrinsicInst->SetImm(0, INVALID_16_BIT_SLOT);
160 }
161 });
162
163 return true;
164 }
165 } // namespace libabckit
166