Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2014 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 "arch/x86/instruction_set_features_x86.h"
     18 #include "base/arena_allocator.h"
     19 #include "builder.h"
     20 #include "code_generator.h"
     21 #include "code_generator_x86.h"
     22 #include "dex_file.h"
     23 #include "dex_instruction.h"
     24 #include "driver/compiler_options.h"
     25 #include "nodes.h"
     26 #include "optimizing_unit_test.h"
     27 #include "register_allocator.h"
     28 #include "ssa_liveness_analysis.h"
     29 #include "ssa_phi_elimination.h"
     30 
     31 namespace art {
     32 
     33 // Note: the register allocator tests rely on the fact that constants have live
     34 // intervals and registers get allocated to them.
     35 
     36 class RegisterAllocatorTest : public CommonCompilerTest {};
     37 
     38 static bool Check(const uint16_t* data) {
     39   ArenaPool pool;
     40   ArenaAllocator allocator(&pool);
     41   HGraph* graph = CreateCFG(&allocator, data);
     42   std::unique_ptr<const X86InstructionSetFeatures> features_x86(
     43       X86InstructionSetFeatures::FromCppDefines());
     44   x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
     45   SsaLivenessAnalysis liveness(graph, &codegen);
     46   liveness.Analyze();
     47   RegisterAllocator register_allocator(&allocator, &codegen, liveness);
     48   register_allocator.AllocateRegisters();
     49   return register_allocator.Validate(false);
     50 }
     51 
     52 /**
     53  * Unit testing of RegisterAllocator::ValidateIntervals. Register allocator
     54  * tests are based on this validation method.
     55  */
     56 TEST_F(RegisterAllocatorTest, ValidateIntervals) {
     57   ArenaPool pool;
     58   ArenaAllocator allocator(&pool);
     59   HGraph* graph = CreateGraph(&allocator);
     60   std::unique_ptr<const X86InstructionSetFeatures> features_x86(
     61       X86InstructionSetFeatures::FromCppDefines());
     62   x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
     63   ArenaVector<LiveInterval*> intervals(allocator.Adapter());
     64 
     65   // Test with two intervals of the same range.
     66   {
     67     static constexpr size_t ranges[][2] = {{0, 42}};
     68     intervals.push_back(BuildInterval(ranges, arraysize(ranges), &allocator, 0));
     69     intervals.push_back(BuildInterval(ranges, arraysize(ranges), &allocator, 1));
     70     ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
     71         intervals, 0, 0, codegen, &allocator, true, false));
     72 
     73     intervals[1]->SetRegister(0);
     74     ASSERT_FALSE(RegisterAllocator::ValidateIntervals(
     75         intervals, 0, 0, codegen, &allocator, true, false));
     76     intervals.clear();
     77   }
     78 
     79   // Test with two non-intersecting intervals.
     80   {
     81     static constexpr size_t ranges1[][2] = {{0, 42}};
     82     intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), &allocator, 0));
     83     static constexpr size_t ranges2[][2] = {{42, 43}};
     84     intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), &allocator, 1));
     85     ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
     86         intervals, 0, 0, codegen, &allocator, true, false));
     87 
     88     intervals[1]->SetRegister(0);
     89     ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
     90         intervals, 0, 0, codegen, &allocator, true, false));
     91     intervals.clear();
     92   }
     93 
     94   // Test with two non-intersecting intervals, with one with a lifetime hole.
     95   {
     96     static constexpr size_t ranges1[][2] = {{0, 42}, {45, 48}};
     97     intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), &allocator, 0));
     98     static constexpr size_t ranges2[][2] = {{42, 43}};
     99     intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), &allocator, 1));
    100     ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
    101         intervals, 0, 0, codegen, &allocator, true, false));
    102 
    103     intervals[1]->SetRegister(0);
    104     ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
    105         intervals, 0, 0, codegen, &allocator, true, false));
    106     intervals.clear();
    107   }
    108 
    109   // Test with intersecting intervals.
    110   {
    111     static constexpr size_t ranges1[][2] = {{0, 42}, {44, 48}};
    112     intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), &allocator, 0));
    113     static constexpr size_t ranges2[][2] = {{42, 47}};
    114     intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), &allocator, 1));
    115     ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
    116         intervals, 0, 0, codegen, &allocator, true, false));
    117 
    118     intervals[1]->SetRegister(0);
    119     ASSERT_FALSE(RegisterAllocator::ValidateIntervals(
    120         intervals, 0, 0, codegen, &allocator, true, false));
    121     intervals.clear();
    122   }
    123 
    124   // Test with siblings.
    125   {
    126     static constexpr size_t ranges1[][2] = {{0, 42}, {44, 48}};
    127     intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), &allocator, 0));
    128     intervals[0]->SplitAt(43);
    129     static constexpr size_t ranges2[][2] = {{42, 47}};
    130     intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), &allocator, 1));
    131     ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
    132         intervals, 0, 0, codegen, &allocator, true, false));
    133 
    134     intervals[1]->SetRegister(0);
    135     // Sibling of the first interval has no register allocated to it.
    136     ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
    137         intervals, 0, 0, codegen, &allocator, true, false));
    138 
    139     intervals[0]->GetNextSibling()->SetRegister(0);
    140     ASSERT_FALSE(RegisterAllocator::ValidateIntervals(
    141         intervals, 0, 0, codegen, &allocator, true, false));
    142   }
    143 }
    144 
    145 TEST_F(RegisterAllocatorTest, CFG1) {
    146   /*
    147    * Test the following snippet:
    148    *  return 0;
    149    *
    150    * Which becomes the following graph:
    151    *       constant0
    152    *       goto
    153    *        |
    154    *       return
    155    *        |
    156    *       exit
    157    */
    158   const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
    159     Instruction::CONST_4 | 0 | 0,
    160     Instruction::RETURN);
    161 
    162   ASSERT_TRUE(Check(data));
    163 }
    164 
    165 TEST_F(RegisterAllocatorTest, Loop1) {
    166   /*
    167    * Test the following snippet:
    168    *  int a = 0;
    169    *  while (a == a) {
    170    *    a = 4;
    171    *  }
    172    *  return 5;
    173    *
    174    * Which becomes the following graph:
    175    *       constant0
    176    *       constant4
    177    *       constant5
    178    *       goto
    179    *        |
    180    *       goto
    181    *        |
    182    *       phi
    183    *       equal
    184    *       if +++++
    185    *        |       \ +
    186    *        |     goto
    187    *        |
    188    *       return
    189    *        |
    190    *       exit
    191    */
    192 
    193   const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
    194     Instruction::CONST_4 | 0 | 0,
    195     Instruction::IF_EQ, 4,
    196     Instruction::CONST_4 | 4 << 12 | 0,
    197     Instruction::GOTO | 0xFD00,
    198     Instruction::CONST_4 | 5 << 12 | 1 << 8,
    199     Instruction::RETURN | 1 << 8);
    200 
    201   ASSERT_TRUE(Check(data));
    202 }
    203 
    204 TEST_F(RegisterAllocatorTest, Loop2) {
    205   /*
    206    * Test the following snippet:
    207    *  int a = 0;
    208    *  while (a == 8) {
    209    *    a = 4 + 5;
    210    *  }
    211    *  return 6 + 7;
    212    *
    213    * Which becomes the following graph:
    214    *       constant0
    215    *       constant4
    216    *       constant5
    217    *       constant6
    218    *       constant7
    219    *       constant8
    220    *       goto
    221    *        |
    222    *       goto
    223    *        |
    224    *       phi
    225    *       equal
    226    *       if +++++
    227    *        |       \ +
    228    *        |      4 + 5
    229    *        |      goto
    230    *        |
    231    *       6 + 7
    232    *       return
    233    *        |
    234    *       exit
    235    */
    236 
    237   const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
    238     Instruction::CONST_4 | 0 | 0,
    239     Instruction::CONST_4 | 8 << 12 | 1 << 8,
    240     Instruction::IF_EQ | 1 << 8, 7,
    241     Instruction::CONST_4 | 4 << 12 | 0 << 8,
    242     Instruction::CONST_4 | 5 << 12 | 1 << 8,
    243     Instruction::ADD_INT, 1 << 8 | 0,
    244     Instruction::GOTO | 0xFA00,
    245     Instruction::CONST_4 | 6 << 12 | 1 << 8,
    246     Instruction::CONST_4 | 7 << 12 | 1 << 8,
    247     Instruction::ADD_INT, 1 << 8 | 0,
    248     Instruction::RETURN | 1 << 8);
    249 
    250   ASSERT_TRUE(Check(data));
    251 }
    252 
    253 TEST_F(RegisterAllocatorTest, Loop3) {
    254   /*
    255    * Test the following snippet:
    256    *  int a = 0
    257    *  do {
    258    *    b = a;
    259    *    a++;
    260    *  } while (a != 5)
    261    *  return b;
    262    *
    263    * Which becomes the following graph:
    264    *       constant0
    265    *       constant1
    266    *       constant5
    267    *       goto
    268    *        |
    269    *       goto
    270    *        |++++++++++++
    271    *       phi          +
    272    *       a++          +
    273    *       equals       +
    274    *       if           +
    275    *        |++++++++++++
    276    *       return
    277    *        |
    278    *       exit
    279    */
    280 
    281   const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
    282     Instruction::CONST_4 | 0 | 0,
    283     Instruction::ADD_INT_LIT8 | 1 << 8, 1 << 8,
    284     Instruction::CONST_4 | 5 << 12 | 2 << 8,
    285     Instruction::IF_NE | 1 << 8 | 2 << 12, 3,
    286     Instruction::RETURN | 0 << 8,
    287     Instruction::MOVE | 1 << 12 | 0 << 8,
    288     Instruction::GOTO | 0xF900);
    289 
    290   ArenaPool pool;
    291   ArenaAllocator allocator(&pool);
    292   HGraph* graph = CreateCFG(&allocator, data);
    293   std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    294       X86InstructionSetFeatures::FromCppDefines());
    295   x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    296   SsaLivenessAnalysis liveness(graph, &codegen);
    297   liveness.Analyze();
    298   RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    299   register_allocator.AllocateRegisters();
    300   ASSERT_TRUE(register_allocator.Validate(false));
    301 
    302   HBasicBlock* loop_header = graph->GetBlocks()[2];
    303   HPhi* phi = loop_header->GetFirstPhi()->AsPhi();
    304 
    305   LiveInterval* phi_interval = phi->GetLiveInterval();
    306   LiveInterval* loop_update = phi->InputAt(1)->GetLiveInterval();
    307   ASSERT_TRUE(phi_interval->HasRegister());
    308   ASSERT_TRUE(loop_update->HasRegister());
    309   ASSERT_NE(phi_interval->GetRegister(), loop_update->GetRegister());
    310 
    311   HBasicBlock* return_block = graph->GetBlocks()[3];
    312   HReturn* ret = return_block->GetLastInstruction()->AsReturn();
    313   ASSERT_EQ(phi_interval->GetRegister(), ret->InputAt(0)->GetLiveInterval()->GetRegister());
    314 }
    315 
    316 TEST_F(RegisterAllocatorTest, FirstRegisterUse) {
    317   const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
    318     Instruction::CONST_4 | 0 | 0,
    319     Instruction::XOR_INT_LIT8 | 1 << 8, 1 << 8,
    320     Instruction::XOR_INT_LIT8 | 0 << 8, 1 << 8,
    321     Instruction::XOR_INT_LIT8 | 1 << 8, 1 << 8 | 1,
    322     Instruction::RETURN_VOID);
    323 
    324   ArenaPool pool;
    325   ArenaAllocator allocator(&pool);
    326   HGraph* graph = CreateCFG(&allocator, data);
    327   std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    328       X86InstructionSetFeatures::FromCppDefines());
    329   x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    330   SsaLivenessAnalysis liveness(graph, &codegen);
    331   liveness.Analyze();
    332 
    333   HXor* first_xor = graph->GetBlocks()[1]->GetFirstInstruction()->AsXor();
    334   HXor* last_xor = graph->GetBlocks()[1]->GetLastInstruction()->GetPrevious()->AsXor();
    335   ASSERT_EQ(last_xor->InputAt(0), first_xor);
    336   LiveInterval* interval = first_xor->GetLiveInterval();
    337   ASSERT_EQ(interval->GetEnd(), last_xor->GetLifetimePosition());
    338   ASSERT_TRUE(interval->GetNextSibling() == nullptr);
    339 
    340   // We need a register for the output of the instruction.
    341   ASSERT_EQ(interval->FirstRegisterUse(), first_xor->GetLifetimePosition());
    342 
    343   // Split at the next instruction.
    344   interval = interval->SplitAt(first_xor->GetLifetimePosition() + 2);
    345   // The user of the split is the last add.
    346   ASSERT_EQ(interval->FirstRegisterUse(), last_xor->GetLifetimePosition());
    347 
    348   // Split before the last add.
    349   LiveInterval* new_interval = interval->SplitAt(last_xor->GetLifetimePosition() - 1);
    350   // Ensure the current interval has no register use...
    351   ASSERT_EQ(interval->FirstRegisterUse(), kNoLifetime);
    352   // And the new interval has it for the last add.
    353   ASSERT_EQ(new_interval->FirstRegisterUse(), last_xor->GetLifetimePosition());
    354 }
    355 
    356 TEST_F(RegisterAllocatorTest, DeadPhi) {
    357   /* Test for a dead loop phi taking as back-edge input a phi that also has
    358    * this loop phi as input. Walking backwards in SsaDeadPhiElimination
    359    * does not solve the problem because the loop phi will be visited last.
    360    *
    361    * Test the following snippet:
    362    *  int a = 0
    363    *  do {
    364    *    if (true) {
    365    *      a = 2;
    366    *    }
    367    *  } while (true);
    368    */
    369 
    370   const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
    371     Instruction::CONST_4 | 0 | 0,
    372     Instruction::CONST_4 | 1 << 8 | 0,
    373     Instruction::IF_NE | 1 << 8 | 1 << 12, 3,
    374     Instruction::CONST_4 | 2 << 12 | 0 << 8,
    375     Instruction::GOTO | 0xFD00,
    376     Instruction::RETURN_VOID);
    377 
    378   ArenaPool pool;
    379   ArenaAllocator allocator(&pool);
    380   HGraph* graph = CreateCFG(&allocator, data);
    381   SsaDeadPhiElimination(graph).Run();
    382   std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    383       X86InstructionSetFeatures::FromCppDefines());
    384   x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    385   SsaLivenessAnalysis liveness(graph, &codegen);
    386   liveness.Analyze();
    387   RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    388   register_allocator.AllocateRegisters();
    389   ASSERT_TRUE(register_allocator.Validate(false));
    390 }
    391 
    392 /**
    393  * Test that the TryAllocateFreeReg method works in the presence of inactive intervals
    394  * that share the same register. It should split the interval it is currently
    395  * allocating for at the minimum lifetime position between the two inactive intervals.
    396  */
    397 TEST_F(RegisterAllocatorTest, FreeUntil) {
    398   const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
    399     Instruction::CONST_4 | 0 | 0,
    400     Instruction::RETURN);
    401 
    402   ArenaPool pool;
    403   ArenaAllocator allocator(&pool);
    404   HGraph* graph = CreateCFG(&allocator, data);
    405   SsaDeadPhiElimination(graph).Run();
    406   std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    407       X86InstructionSetFeatures::FromCppDefines());
    408   x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    409   SsaLivenessAnalysis liveness(graph, &codegen);
    410   liveness.Analyze();
    411   RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    412 
    413   // Add an artifical range to cover the temps that will be put in the unhandled list.
    414   LiveInterval* unhandled = graph->GetEntryBlock()->GetFirstInstruction()->GetLiveInterval();
    415   unhandled->AddLoopRange(0, 60);
    416 
    417   // Populate the instructions in the liveness object, to please the register allocator.
    418   for (size_t i = 0; i < 60; ++i) {
    419     liveness.instructions_from_lifetime_position_.push_back(
    420         graph->GetEntryBlock()->GetFirstInstruction());
    421   }
    422 
    423   // For SSA value intervals, only an interval resulted from a split may intersect
    424   // with inactive intervals.
    425   unhandled = register_allocator.Split(unhandled, 5);
    426 
    427   // Add three temps holding the same register, and starting at different positions.
    428   // Put the one that should be picked in the middle of the inactive list to ensure
    429   // we do not depend on an order.
    430   LiveInterval* interval = LiveInterval::MakeFixedInterval(&allocator, 0, Primitive::kPrimInt);
    431   interval->AddRange(40, 50);
    432   register_allocator.inactive_.push_back(interval);
    433 
    434   interval = LiveInterval::MakeFixedInterval(&allocator, 0, Primitive::kPrimInt);
    435   interval->AddRange(20, 30);
    436   register_allocator.inactive_.push_back(interval);
    437 
    438   interval = LiveInterval::MakeFixedInterval(&allocator, 0, Primitive::kPrimInt);
    439   interval->AddRange(60, 70);
    440   register_allocator.inactive_.push_back(interval);
    441 
    442   register_allocator.number_of_registers_ = 1;
    443   register_allocator.registers_array_ = allocator.AllocArray<size_t>(1);
    444   register_allocator.processing_core_registers_ = true;
    445   register_allocator.unhandled_ = &register_allocator.unhandled_core_intervals_;
    446 
    447   ASSERT_TRUE(register_allocator.TryAllocateFreeReg(unhandled));
    448 
    449   // Check that we have split the interval.
    450   ASSERT_EQ(1u, register_allocator.unhandled_->size());
    451   // Check that we know need to find a new register where the next interval
    452   // that uses the register starts.
    453   ASSERT_EQ(20u, register_allocator.unhandled_->front()->GetStart());
    454 }
    455 
    456 static HGraph* BuildIfElseWithPhi(ArenaAllocator* allocator,
    457                                   HPhi** phi,
    458                                   HInstruction** input1,
    459                                   HInstruction** input2) {
    460   HGraph* graph = CreateGraph(allocator);
    461   HBasicBlock* entry = new (allocator) HBasicBlock(graph);
    462   ScopedNullHandle<mirror::DexCache> dex_cache;
    463   graph->AddBlock(entry);
    464   graph->SetEntryBlock(entry);
    465   HInstruction* parameter = new (allocator) HParameterValue(
    466       graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
    467   entry->AddInstruction(parameter);
    468 
    469   HBasicBlock* block = new (allocator) HBasicBlock(graph);
    470   graph->AddBlock(block);
    471   entry->AddSuccessor(block);
    472 
    473   HInstruction* test = new (allocator) HInstanceFieldGet(parameter,
    474                                                          Primitive::kPrimBoolean,
    475                                                          MemberOffset(22),
    476                                                          false,
    477                                                          kUnknownFieldIndex,
    478                                                          kUnknownClassDefIndex,
    479                                                          graph->GetDexFile(),
    480                                                          dex_cache,
    481                                                          0);
    482   block->AddInstruction(test);
    483   block->AddInstruction(new (allocator) HIf(test));
    484   HBasicBlock* then = new (allocator) HBasicBlock(graph);
    485   HBasicBlock* else_ = new (allocator) HBasicBlock(graph);
    486   HBasicBlock* join = new (allocator) HBasicBlock(graph);
    487   graph->AddBlock(then);
    488   graph->AddBlock(else_);
    489   graph->AddBlock(join);
    490 
    491   block->AddSuccessor(then);
    492   block->AddSuccessor(else_);
    493   then->AddSuccessor(join);
    494   else_->AddSuccessor(join);
    495   then->AddInstruction(new (allocator) HGoto());
    496   else_->AddInstruction(new (allocator) HGoto());
    497 
    498   *phi = new (allocator) HPhi(allocator, 0, 0, Primitive::kPrimInt);
    499   join->AddPhi(*phi);
    500   *input1 = new (allocator) HInstanceFieldGet(parameter,
    501                                               Primitive::kPrimInt,
    502                                               MemberOffset(42),
    503                                               false,
    504                                               kUnknownFieldIndex,
    505                                               kUnknownClassDefIndex,
    506                                               graph->GetDexFile(),
    507                                               dex_cache,
    508                                               0);
    509 *input2 = new (allocator) HInstanceFieldGet(parameter,
    510                                             Primitive::kPrimInt,
    511                                             MemberOffset(42),
    512                                             false,
    513                                             kUnknownFieldIndex,
    514                                             kUnknownClassDefIndex,
    515                                             graph->GetDexFile(),
    516                                             dex_cache,
    517                                             0);
    518   then->AddInstruction(*input1);
    519   else_->AddInstruction(*input2);
    520   join->AddInstruction(new (allocator) HExit());
    521   (*phi)->AddInput(*input1);
    522   (*phi)->AddInput(*input2);
    523 
    524   graph->BuildDominatorTree();
    525   graph->AnalyzeLoops();
    526   return graph;
    527 }
    528 
    529 TEST_F(RegisterAllocatorTest, PhiHint) {
    530   ArenaPool pool;
    531   ArenaAllocator allocator(&pool);
    532   HPhi *phi;
    533   HInstruction *input1, *input2;
    534 
    535   {
    536     HGraph* graph = BuildIfElseWithPhi(&allocator, &phi, &input1, &input2);
    537     std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    538         X86InstructionSetFeatures::FromCppDefines());
    539     x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    540     SsaLivenessAnalysis liveness(graph, &codegen);
    541     liveness.Analyze();
    542 
    543     // Check that the register allocator is deterministic.
    544     RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    545     register_allocator.AllocateRegisters();
    546 
    547     ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 0);
    548     ASSERT_EQ(input2->GetLiveInterval()->GetRegister(), 0);
    549     ASSERT_EQ(phi->GetLiveInterval()->GetRegister(), 0);
    550   }
    551 
    552   {
    553     HGraph* graph = BuildIfElseWithPhi(&allocator, &phi, &input1, &input2);
    554     std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    555         X86InstructionSetFeatures::FromCppDefines());
    556     x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    557     SsaLivenessAnalysis liveness(graph, &codegen);
    558     liveness.Analyze();
    559 
    560     // Set the phi to a specific register, and check that the inputs get allocated
    561     // the same register.
    562     phi->GetLocations()->UpdateOut(Location::RegisterLocation(2));
    563     RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    564     register_allocator.AllocateRegisters();
    565 
    566     ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 2);
    567     ASSERT_EQ(input2->GetLiveInterval()->GetRegister(), 2);
    568     ASSERT_EQ(phi->GetLiveInterval()->GetRegister(), 2);
    569   }
    570 
    571   {
    572     HGraph* graph = BuildIfElseWithPhi(&allocator, &phi, &input1, &input2);
    573     std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    574         X86InstructionSetFeatures::FromCppDefines());
    575     x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    576     SsaLivenessAnalysis liveness(graph, &codegen);
    577     liveness.Analyze();
    578 
    579     // Set input1 to a specific register, and check that the phi and other input get allocated
    580     // the same register.
    581     input1->GetLocations()->UpdateOut(Location::RegisterLocation(2));
    582     RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    583     register_allocator.AllocateRegisters();
    584 
    585     ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 2);
    586     ASSERT_EQ(input2->GetLiveInterval()->GetRegister(), 2);
    587     ASSERT_EQ(phi->GetLiveInterval()->GetRegister(), 2);
    588   }
    589 
    590   {
    591     HGraph* graph = BuildIfElseWithPhi(&allocator, &phi, &input1, &input2);
    592     std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    593         X86InstructionSetFeatures::FromCppDefines());
    594     x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    595     SsaLivenessAnalysis liveness(graph, &codegen);
    596     liveness.Analyze();
    597 
    598     // Set input2 to a specific register, and check that the phi and other input get allocated
    599     // the same register.
    600     input2->GetLocations()->UpdateOut(Location::RegisterLocation(2));
    601     RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    602     register_allocator.AllocateRegisters();
    603 
    604     ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 2);
    605     ASSERT_EQ(input2->GetLiveInterval()->GetRegister(), 2);
    606     ASSERT_EQ(phi->GetLiveInterval()->GetRegister(), 2);
    607   }
    608 }
    609 
    610 static HGraph* BuildFieldReturn(ArenaAllocator* allocator,
    611                                 HInstruction** field,
    612                                 HInstruction** ret) {
    613   HGraph* graph = CreateGraph(allocator);
    614   ScopedNullHandle<mirror::DexCache> dex_cache;
    615   HBasicBlock* entry = new (allocator) HBasicBlock(graph);
    616   graph->AddBlock(entry);
    617   graph->SetEntryBlock(entry);
    618   HInstruction* parameter = new (allocator) HParameterValue(
    619       graph->GetDexFile(), 0, 0, Primitive::kPrimNot);
    620   entry->AddInstruction(parameter);
    621 
    622   HBasicBlock* block = new (allocator) HBasicBlock(graph);
    623   graph->AddBlock(block);
    624   entry->AddSuccessor(block);
    625 
    626   *field = new (allocator) HInstanceFieldGet(parameter,
    627                                              Primitive::kPrimInt,
    628                                              MemberOffset(42),
    629                                              false,
    630                                              kUnknownFieldIndex,
    631                                              kUnknownClassDefIndex,
    632                                              graph->GetDexFile(),
    633                                              dex_cache,
    634                                              0);
    635   block->AddInstruction(*field);
    636   *ret = new (allocator) HReturn(*field);
    637   block->AddInstruction(*ret);
    638 
    639   HBasicBlock* exit = new (allocator) HBasicBlock(graph);
    640   graph->AddBlock(exit);
    641   block->AddSuccessor(exit);
    642   exit->AddInstruction(new (allocator) HExit());
    643 
    644   graph->BuildDominatorTree();
    645   return graph;
    646 }
    647 
    648 TEST_F(RegisterAllocatorTest, ExpectedInRegisterHint) {
    649   ArenaPool pool;
    650   ArenaAllocator allocator(&pool);
    651   HInstruction *field, *ret;
    652 
    653   {
    654     HGraph* graph = BuildFieldReturn(&allocator, &field, &ret);
    655     std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    656         X86InstructionSetFeatures::FromCppDefines());
    657     x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    658     SsaLivenessAnalysis liveness(graph, &codegen);
    659     liveness.Analyze();
    660 
    661     RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    662     register_allocator.AllocateRegisters();
    663 
    664     // Sanity check that in normal conditions, the register should be hinted to 0 (EAX).
    665     ASSERT_EQ(field->GetLiveInterval()->GetRegister(), 0);
    666   }
    667 
    668   {
    669     HGraph* graph = BuildFieldReturn(&allocator, &field, &ret);
    670     std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    671         X86InstructionSetFeatures::FromCppDefines());
    672     x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    673     SsaLivenessAnalysis liveness(graph, &codegen);
    674     liveness.Analyze();
    675 
    676     // Check that the field gets put in the register expected by its use.
    677     // Don't use SetInAt because we are overriding an already allocated location.
    678     ret->GetLocations()->inputs_[0] = Location::RegisterLocation(2);
    679 
    680     RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    681     register_allocator.AllocateRegisters();
    682 
    683     ASSERT_EQ(field->GetLiveInterval()->GetRegister(), 2);
    684   }
    685 }
    686 
    687 static HGraph* BuildTwoSubs(ArenaAllocator* allocator,
    688                             HInstruction** first_sub,
    689                             HInstruction** second_sub) {
    690   HGraph* graph = CreateGraph(allocator);
    691   HBasicBlock* entry = new (allocator) HBasicBlock(graph);
    692   graph->AddBlock(entry);
    693   graph->SetEntryBlock(entry);
    694   HInstruction* parameter = new (allocator) HParameterValue(
    695       graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
    696   entry->AddInstruction(parameter);
    697 
    698   HInstruction* constant1 = graph->GetIntConstant(1);
    699   HInstruction* constant2 = graph->GetIntConstant(2);
    700 
    701   HBasicBlock* block = new (allocator) HBasicBlock(graph);
    702   graph->AddBlock(block);
    703   entry->AddSuccessor(block);
    704 
    705   *first_sub = new (allocator) HSub(Primitive::kPrimInt, parameter, constant1);
    706   block->AddInstruction(*first_sub);
    707   *second_sub = new (allocator) HSub(Primitive::kPrimInt, *first_sub, constant2);
    708   block->AddInstruction(*second_sub);
    709 
    710   block->AddInstruction(new (allocator) HExit());
    711 
    712   graph->BuildDominatorTree();
    713   return graph;
    714 }
    715 
    716 TEST_F(RegisterAllocatorTest, SameAsFirstInputHint) {
    717   ArenaPool pool;
    718   ArenaAllocator allocator(&pool);
    719   HInstruction *first_sub, *second_sub;
    720 
    721   {
    722     HGraph* graph = BuildTwoSubs(&allocator, &first_sub, &second_sub);
    723     std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    724         X86InstructionSetFeatures::FromCppDefines());
    725     x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    726     SsaLivenessAnalysis liveness(graph, &codegen);
    727     liveness.Analyze();
    728 
    729     RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    730     register_allocator.AllocateRegisters();
    731 
    732     // Sanity check that in normal conditions, the registers are the same.
    733     ASSERT_EQ(first_sub->GetLiveInterval()->GetRegister(), 1);
    734     ASSERT_EQ(second_sub->GetLiveInterval()->GetRegister(), 1);
    735   }
    736 
    737   {
    738     HGraph* graph = BuildTwoSubs(&allocator, &first_sub, &second_sub);
    739     std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    740         X86InstructionSetFeatures::FromCppDefines());
    741     x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    742     SsaLivenessAnalysis liveness(graph, &codegen);
    743     liveness.Analyze();
    744 
    745     // check that both adds get the same register.
    746     // Don't use UpdateOutput because output is already allocated.
    747     first_sub->InputAt(0)->GetLocations()->output_ = Location::RegisterLocation(2);
    748     ASSERT_EQ(first_sub->GetLocations()->Out().GetPolicy(), Location::kSameAsFirstInput);
    749     ASSERT_EQ(second_sub->GetLocations()->Out().GetPolicy(), Location::kSameAsFirstInput);
    750 
    751     RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    752     register_allocator.AllocateRegisters();
    753 
    754     ASSERT_EQ(first_sub->GetLiveInterval()->GetRegister(), 2);
    755     ASSERT_EQ(second_sub->GetLiveInterval()->GetRegister(), 2);
    756   }
    757 }
    758 
    759 static HGraph* BuildDiv(ArenaAllocator* allocator,
    760                         HInstruction** div) {
    761   HGraph* graph = CreateGraph(allocator);
    762   HBasicBlock* entry = new (allocator) HBasicBlock(graph);
    763   graph->AddBlock(entry);
    764   graph->SetEntryBlock(entry);
    765   HInstruction* first = new (allocator) HParameterValue(
    766       graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
    767   HInstruction* second = new (allocator) HParameterValue(
    768       graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
    769   entry->AddInstruction(first);
    770   entry->AddInstruction(second);
    771 
    772   HBasicBlock* block = new (allocator) HBasicBlock(graph);
    773   graph->AddBlock(block);
    774   entry->AddSuccessor(block);
    775 
    776   *div = new (allocator) HDiv(Primitive::kPrimInt, first, second, 0);  // don't care about dex_pc.
    777   block->AddInstruction(*div);
    778 
    779   block->AddInstruction(new (allocator) HExit());
    780 
    781   graph->BuildDominatorTree();
    782   return graph;
    783 }
    784 
    785 TEST_F(RegisterAllocatorTest, ExpectedExactInRegisterAndSameOutputHint) {
    786   ArenaPool pool;
    787   ArenaAllocator allocator(&pool);
    788   HInstruction *div;
    789 
    790   {
    791     HGraph* graph = BuildDiv(&allocator, &div);
    792     std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    793         X86InstructionSetFeatures::FromCppDefines());
    794     x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    795     SsaLivenessAnalysis liveness(graph, &codegen);
    796     liveness.Analyze();
    797 
    798     RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    799     register_allocator.AllocateRegisters();
    800 
    801     // div on x86 requires its first input in eax and the output be the same as the first input.
    802     ASSERT_EQ(div->GetLiveInterval()->GetRegister(), 0);
    803   }
    804 }
    805 
    806 // Test a bug in the register allocator, where allocating a blocked
    807 // register would lead to spilling an inactive interval at the wrong
    808 // position.
    809 TEST_F(RegisterAllocatorTest, SpillInactive) {
    810   ArenaPool pool;
    811 
    812   // Create a synthesized graph to please the register_allocator and
    813   // ssa_liveness_analysis code.
    814   ArenaAllocator allocator(&pool);
    815   HGraph* graph = CreateGraph(&allocator);
    816   HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
    817   graph->AddBlock(entry);
    818   graph->SetEntryBlock(entry);
    819   HInstruction* one = new (&allocator) HParameterValue(
    820       graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
    821   HInstruction* two = new (&allocator) HParameterValue(
    822       graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
    823   HInstruction* three = new (&allocator) HParameterValue(
    824       graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
    825   HInstruction* four = new (&allocator) HParameterValue(
    826       graph->GetDexFile(), 0, 0, Primitive::kPrimInt);
    827   entry->AddInstruction(one);
    828   entry->AddInstruction(two);
    829   entry->AddInstruction(three);
    830   entry->AddInstruction(four);
    831 
    832   HBasicBlock* block = new (&allocator) HBasicBlock(graph);
    833   graph->AddBlock(block);
    834   entry->AddSuccessor(block);
    835   block->AddInstruction(new (&allocator) HExit());
    836 
    837   // We create a synthesized user requesting a register, to avoid just spilling the
    838   // intervals.
    839   HPhi* user = new (&allocator) HPhi(&allocator, 0, 1, Primitive::kPrimInt);
    840   user->AddInput(one);
    841   user->SetBlock(block);
    842   LocationSummary* locations = new (&allocator) LocationSummary(user, LocationSummary::kNoCall);
    843   locations->SetInAt(0, Location::RequiresRegister());
    844   static constexpr size_t phi_ranges[][2] = {{20, 30}};
    845   BuildInterval(phi_ranges, arraysize(phi_ranges), &allocator, -1, user);
    846 
    847   // Create an interval with lifetime holes.
    848   static constexpr size_t ranges1[][2] = {{0, 2}, {4, 6}, {8, 10}};
    849   LiveInterval* first = BuildInterval(ranges1, arraysize(ranges1), &allocator, -1, one);
    850   first->first_use_ = new(&allocator) UsePosition(user, 0, false, 8, first->first_use_);
    851   first->first_use_ = new(&allocator) UsePosition(user, 0, false, 7, first->first_use_);
    852   first->first_use_ = new(&allocator) UsePosition(user, 0, false, 6, first->first_use_);
    853 
    854   locations = new (&allocator) LocationSummary(first->GetDefinedBy(), LocationSummary::kNoCall);
    855   locations->SetOut(Location::RequiresRegister());
    856   first = first->SplitAt(1);
    857 
    858   // Create an interval that conflicts with the next interval, to force the next
    859   // interval to call `AllocateBlockedReg`.
    860   static constexpr size_t ranges2[][2] = {{2, 4}};
    861   LiveInterval* second = BuildInterval(ranges2, arraysize(ranges2), &allocator, -1, two);
    862   locations = new (&allocator) LocationSummary(second->GetDefinedBy(), LocationSummary::kNoCall);
    863   locations->SetOut(Location::RequiresRegister());
    864 
    865   // Create an interval that will lead to splitting the first interval. The bug occured
    866   // by splitting at a wrong position, in this case at the next intersection between
    867   // this interval and the first interval. We would have then put the interval with ranges
    868   // "[0, 2(, [4, 6(" in the list of handled intervals, even though we haven't processed intervals
    869   // before lifetime position 6 yet.
    870   static constexpr size_t ranges3[][2] = {{2, 4}, {8, 10}};
    871   LiveInterval* third = BuildInterval(ranges3, arraysize(ranges3), &allocator, -1, three);
    872   third->first_use_ = new(&allocator) UsePosition(user, 0, false, 8, third->first_use_);
    873   third->first_use_ = new(&allocator) UsePosition(user, 0, false, 4, third->first_use_);
    874   third->first_use_ = new(&allocator) UsePosition(user, 0, false, 3, third->first_use_);
    875   locations = new (&allocator) LocationSummary(third->GetDefinedBy(), LocationSummary::kNoCall);
    876   locations->SetOut(Location::RequiresRegister());
    877   third = third->SplitAt(3);
    878 
    879   // Because the first part of the split interval was considered handled, this interval
    880   // was free to allocate the same register, even though it conflicts with it.
    881   static constexpr size_t ranges4[][2] = {{4, 6}};
    882   LiveInterval* fourth = BuildInterval(ranges4, arraysize(ranges4), &allocator, -1, four);
    883   locations = new (&allocator) LocationSummary(fourth->GetDefinedBy(), LocationSummary::kNoCall);
    884   locations->SetOut(Location::RequiresRegister());
    885 
    886   std::unique_ptr<const X86InstructionSetFeatures> features_x86(
    887       X86InstructionSetFeatures::FromCppDefines());
    888   x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
    889   SsaLivenessAnalysis liveness(graph, &codegen);
    890   // Populate the instructions in the liveness object, to please the register allocator.
    891   for (size_t i = 0; i < 32; ++i) {
    892     liveness.instructions_from_lifetime_position_.push_back(user);
    893   }
    894 
    895   RegisterAllocator register_allocator(&allocator, &codegen, liveness);
    896   register_allocator.unhandled_core_intervals_.push_back(fourth);
    897   register_allocator.unhandled_core_intervals_.push_back(third);
    898   register_allocator.unhandled_core_intervals_.push_back(second);
    899   register_allocator.unhandled_core_intervals_.push_back(first);
    900 
    901   // Set just one register available to make all intervals compete for the same.
    902   register_allocator.number_of_registers_ = 1;
    903   register_allocator.registers_array_ = allocator.AllocArray<size_t>(1);
    904   register_allocator.processing_core_registers_ = true;
    905   register_allocator.unhandled_ = &register_allocator.unhandled_core_intervals_;
    906   register_allocator.LinearScan();
    907 
    908   // Test that there is no conflicts between intervals.
    909   ArenaVector<LiveInterval*> intervals(allocator.Adapter());
    910   intervals.push_back(first);
    911   intervals.push_back(second);
    912   intervals.push_back(third);
    913   intervals.push_back(fourth);
    914   ASSERT_TRUE(RegisterAllocator::ValidateIntervals(
    915       intervals, 0, 0, codegen, &allocator, true, false));
    916 }
    917 
    918 }  // namespace art
    919