blob: e977ebf722842fa97c9331d1cfd2389e7be32c11 [file] [log] [blame]
Chao-ying Fuc4013ea2015-04-22 10:51:21 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "dex/quick/quick_compiler.h"
18#include "dex/pass_manager.h"
19#include "dex/verification_results.h"
20#include "dex/quick/dex_file_to_method_inliner_map.h"
21#include "runtime/dex_file.h"
22#include "driver/compiler_options.h"
23#include "driver/compiler_driver.h"
24#include "codegen_x86.h"
25#include "gtest/gtest.h"
26#include "utils/assembler_test_base.h"
27
28namespace art {
29
30class QuickAssembleX86TestBase : public testing::Test {
31 protected:
32 X86Mir2Lir* Prepare(InstructionSet target) {
33 isa_ = target;
34 pool_.reset(new ArenaPool());
35 compiler_options_.reset(new CompilerOptions(
36 CompilerOptions::kDefaultCompilerFilter,
37 CompilerOptions::kDefaultHugeMethodThreshold,
38 CompilerOptions::kDefaultLargeMethodThreshold,
39 CompilerOptions::kDefaultSmallMethodThreshold,
40 CompilerOptions::kDefaultTinyMethodThreshold,
41 CompilerOptions::kDefaultNumDexMethodsThreshold,
Calin Juravle0941b9d2015-07-29 18:59:13 +010042 CompilerOptions::kDefaultInlineDepthLimit,
43 CompilerOptions::kDefaultInlineMaxCodeUnits,
Chao-ying Fuc4013ea2015-04-22 10:51:21 -070044 false,
45 CompilerOptions::kDefaultTopKProfileThreshold,
46 false,
David Srbecky8363c772015-05-28 16:12:43 +010047 CompilerOptions::kDefaultGenerateDebugInfo,
Chao-ying Fuc4013ea2015-04-22 10:51:21 -070048 false,
49 false,
50 false,
51 false,
52 nullptr,
Chao-ying Fuc4013ea2015-04-22 10:51:21 -070053 nullptr,
54 false));
55 verification_results_.reset(new VerificationResults(compiler_options_.get()));
56 method_inliner_map_.reset(new DexFileToMethodInlinerMap());
57 compiler_driver_.reset(new CompilerDriver(
58 compiler_options_.get(),
59 verification_results_.get(),
60 method_inliner_map_.get(),
61 Compiler::kQuick,
62 isa_,
63 nullptr,
64 false,
65 nullptr,
66 nullptr,
67 nullptr,
68 0,
69 false,
70 false,
71 "",
Calin Juravle87000a92015-08-24 15:34:44 +010072 false,
Chao-ying Fuc4013ea2015-04-22 10:51:21 -070073 0,
74 -1,
75 ""));
76 cu_.reset(new CompilationUnit(pool_.get(), isa_, compiler_driver_.get(), nullptr));
77 DexFile::CodeItem* code_item = static_cast<DexFile::CodeItem*>(
78 cu_->arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc));
79 memset(code_item, 0, sizeof(DexFile::CodeItem));
80 cu_->mir_graph.reset(new MIRGraph(cu_.get(), &cu_->arena));
81 cu_->mir_graph->current_code_item_ = code_item;
82 cu_->cg.reset(QuickCompiler::GetCodeGenerator(cu_.get(), nullptr));
83
84 test_helper_.reset(new AssemblerTestInfrastructure(
85 isa_ == kX86 ? "x86" : "x86_64",
86 "as",
87 isa_ == kX86 ? " --32" : "",
88 "objdump",
89 " -h",
90 "objdump",
91 isa_ == kX86 ?
92 " -D -bbinary -mi386 --no-show-raw-insn" :
93 " -D -bbinary -mi386:x86-64 -Mx86-64,addr64,data32 --no-show-raw-insn",
94 nullptr));
95
96 X86Mir2Lir* m2l = static_cast<X86Mir2Lir*>(cu_->cg.get());
97 m2l->CompilerInitializeRegAlloc();
98 return m2l;
99 }
100
101 void Release() {
102 cu_.reset();
103 compiler_driver_.reset();
104 method_inliner_map_.reset();
105 verification_results_.reset();
106 compiler_options_.reset();
107 pool_.reset();
108
109 test_helper_.reset();
110 }
111
112 void TearDown() OVERRIDE {
113 Release();
114 }
115
116 bool CheckTools(InstructionSet target) {
117 Prepare(target);
118 bool result = test_helper_->CheckTools();
119 Release();
120 return result;
121 }
122
123 std::unique_ptr<CompilationUnit> cu_;
124 std::unique_ptr<AssemblerTestInfrastructure> test_helper_;
125
126 private:
127 InstructionSet isa_;
128 std::unique_ptr<ArenaPool> pool_;
129 std::unique_ptr<CompilerOptions> compiler_options_;
130 std::unique_ptr<VerificationResults> verification_results_;
131 std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_;
132 std::unique_ptr<CompilerDriver> compiler_driver_;
133};
134
135class QuickAssembleX86LowLevelTest : public QuickAssembleX86TestBase {
136 protected:
137 void Test(InstructionSet target, std::string test_name, std::string gcc_asm,
138 int opcode, int op0 = 0, int op1 = 0, int op2 = 0, int op3 = 0, int op4 = 0) {
139 X86Mir2Lir* m2l = Prepare(target);
140
141 LIR lir;
142 memset(&lir, 0, sizeof(LIR));
143 lir.opcode = opcode;
144 lir.operands[0] = op0;
145 lir.operands[1] = op1;
146 lir.operands[2] = op2;
147 lir.operands[3] = op3;
148 lir.operands[4] = op4;
149 lir.flags.size = m2l->GetInsnSize(&lir);
150
151 AssemblerStatus status = m2l->AssembleInstructions(&lir, 0);
152 // We don't expect a retry.
153 ASSERT_EQ(status, AssemblerStatus::kSuccess);
154
155 // Need a "base" std::vector.
156 std::vector<uint8_t> buffer(m2l->code_buffer_.begin(), m2l->code_buffer_.end());
157 test_helper_->Driver(buffer, gcc_asm, test_name);
158
159 Release();
160 }
161};
162
163TEST_F(QuickAssembleX86LowLevelTest, Addpd) {
164 Test(kX86, "Addpd", "addpd %xmm1, %xmm0\n", kX86AddpdRR,
165 RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
166 Test(kX86_64, "Addpd", "addpd %xmm1, %xmm0\n", kX86AddpdRR,
167 RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
168}
169
170TEST_F(QuickAssembleX86LowLevelTest, Subpd) {
171 Test(kX86, "Subpd", "subpd %xmm1, %xmm0\n", kX86SubpdRR,
172 RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
173 Test(kX86_64, "Subpd", "subpd %xmm1, %xmm0\n", kX86SubpdRR,
174 RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
175}
176
177TEST_F(QuickAssembleX86LowLevelTest, Mulpd) {
178 Test(kX86, "Mulpd", "mulpd %xmm1, %xmm0\n", kX86MulpdRR,
179 RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
180 Test(kX86_64, "Mulpd", "mulpd %xmm1, %xmm0\n", kX86MulpdRR,
181 RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg());
182}
183
nikolay serdjuke0705f52015-04-27 17:52:57 +0600184TEST_F(QuickAssembleX86LowLevelTest, Pextrw) {
185 Test(kX86, "Pextrw", "pextrw $7, %xmm3, 8(%eax)\n", kX86PextrwMRI,
186 RegStorage::Solo32(r0).GetReg(), 8, RegStorage::Solo128(3).GetReg(), 7);
187 Test(kX86_64, "Pextrw", "pextrw $7, %xmm8, 8(%r10)\n", kX86PextrwMRI,
188 RegStorage::Solo64(r10q).GetReg(), 8, RegStorage::Solo128(8).GetReg(), 7);
189}
190
Chao-ying Fuc4013ea2015-04-22 10:51:21 -0700191class QuickAssembleX86MacroTest : public QuickAssembleX86TestBase {
192 protected:
193 typedef void (X86Mir2Lir::*AsmFn)(MIR*);
194
195 void TestVectorFn(InstructionSet target,
196 Instruction::Code opcode,
197 AsmFn f,
198 std::string inst_string) {
199 X86Mir2Lir *m2l = Prepare(target);
200
201 // Create a vector MIR.
202 MIR* mir = cu_->mir_graph->NewMIR();
203 mir->dalvikInsn.opcode = opcode;
204 mir->dalvikInsn.vA = 0; // Destination and source.
205 mir->dalvikInsn.vB = 1; // Source.
206 int vector_size = 128;
207 int vector_type = kDouble;
208 mir->dalvikInsn.vC = (vector_type << 16) | vector_size; // Type size.
209 (m2l->*f)(mir);
210 m2l->AssembleLIR();
211
212 std::string gcc_asm = inst_string + " %xmm1, %xmm0\n";
213 // Need a "base" std::vector.
214 std::vector<uint8_t> buffer(m2l->code_buffer_.begin(), m2l->code_buffer_.end());
215 test_helper_->Driver(buffer, gcc_asm, inst_string);
216
217 Release();
218 }
219
220 // Tests are member functions as many of the assembler functions are protected or private,
221 // and it would be inelegant to define ART_FRIEND_TEST for all the tests.
222
223 void TestAddpd() {
224 TestVectorFn(kX86,
225 static_cast<Instruction::Code>(kMirOpPackedAddition),
226 &X86Mir2Lir::GenAddVector,
227 "addpd");
228 TestVectorFn(kX86_64,
229 static_cast<Instruction::Code>(kMirOpPackedAddition),
230 &X86Mir2Lir::GenAddVector,
231 "addpd");
232 }
233
234 void TestSubpd() {
235 TestVectorFn(kX86,
236 static_cast<Instruction::Code>(kMirOpPackedSubtract),
237 &X86Mir2Lir::GenSubtractVector,
238 "subpd");
239 TestVectorFn(kX86_64,
240 static_cast<Instruction::Code>(kMirOpPackedSubtract),
241 &X86Mir2Lir::GenSubtractVector,
242 "subpd");
243 }
244
245 void TestMulpd() {
246 TestVectorFn(kX86,
247 static_cast<Instruction::Code>(kMirOpPackedMultiply),
248 &X86Mir2Lir::GenMultiplyVector,
249 "mulpd");
250 TestVectorFn(kX86_64,
251 static_cast<Instruction::Code>(kMirOpPackedMultiply),
252 &X86Mir2Lir::GenMultiplyVector,
253 "mulpd");
254 }
255};
256
257TEST_F(QuickAssembleX86MacroTest, CheckTools) {
258 ASSERT_TRUE(CheckTools(kX86)) << "x86 tools not found.";
259 ASSERT_TRUE(CheckTools(kX86_64)) << "x86_64 tools not found.";
260}
261
262#define DECLARE_TEST(name) \
263 TEST_F(QuickAssembleX86MacroTest, name) { \
264 Test ## name(); \
265 }
266
267DECLARE_TEST(Addpd)
268DECLARE_TEST(Subpd)
269DECLARE_TEST(Mulpd)
270
271} // namespace art