1 /**
2 * Copyright (c) 2021-2022 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 "unit_test.h"
17 #include "inst_generator.h"
18 #include "optimizer/code_generator/codegen.h"
19 #include "optimizer/optimizations/regalloc/reg_alloc_linear_scan.h"
20 #include "target/amd64/target.h"
21 #include "target/aarch64/target.h"
22 #include "target/aarch32/target.h"
23
24 namespace panda::compiler {
25
26 class IntrinsicCodegenTest : public GraphTest {
27 public:
IntrinsicCodegenTest()28 IntrinsicCodegenTest()
29 : alloc_ {SpaceType::SPACE_TYPE_COMPILER},
30 local_alloc_ {SpaceType::SPACE_TYPE_COMPILER},
31 graph_creator_ {alloc_, local_alloc_},
32 aarch64_encoder_ {&alloc_},
33 aarch32_encoder_ {&alloc_},
34 amd64_encoder_ {&alloc_}
35 {
36 }
37
TryEncode(DataType::Type type,RuntimeInterface::IntrinsicId intrinsic_id,Arch arch,bool prepare_graph)38 bool TryEncode(DataType::Type type, RuntimeInterface::IntrinsicId intrinsic_id, Arch arch, bool prepare_graph)
39 {
40 graph_creator_.SetRuntimeTargetArch(arch);
41 auto inst = GenerateIntrinsic(&alloc_, type, intrinsic_id);
42 auto graph = graph_creator_.GenerateGraph(inst);
43 Codegen codegen(graph);
44 codegen.GetCodeBuilder()->BeginMethod(0, 0);
45 Reg dst = INVALID_REGISTER;
46 Codegen::SRCREGS src;
47 RegMask regmask;
48 if (prepare_graph) {
49 graph->GetAnalysis<LoopAnalyzer>().Run();
50 GraphChecker(graph).Check();
51 RegAllocLinearScan(graph).Run();
52 graph->SetStackSlotsCount(2U);
53 codegen.Initialize();
54 if (inst->GetType() != DataType::VOID) {
55 dst = codegen.ConvertRegister(0, inst->GetType());
56 }
57 uint8_t reg_id = 2;
58 for (size_t i = 0; i < inst->GetInputsCount(); i++, reg_id += 2) {
59 if (inst->GetInput(i).GetInst()->IsSaveState()) {
60 continue;
61 }
62 auto type = inst->GetInputType(i);
63 src[i] = codegen.ConvertRegister(2, type);
64 }
65 }
66 codegen.FillBuiltin(inst, src, dst, ®mask);
67 return codegen.GetEncoder()->GetResult();
68 }
69
70 private:
71 ArenaAllocator alloc_;
72 ArenaAllocator local_alloc_;
73 GraphCreator graph_creator_;
74 aarch64::Aarch64Encoder aarch64_encoder_;
75 aarch32::Aarch32Encoder aarch32_encoder_;
76 amd64::Amd64Encoder amd64_encoder_;
77
GenerateIntrinsic(ArenaAllocator * allocator,DataType::Type Type,RuntimeInterface::IntrinsicId intrinsic_id)78 IntrinsicInst *GenerateIntrinsic(ArenaAllocator *allocator, DataType::Type Type,
79 RuntimeInterface::IntrinsicId intrinsic_id)
80 {
81 auto inst = Inst::New<IntrinsicInst>(allocator, Opcode::Intrinsic);
82 inst->SetType(Type);
83 inst->SetIntrinsicId(intrinsic_id);
84 return inst;
85 }
86 };
87
88 #ifdef INTRINSIC_CODEGEN_TEST_ARM64
TEST_F(IntrinsicCodegenTest,EncodingARM64)89 TEST_F(IntrinsicCodegenTest, EncodingARM64)
90 {
91 std::pair<Arch, std::string> arch = std::pair {Arch::AARCH64, "arm64"};
92 #include "intrinsic_codegen_test.inl"
93 }
94 #endif
95
96 #ifdef INTRINSIC_CODEGEN_TEST_AMD64
TEST_F(IntrinsicCodegenTest,EncodingAMD64)97 TEST_F(IntrinsicCodegenTest, EncodingAMD64)
98 {
99 std::pair<Arch, std::string> arch = std::pair {Arch::X86_64, "amd64"};
100 #include "intrinsic_codegen_test.inl"
101 }
102 #endif
103
104 #ifdef INTRINSIC_CODEGEN_TEST_ARM32
TEST_F(IntrinsicCodegenTest,EncodingARM32)105 TEST_F(IntrinsicCodegenTest, EncodingARM32)
106 {
107 std::pair<Arch, std::string> arch = std::pair {Arch::AARCH32, "arm32"};
108 #include "intrinsic_codegen_test.inl"
109 }
110 #endif
111 } // namespace panda::compiler
112