1 /* 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 28 namespace art { 29 30 class 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, 42 CompilerOptions::kDefaultInlineDepthLimit, 43 CompilerOptions::kDefaultInlineMaxCodeUnits, 44 false, 45 CompilerOptions::kDefaultTopKProfileThreshold, 46 false, 47 CompilerOptions::kDefaultGenerateDebugInfo, 48 false, 49 false, 50 false, 51 false, 52 nullptr, 53 new PassManagerOptions(), 54 nullptr, 55 false)); 56 verification_results_.reset(new VerificationResults(compiler_options_.get())); 57 method_inliner_map_.reset(new DexFileToMethodInlinerMap()); 58 compiler_driver_.reset(new CompilerDriver( 59 compiler_options_.get(), 60 verification_results_.get(), 61 method_inliner_map_.get(), 62 Compiler::kQuick, 63 isa_, 64 nullptr, 65 false, 66 nullptr, 67 nullptr, 68 nullptr, 69 0, 70 false, 71 false, 72 "", 73 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 135 class 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 163 TEST_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 170 TEST_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 177 TEST_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 184 TEST_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 191 class 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 257 TEST_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 267 DECLARE_TEST(Addpd) 268 DECLARE_TEST(Subpd) 269 DECLARE_TEST(Mulpd) 270 271 } // namespace art 272