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 "helpers_arithmetic.h"
17 #include "libabckit/include/c/abckit.h"
18 #include "helpers/helpers.h"
19 #include "libabckit/include/c/ir_core.h"
20 #include "libabckit/include/c/isa/isa_dynamic.h"
21 #include "libabckit/src/include_v2/c/isa/isa_static.h"
22 #include <gtest/gtest.h>
23
24 // NOLINTBEGIN(readability-magic-numbers)
25
26 static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
27 static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
28 static auto g_statG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0);
29 static auto g_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0);
30
31 namespace libabckit::test::helpers::arithmetic {
32
TransformIrUnaryInstValid(AbckitGraph * graph,AbckitInst * (* unaryInstToCheck)(AbckitGraph * graph,AbckitInst * input0),uint32_t operandId)33 void TransformIrUnaryInstValid(AbckitGraph *graph,
34 AbckitInst *(*unaryInstToCheck)(AbckitGraph *graph, AbckitInst *input0),
35 uint32_t operandId)
36 {
37 AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
38 AbckitInst *curInst = g_implG->bbGetFirstInst(startBB);
39
40 AbckitInst *firstInst = nullptr;
41 while (curInst != nullptr) {
42 if (g_implG->iGetId(curInst) == operandId) {
43 firstInst = curInst;
44 }
45 curInst = g_implG->iGetNext(curInst);
46 }
47
48 AbckitInst *retOp = nullptr;
49 if (g_implG->gGetIsa(graph) == ABCKIT_ISA_TYPE_DYNAMIC) {
50 retOp = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURN);
51 } else {
52 retOp = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_RETURN);
53 }
54 ASSERT_NE(retOp, nullptr);
55 AbckitInst *mainInst = unaryInstToCheck(graph, firstInst);
56 ASSERT_NE(mainInst, nullptr);
57 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
58 g_implG->iInsertBefore(mainInst, retOp);
59 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
60 g_implG->iSetInput(retOp, mainInst, 0);
61 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
62 }
63
IsMulOrAdd(AbckitGraph * graph,AbckitInst * inst)64 static bool IsMulOrAdd(AbckitGraph *graph, AbckitInst *inst)
65 {
66 if (g_implG->gGetIsa(graph) == ABCKIT_ISA_TYPE_DYNAMIC) {
67 AbckitIsaApiDynamicOpcode curOpcode = g_dynG->iGetOpcode(inst);
68 if (curOpcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_MUL2 && curOpcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_ADD2) {
69 return true;
70 }
71 } else if (g_implG->gGetIsa(graph) == ABCKIT_ISA_TYPE_STATIC) {
72 AbckitIsaApiStaticOpcode curOpcode = g_statG->iGetOpcode(inst);
73 if (curOpcode != ABCKIT_ISA_API_STATIC_OPCODE_MUL && curOpcode != ABCKIT_ISA_API_STATIC_OPCODE_ADD) {
74 return true;
75 }
76 } else {
77 LIBABCKIT_UNREACHABLE;
78 }
79 return false;
80 }
81
TransformIrBinInstrValid(AbckitGraph * graph,AbckitInst * (* binaryInstToCheck)(AbckitGraph * graph,AbckitInst * input0,AbckitInst * input1),uint32_t lhsId,uint32_t rhsId)82 void TransformIrBinInstrValid(AbckitGraph *graph,
83 AbckitInst *(*binaryInstToCheck)(AbckitGraph *graph, AbckitInst *input0,
84 AbckitInst *input1),
85 uint32_t lhsId, uint32_t rhsId)
86 {
87 AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
88 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
89
90 AbckitInst *curInst = g_implG->bbGetFirstInst(startBB);
91 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
92
93 AbckitInst *firstInst = nullptr;
94 AbckitInst *secondInst = nullptr;
95 while (curInst != nullptr) {
96 if (g_implG->iGetId(curInst) == lhsId) {
97 firstInst = curInst;
98 }
99 if (g_implG->iGetId(curInst) == rhsId) {
100 secondInst = curInst;
101 }
102 curInst = g_implG->iGetNext(curInst);
103 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
104 }
105 auto *bb = helpers::BBgetSuccBlocks(startBB)[0];
106 g_implG->bbGetFirstInst(bb);
107 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
108
109 curInst = g_implG->bbGetFirstInst(bb);
110 while (curInst != nullptr) {
111 if (IsMulOrAdd(graph, curInst)) {
112 curInst = g_implG->iGetNext(curInst);
113 continue;
114 }
115 auto extraInst = curInst;
116 curInst = g_implG->iGetNext(curInst);
117 g_implG->iRemove(extraInst);
118 }
119
120 AbckitInst *retOp = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURN);
121 if (retOp == nullptr) {
122 retOp = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_RETURN);
123 }
124 ASSERT_NE(retOp, nullptr);
125 AbckitInst *mainInst = binaryInstToCheck(graph, firstInst, secondInst);
126 ASSERT_NE(mainInst, nullptr);
127 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
128 g_implG->iInsertBefore(mainInst, retOp);
129 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
130 g_implG->iSetInput(retOp, mainInst, 0);
131 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
132 }
133
TransformIrBinInstrWithImmValid(AbckitGraph * graph,AbckitInst * (* binaryInstToCheck)(AbckitGraph * graph,AbckitInst * input0,uint64_t imm))134 void TransformIrBinInstrWithImmValid(AbckitGraph *graph,
135 AbckitInst *(*binaryInstToCheck)(AbckitGraph *graph, AbckitInst *input0,
136 uint64_t imm))
137 {
138 uint64_t imm = 0x5;
139
140 AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
141 AbckitInst *curInst = g_implG->bbGetFirstInst(startBB);
142
143 AbckitInst *firstInst = nullptr;
144 AbckitInst *mainInst = nullptr;
145 while (curInst != nullptr) {
146 if (g_implG->iGetId(curInst) == 1) {
147 firstInst = curInst;
148 }
149 curInst = g_implG->iGetNext(curInst);
150 }
151 std::vector<AbckitBasicBlock *> succBBs = helpers::BBgetSuccBlocks(startBB);
152 auto *bb = succBBs[0];
153 curInst = g_implG->bbGetFirstInst(bb);
154
155 while (curInst != nullptr) {
156 if (IsMulOrAdd(graph, curInst)) {
157 curInst = g_implG->iGetNext(curInst);
158 continue;
159 }
160 auto extraInst = curInst;
161 curInst = g_implG->iGetNext(curInst);
162 g_implG->iRemove(extraInst);
163 }
164
165 AbckitInst *retOp = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_RETURN);
166 mainInst = binaryInstToCheck(graph, firstInst, imm);
167 ASSERT_NE(graph, nullptr);
168 ASSERT_NE(mainInst, nullptr);
169 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
170 g_implG->iInsertBefore(mainInst, retOp);
171 g_implG->iSetInput(retOp, mainInst, 0);
172 }
173
CreateBBSchemaForBinary(AbckitIsaApiStaticOpcode opcode)174 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> CreateBBSchemaForBinary(AbckitIsaApiStaticOpcode opcode)
175 {
176 std::vector<helpers::InstSchema<AbckitIsaApiStaticOpcode>> instVector {};
177 if (opcode != ABCKIT_ISA_API_STATIC_OPCODE_MOD && opcode != ABCKIT_ISA_API_STATIC_OPCODE_DIV) {
178 instVector = {
179 {4, opcode, {1, 2}},
180 {5, ABCKIT_ISA_API_STATIC_OPCODE_RETURN, {4}},
181 };
182 } else {
183 instVector = {
184 {6, opcode, {1, 2}},
185 {7, ABCKIT_ISA_API_STATIC_OPCODE_RETURN, {6}},
186 };
187 }
188 return {{{},
189 {1},
190 {{0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
191 {1, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
192 {2, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}}}},
193 {{0}, {2}, instVector},
194 {{1}, {}, {}}};
195 }
196
CreateBBSchemaForDynBinary(AbckitIsaApiDynamicOpcode opcode)197 std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> CreateBBSchemaForDynBinary(AbckitIsaApiDynamicOpcode opcode)
198 {
199 std::vector<helpers::InstSchema<AbckitIsaApiDynamicOpcode>> instVector {};
200 std::vector<helpers::InstSchema<AbckitIsaApiDynamicOpcode>> paramInstVector {};
201 instVector = {
202 {6, opcode, {4, 3}},
203 {7, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURN, {6}},
204 };
205 paramInstVector = {{0, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
206 {1, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
207 {2, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
208 {3, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
209 {4, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}}};
210 return {{{}, {1}, paramInstVector}, {{0}, {2}, instVector}, {{1}, {}, {}}};
211 }
212
CreateBBSchemaForBinaryWithImm(AbckitIsaApiStaticOpcode opcode)213 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> CreateBBSchemaForBinaryWithImm(AbckitIsaApiStaticOpcode opcode)
214 {
215 std::vector<helpers::InstSchema<AbckitIsaApiStaticOpcode>> instVector {};
216 std::vector<helpers::InstSchema<AbckitIsaApiStaticOpcode>> startInstVector {};
217 if (opcode != ABCKIT_ISA_API_STATIC_OPCODE_ADDI && opcode != ABCKIT_ISA_API_STATIC_OPCODE_SUBI &&
218 opcode != ABCKIT_ISA_API_STATIC_OPCODE_MULI && opcode != ABCKIT_ISA_API_STATIC_OPCODE_DIVI &&
219 opcode != ABCKIT_ISA_API_STATIC_OPCODE_MODI) {
220 startInstVector = {{0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
221 {1, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
222 {2, ABCKIT_ISA_API_STATIC_OPCODE_CONSTANT, {}}};
223 } else {
224 startInstVector = {{0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
225 {1, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
226 {2, ABCKIT_ISA_API_STATIC_OPCODE_CONSTANT, {}},
227 {3, ABCKIT_ISA_API_STATIC_OPCODE_CONSTANT, {}}};
228 }
229 if (opcode != ABCKIT_ISA_API_STATIC_OPCODE_MODI && opcode != ABCKIT_ISA_API_STATIC_OPCODE_DIVI) {
230 instVector = {
231 {4, opcode, {1}},
232 {5, ABCKIT_ISA_API_STATIC_OPCODE_RETURN, {4}},
233 };
234 } else {
235 instVector = {
236 {5, opcode, {1}},
237 {4, ABCKIT_ISA_API_STATIC_OPCODE_RETURN, {5}},
238 };
239 }
240 return {{{}, {1}, startInstVector}, {{0}, {2}, instVector}, {{1}, {}, {}}};
241 }
242
CreateBBSchemaForUnary(AbckitIsaApiStaticOpcode opcode)243 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> CreateBBSchemaForUnary(AbckitIsaApiStaticOpcode opcode)
244 {
245 return {
246 {{}, {1}, {{0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}}, {1, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}}}},
247 {{0},
248 {2},
249 {
250 {3, opcode, {1}},
251 {4, ABCKIT_ISA_API_STATIC_OPCODE_RETURN, {3}},
252 }},
253 {{1}, {}, {}}};
254 }
255
CreateBBSchemaForDynUnary(AbckitIsaApiDynamicOpcode opcode)256 std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> CreateBBSchemaForDynUnary(AbckitIsaApiDynamicOpcode opcode)
257 {
258 return {{{},
259 {1},
260 {{0, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
261 {1, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
262 {2, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
263 {3, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}}}},
264 {{0},
265 {2},
266 {
267 {5, opcode, {3}},
268 {6, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURN, {5}},
269 }},
270 {{1}, {}, {}}};
271 }
272
273 } // namespace libabckit::test::helpers::arithmetic
274 // NOLINTEND(readability-magic-numbers)
275