Home | History | Annotate | Download | only in x86
      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