diff options
| author | 2015-04-26 01:12:52 +0000 | |
|---|---|---|
| committer | 2015-04-26 01:12:52 +0000 | |
| commit | 357b71e188bb4aa371cc7d834f573cb7a8f30f44 (patch) | |
| tree | 39818190d99cc7fdae7c3c2c3dbbb5b50ee33f68 /compiler | |
| parent | 29d577f58f9153c2c0a9b381afe4070bc00941b8 (diff) | |
| parent | bd90c932e570b28406932e33f2aa3c113ba2efa3 (diff) | |
am bd90c932: am 711d8400: Merge "ART: Fix addpd opcode, add Quick x86 assembler test"
* commit 'bd90c932e570b28406932e33f2aa3c113ba2efa3':
ART: Fix addpd opcode, add Quick x86 assembler test
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/dex/mir_graph.h | 1 | ||||
| -rw-r--r-- | compiler/dex/quick/x86/assemble_x86.cc | 8 | ||||
| -rw-r--r-- | compiler/dex/quick/x86/codegen_x86.h | 5 | ||||
| -rw-r--r-- | compiler/dex/quick/x86/quick_assemble_x86_test.cc | 263 |
4 files changed, 272 insertions, 5 deletions
diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index 7f9698bbee..7bfbb34ae9 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -1451,6 +1451,7 @@ class MIRGraph { friend class TopologicalSortOrderTest; friend class TypeInferenceTest; friend class QuickCFITest; + friend class QuickAssembleX86TestBase; }; } // namespace art diff --git a/compiler/dex/quick/x86/assemble_x86.cc b/compiler/dex/quick/x86/assemble_x86.cc index eb3335798e..934fa3509c 100644 --- a/compiler/dex/quick/x86/assemble_x86.cc +++ b/compiler/dex/quick/x86/assemble_x86.cc @@ -409,7 +409,7 @@ ENCODING_MAP(Cmp, IS_LOAD, 0, 0, EXT_0F_ENCODING_MAP(Paddq, 0x66, 0xD4, REG_DEF0_USE0), EXT_0F_ENCODING_MAP(Psadbw, 0x66, 0xF6, REG_DEF0_USE0), EXT_0F_ENCODING_MAP(Addps, 0x00, 0x58, REG_DEF0_USE0), - EXT_0F_ENCODING_MAP(Addpd, 0xF2, 0x58, REG_DEF0_USE0), + EXT_0F_ENCODING_MAP(Addpd, 0x66, 0x58, REG_DEF0_USE0), EXT_0F_ENCODING_MAP(Psubb, 0x66, 0xF8, REG_DEF0_USE0), EXT_0F_ENCODING_MAP(Psubw, 0x66, 0xF9, REG_DEF0_USE0), EXT_0F_ENCODING_MAP(Psubd, 0x66, 0xFA, REG_DEF0_USE0), @@ -1627,13 +1627,13 @@ void X86Mir2Lir::EmitUnimplemented(const X86EncodingMap* entry, LIR* lir) { * instruction. In those cases we will try to substitute a new code * sequence or request that the trace be shortened and retried. */ -AssemblerStatus X86Mir2Lir::AssembleInstructions(CodeOffset start_addr) { +AssemblerStatus X86Mir2Lir::AssembleInstructions(LIR* first_lir_insn, CodeOffset start_addr) { UNUSED(start_addr); LIR *lir; AssemblerStatus res = kSuccess; // Assume success const bool kVerbosePcFixup = false; - for (lir = first_lir_insn_; lir != nullptr; lir = NEXT_LIR(lir)) { + for (lir = first_lir_insn; lir != nullptr; lir = NEXT_LIR(lir)) { if (IsPseudoLirOp(lir->opcode)) { continue; } @@ -2034,7 +2034,7 @@ void X86Mir2Lir::AssembleLIR() { */ while (true) { - AssemblerStatus res = AssembleInstructions(0); + AssemblerStatus res = AssembleInstructions(first_lir_insn_, 0); if (res == kSuccess) { break; } else { diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h index 72580a3e39..5a465203bc 100644 --- a/compiler/dex/quick/x86/codegen_x86.h +++ b/compiler/dex/quick/x86/codegen_x86.h @@ -432,7 +432,7 @@ class X86Mir2Lir FINAL : public Mir2Lir { int AssignInsnOffsets(); void AssignOffsets(); - AssemblerStatus AssembleInstructions(CodeOffset start_addr); + AssemblerStatus AssembleInstructions(LIR* first_lir_insn, CodeOffset start_addr); size_t ComputeSize(const X86EncodingMap* entry, int32_t raw_reg, int32_t raw_index, int32_t raw_base, int32_t displacement); @@ -972,6 +972,9 @@ class X86Mir2Lir FINAL : public Mir2Lir { static const X86EncodingMap EncodingMap[kX86Last]; friend std::ostream& operator<<(std::ostream& os, const X86OpCode& rhs); + friend class QuickAssembleX86Test; + friend class QuickAssembleX86MacroTest; + friend class QuickAssembleX86LowLevelTest; DISALLOW_COPY_AND_ASSIGN(X86Mir2Lir); }; diff --git a/compiler/dex/quick/x86/quick_assemble_x86_test.cc b/compiler/dex/quick/x86/quick_assemble_x86_test.cc new file mode 100644 index 0000000000..36339f72e4 --- /dev/null +++ b/compiler/dex/quick/x86/quick_assemble_x86_test.cc @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dex/quick/quick_compiler.h" +#include "dex/pass_manager.h" +#include "dex/verification_results.h" +#include "dex/quick/dex_file_to_method_inliner_map.h" +#include "runtime/dex_file.h" +#include "driver/compiler_options.h" +#include "driver/compiler_driver.h" +#include "codegen_x86.h" +#include "gtest/gtest.h" +#include "utils/assembler_test_base.h" + +namespace art { + +class QuickAssembleX86TestBase : public testing::Test { + protected: + X86Mir2Lir* Prepare(InstructionSet target) { + isa_ = target; + pool_.reset(new ArenaPool()); + compiler_options_.reset(new CompilerOptions( + CompilerOptions::kDefaultCompilerFilter, + CompilerOptions::kDefaultHugeMethodThreshold, + CompilerOptions::kDefaultLargeMethodThreshold, + CompilerOptions::kDefaultSmallMethodThreshold, + CompilerOptions::kDefaultTinyMethodThreshold, + CompilerOptions::kDefaultNumDexMethodsThreshold, + false, + CompilerOptions::kDefaultTopKProfileThreshold, + false, + false, + false, + false, + false, + false, + false, + nullptr, + new PassManagerOptions(), + nullptr, + false)); + verification_results_.reset(new VerificationResults(compiler_options_.get())); + method_inliner_map_.reset(new DexFileToMethodInlinerMap()); + compiler_driver_.reset(new CompilerDriver( + compiler_options_.get(), + verification_results_.get(), + method_inliner_map_.get(), + Compiler::kQuick, + isa_, + nullptr, + false, + nullptr, + nullptr, + nullptr, + 0, + false, + false, + "", + 0, + -1, + "")); + cu_.reset(new CompilationUnit(pool_.get(), isa_, compiler_driver_.get(), nullptr)); + DexFile::CodeItem* code_item = static_cast<DexFile::CodeItem*>( + cu_->arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc)); + memset(code_item, 0, sizeof(DexFile::CodeItem)); + cu_->mir_graph.reset(new MIRGraph(cu_.get(), &cu_->arena)); + cu_->mir_graph->current_code_item_ = code_item; + cu_->cg.reset(QuickCompiler::GetCodeGenerator(cu_.get(), nullptr)); + + test_helper_.reset(new AssemblerTestInfrastructure( + isa_ == kX86 ? "x86" : "x86_64", + "as", + isa_ == kX86 ? " --32" : "", + "objdump", + " -h", + "objdump", + isa_ == kX86 ? + " -D -bbinary -mi386 --no-show-raw-insn" : + " -D -bbinary -mi386:x86-64 -Mx86-64,addr64,data32 --no-show-raw-insn", + nullptr)); + + X86Mir2Lir* m2l = static_cast<X86Mir2Lir*>(cu_->cg.get()); + m2l->CompilerInitializeRegAlloc(); + return m2l; + } + + void Release() { + cu_.reset(); + compiler_driver_.reset(); + method_inliner_map_.reset(); + verification_results_.reset(); + compiler_options_.reset(); + pool_.reset(); + + test_helper_.reset(); + } + + void TearDown() OVERRIDE { + Release(); + } + + bool CheckTools(InstructionSet target) { + Prepare(target); + bool result = test_helper_->CheckTools(); + Release(); + return result; + } + + std::unique_ptr<CompilationUnit> cu_; + std::unique_ptr<AssemblerTestInfrastructure> test_helper_; + + private: + InstructionSet isa_; + std::unique_ptr<ArenaPool> pool_; + std::unique_ptr<CompilerOptions> compiler_options_; + std::unique_ptr<VerificationResults> verification_results_; + std::unique_ptr<DexFileToMethodInlinerMap> method_inliner_map_; + std::unique_ptr<CompilerDriver> compiler_driver_; +}; + +class QuickAssembleX86LowLevelTest : public QuickAssembleX86TestBase { + protected: + void Test(InstructionSet target, std::string test_name, std::string gcc_asm, + int opcode, int op0 = 0, int op1 = 0, int op2 = 0, int op3 = 0, int op4 = 0) { + X86Mir2Lir* m2l = Prepare(target); + + LIR lir; + memset(&lir, 0, sizeof(LIR)); + lir.opcode = opcode; + lir.operands[0] = op0; + lir.operands[1] = op1; + lir.operands[2] = op2; + lir.operands[3] = op3; + lir.operands[4] = op4; + lir.flags.size = m2l->GetInsnSize(&lir); + + AssemblerStatus status = m2l->AssembleInstructions(&lir, 0); + // We don't expect a retry. + ASSERT_EQ(status, AssemblerStatus::kSuccess); + + // Need a "base" std::vector. + std::vector<uint8_t> buffer(m2l->code_buffer_.begin(), m2l->code_buffer_.end()); + test_helper_->Driver(buffer, gcc_asm, test_name); + + Release(); + } +}; + +TEST_F(QuickAssembleX86LowLevelTest, Addpd) { + Test(kX86, "Addpd", "addpd %xmm1, %xmm0\n", kX86AddpdRR, + RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg()); + Test(kX86_64, "Addpd", "addpd %xmm1, %xmm0\n", kX86AddpdRR, + RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg()); +} + +TEST_F(QuickAssembleX86LowLevelTest, Subpd) { + Test(kX86, "Subpd", "subpd %xmm1, %xmm0\n", kX86SubpdRR, + RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg()); + Test(kX86_64, "Subpd", "subpd %xmm1, %xmm0\n", kX86SubpdRR, + RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg()); +} + +TEST_F(QuickAssembleX86LowLevelTest, Mulpd) { + Test(kX86, "Mulpd", "mulpd %xmm1, %xmm0\n", kX86MulpdRR, + RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg()); + Test(kX86_64, "Mulpd", "mulpd %xmm1, %xmm0\n", kX86MulpdRR, + RegStorage::Solo128(0).GetReg(), RegStorage::Solo128(1).GetReg()); +} + +class QuickAssembleX86MacroTest : public QuickAssembleX86TestBase { + protected: + typedef void (X86Mir2Lir::*AsmFn)(MIR*); + + void TestVectorFn(InstructionSet target, + Instruction::Code opcode, + AsmFn f, + std::string inst_string) { + X86Mir2Lir *m2l = Prepare(target); + + // Create a vector MIR. + MIR* mir = cu_->mir_graph->NewMIR(); + mir->dalvikInsn.opcode = opcode; + mir->dalvikInsn.vA = 0; // Destination and source. + mir->dalvikInsn.vB = 1; // Source. + int vector_size = 128; + int vector_type = kDouble; + mir->dalvikInsn.vC = (vector_type << 16) | vector_size; // Type size. + (m2l->*f)(mir); + m2l->AssembleLIR(); + + std::string gcc_asm = inst_string + " %xmm1, %xmm0\n"; + // Need a "base" std::vector. + std::vector<uint8_t> buffer(m2l->code_buffer_.begin(), m2l->code_buffer_.end()); + test_helper_->Driver(buffer, gcc_asm, inst_string); + + Release(); + } + + // Tests are member functions as many of the assembler functions are protected or private, + // and it would be inelegant to define ART_FRIEND_TEST for all the tests. + + void TestAddpd() { + TestVectorFn(kX86, + static_cast<Instruction::Code>(kMirOpPackedAddition), + &X86Mir2Lir::GenAddVector, + "addpd"); + TestVectorFn(kX86_64, + static_cast<Instruction::Code>(kMirOpPackedAddition), + &X86Mir2Lir::GenAddVector, + "addpd"); + } + + void TestSubpd() { + TestVectorFn(kX86, + static_cast<Instruction::Code>(kMirOpPackedSubtract), + &X86Mir2Lir::GenSubtractVector, + "subpd"); + TestVectorFn(kX86_64, + static_cast<Instruction::Code>(kMirOpPackedSubtract), + &X86Mir2Lir::GenSubtractVector, + "subpd"); + } + + void TestMulpd() { + TestVectorFn(kX86, + static_cast<Instruction::Code>(kMirOpPackedMultiply), + &X86Mir2Lir::GenMultiplyVector, + "mulpd"); + TestVectorFn(kX86_64, + static_cast<Instruction::Code>(kMirOpPackedMultiply), + &X86Mir2Lir::GenMultiplyVector, + "mulpd"); + } +}; + +TEST_F(QuickAssembleX86MacroTest, CheckTools) { + ASSERT_TRUE(CheckTools(kX86)) << "x86 tools not found."; + ASSERT_TRUE(CheckTools(kX86_64)) << "x86_64 tools not found."; +} + +#define DECLARE_TEST(name) \ + TEST_F(QuickAssembleX86MacroTest, name) { \ + Test ## name(); \ + } + +DECLARE_TEST(Addpd) +DECLARE_TEST(Subpd) +DECLARE_TEST(Mulpd) + +} // namespace art |