• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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