/*
 * Copyright (C) 2014 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 "register_allocator.h"

#include "arch/x86/instruction_set_features_x86.h"
#include "base/arena_allocator.h"
#include "builder.h"
#include "code_generator.h"
#include "code_generator_x86.h"
#include "dex/dex_file.h"
#include "dex/dex_file_types.h"
#include "dex/dex_instruction.h"
#include "driver/compiler_options.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "register_allocator_linear_scan.h"
#include "ssa_liveness_analysis.h"
#include "ssa_phi_elimination.h"

namespace art {

using Strategy = RegisterAllocator::Strategy;

// Note: the register allocator tests rely on the fact that constants have live
// intervals and registers get allocated to them.

class RegisterAllocatorTest : public OptimizingUnitTest {
 protected:
  void SetUp() override {
    // This test is using the x86 ISA.
    OverrideInstructionSetFeatures(InstructionSet::kX86, "default");
    OptimizingUnitTest::SetUp();
  }

  // These functions need to access private variables of LocationSummary, so we declare it
  // as a member of RegisterAllocatorTest, which we make a friend class.
  void SameAsFirstInputHint(Strategy strategy);
  void ExpectedInRegisterHint(Strategy strategy);

  // Helper functions that make use of the OptimizingUnitTest's members.
  bool Check(const std::vector<uint16_t>& data, Strategy strategy);
  void CFG1(Strategy strategy);
  void Loop1(Strategy strategy);
  void Loop2(Strategy strategy);
  void Loop3(Strategy strategy);
  void DeadPhi(Strategy strategy);
  HGraph* BuildIfElseWithPhi(HPhi** phi, HInstruction** input1, HInstruction** input2);
  void PhiHint(Strategy strategy);
  HGraph* BuildFieldReturn(HInstruction** field, HInstruction** ret);
  HGraph* BuildTwoSubs(HInstruction** first_sub, HInstruction** second_sub);
  HGraph* BuildDiv(HInstruction** div);
  void ExpectedExactInRegisterAndSameOutputHint(Strategy strategy);

  bool ValidateIntervals(const ScopedArenaVector<LiveInterval*>& intervals,
                         const CodeGenerator& codegen) {
    return RegisterAllocator::ValidateIntervals(ArrayRef<LiveInterval* const>(intervals),
                                                /* number_of_spill_slots= */ 0u,
                                                /* number_of_out_slots= */ 0u,
                                                codegen,
                                                /* processing_core_registers= */ true,
                                                /* log_fatal_on_failure= */ false);
  }
};

// This macro should include all register allocation strategies that should be tested.
#define TEST_ALL_STRATEGIES(test_name)\
TEST_F(RegisterAllocatorTest, test_name##_LinearScan) {\
  test_name(Strategy::kRegisterAllocatorLinearScan);\
}\
TEST_F(RegisterAllocatorTest, test_name##_GraphColor) {\
  test_name(Strategy::kRegisterAllocatorGraphColor);\
}

bool RegisterAllocatorTest::Check(const std::vector<uint16_t>& data, Strategy strategy) {
  HGraph* graph = CreateCFG(data);
  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
  liveness.Analyze();
  std::unique_ptr<RegisterAllocator> register_allocator =
      RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
  register_allocator->AllocateRegisters();
  return register_allocator->Validate(false);
}

/**
 * Unit testing of RegisterAllocator::ValidateIntervals. Register allocator
 * tests are based on this validation method.
 */
TEST_F(RegisterAllocatorTest, ValidateIntervals) {
  HGraph* graph = CreateGraph();
  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
  ScopedArenaVector<LiveInterval*> intervals(GetScopedAllocator()->Adapter());

  // Test with two intervals of the same range.
  {
    static constexpr size_t ranges[][2] = {{0, 42}};
    intervals.push_back(BuildInterval(ranges, arraysize(ranges), GetScopedAllocator(), 0));
    intervals.push_back(BuildInterval(ranges, arraysize(ranges), GetScopedAllocator(), 1));
    ASSERT_TRUE(ValidateIntervals(intervals, codegen));

    intervals[1]->SetRegister(0);
    ASSERT_FALSE(ValidateIntervals(intervals, codegen));
    intervals.clear();
  }

  // Test with two non-intersecting intervals.
  {
    static constexpr size_t ranges1[][2] = {{0, 42}};
    intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), 0));
    static constexpr size_t ranges2[][2] = {{42, 43}};
    intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), 1));
    ASSERT_TRUE(ValidateIntervals(intervals, codegen));

    intervals[1]->SetRegister(0);
    ASSERT_TRUE(ValidateIntervals(intervals, codegen));
    intervals.clear();
  }

  // Test with two non-intersecting intervals, with one with a lifetime hole.
  {
    static constexpr size_t ranges1[][2] = {{0, 42}, {45, 48}};
    intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), 0));
    static constexpr size_t ranges2[][2] = {{42, 43}};
    intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), 1));
    ASSERT_TRUE(ValidateIntervals(intervals, codegen));

    intervals[1]->SetRegister(0);
    ASSERT_TRUE(ValidateIntervals(intervals, codegen));
    intervals.clear();
  }

  // Test with intersecting intervals.
  {
    static constexpr size_t ranges1[][2] = {{0, 42}, {44, 48}};
    intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), 0));
    static constexpr size_t ranges2[][2] = {{42, 47}};
    intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), 1));
    ASSERT_TRUE(ValidateIntervals(intervals, codegen));

    intervals[1]->SetRegister(0);
    ASSERT_FALSE(ValidateIntervals(intervals, codegen));
    intervals.clear();
  }

  // Test with siblings.
  {
    static constexpr size_t ranges1[][2] = {{0, 42}, {44, 48}};
    intervals.push_back(BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), 0));
    intervals[0]->SplitAt(43);
    static constexpr size_t ranges2[][2] = {{42, 47}};
    intervals.push_back(BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), 1));
    ASSERT_TRUE(ValidateIntervals(intervals, codegen));

    intervals[1]->SetRegister(0);
    // Sibling of the first interval has no register allocated to it.
    ASSERT_TRUE(ValidateIntervals(intervals, codegen));

    intervals[0]->GetNextSibling()->SetRegister(0);
    ASSERT_FALSE(ValidateIntervals(intervals, codegen));
  }
}

void RegisterAllocatorTest::CFG1(Strategy strategy) {
  /*
   * Test the following snippet:
   *  return 0;
   *
   * Which becomes the following graph:
   *       constant0
   *       goto
   *        |
   *       return
   *        |
   *       exit
   */
  const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::RETURN);

  ASSERT_TRUE(Check(data, strategy));
}

TEST_ALL_STRATEGIES(CFG1);

void RegisterAllocatorTest::Loop1(Strategy strategy) {
  /*
   * Test the following snippet:
   *  int a = 0;
   *  while (a == a) {
   *    a = 4;
   *  }
   *  return 5;
   *
   * Which becomes the following graph:
   *       constant0
   *       constant4
   *       constant5
   *       goto
   *        |
   *       goto
   *        |
   *       phi
   *       equal
   *       if +++++
   *        |       \ +
   *        |     goto
   *        |
   *       return
   *        |
   *       exit
   */

  const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::IF_EQ, 4,
    Instruction::CONST_4 | 4 << 12 | 0,
    Instruction::GOTO | 0xFD00,
    Instruction::CONST_4 | 5 << 12 | 1 << 8,
    Instruction::RETURN | 1 << 8);

  ASSERT_TRUE(Check(data, strategy));
}

TEST_ALL_STRATEGIES(Loop1);

void RegisterAllocatorTest::Loop2(Strategy strategy) {
  /*
   * Test the following snippet:
   *  int a = 0;
   *  while (a == 8) {
   *    a = 4 + 5;
   *  }
   *  return 6 + 7;
   *
   * Which becomes the following graph:
   *       constant0
   *       constant4
   *       constant5
   *       constant6
   *       constant7
   *       constant8
   *       goto
   *        |
   *       goto
   *        |
   *       phi
   *       equal
   *       if +++++
   *        |       \ +
   *        |      4 + 5
   *        |      goto
   *        |
   *       6 + 7
   *       return
   *        |
   *       exit
   */

  const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::CONST_4 | 8 << 12 | 1 << 8,
    Instruction::IF_EQ | 1 << 8, 7,
    Instruction::CONST_4 | 4 << 12 | 0 << 8,
    Instruction::CONST_4 | 5 << 12 | 1 << 8,
    Instruction::ADD_INT, 1 << 8 | 0,
    Instruction::GOTO | 0xFA00,
    Instruction::CONST_4 | 6 << 12 | 1 << 8,
    Instruction::CONST_4 | 7 << 12 | 1 << 8,
    Instruction::ADD_INT, 1 << 8 | 0,
    Instruction::RETURN | 1 << 8);

  ASSERT_TRUE(Check(data, strategy));
}

TEST_ALL_STRATEGIES(Loop2);

void RegisterAllocatorTest::Loop3(Strategy strategy) {
  /*
   * Test the following snippet:
   *  int a = 0
   *  do {
   *    b = a;
   *    a++;
   *  } while (a != 5)
   *  return b;
   *
   * Which becomes the following graph:
   *       constant0
   *       constant1
   *       constant5
   *       goto
   *        |
   *       goto
   *        |++++++++++++
   *       phi          +
   *       a++          +
   *       equals       +
   *       if           +
   *        |++++++++++++
   *       return
   *        |
   *       exit
   */

  const std::vector<uint16_t> data = THREE_REGISTERS_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::ADD_INT_LIT8 | 1 << 8, 1 << 8,
    Instruction::CONST_4 | 5 << 12 | 2 << 8,
    Instruction::IF_NE | 1 << 8 | 2 << 12, 3,
    Instruction::RETURN | 0 << 8,
    Instruction::MOVE | 1 << 12 | 0 << 8,
    Instruction::GOTO | 0xF900);

  HGraph* graph = CreateCFG(data);
  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
  liveness.Analyze();
  std::unique_ptr<RegisterAllocator> register_allocator =
      RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
  register_allocator->AllocateRegisters();
  ASSERT_TRUE(register_allocator->Validate(false));

  HBasicBlock* loop_header = graph->GetBlocks()[2];
  HPhi* phi = loop_header->GetFirstPhi()->AsPhi();

  LiveInterval* phi_interval = phi->GetLiveInterval();
  LiveInterval* loop_update = phi->InputAt(1)->GetLiveInterval();
  ASSERT_TRUE(phi_interval->HasRegister());
  ASSERT_TRUE(loop_update->HasRegister());
  ASSERT_NE(phi_interval->GetRegister(), loop_update->GetRegister());

  HBasicBlock* return_block = graph->GetBlocks()[3];
  HReturn* ret = return_block->GetLastInstruction()->AsReturn();
  ASSERT_EQ(phi_interval->GetRegister(), ret->InputAt(0)->GetLiveInterval()->GetRegister());
}

TEST_ALL_STRATEGIES(Loop3);

TEST_F(RegisterAllocatorTest, FirstRegisterUse) {
  const std::vector<uint16_t> data = THREE_REGISTERS_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::XOR_INT_LIT8 | 1 << 8, 1 << 8,
    Instruction::XOR_INT_LIT8 | 0 << 8, 1 << 8,
    Instruction::XOR_INT_LIT8 | 1 << 8, 1 << 8 | 1,
    Instruction::RETURN_VOID);

  HGraph* graph = CreateCFG(data);
  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
  liveness.Analyze();

  HXor* first_xor = graph->GetBlocks()[1]->GetFirstInstruction()->AsXor();
  HXor* last_xor = graph->GetBlocks()[1]->GetLastInstruction()->GetPrevious()->AsXor();
  ASSERT_EQ(last_xor->InputAt(0), first_xor);
  LiveInterval* interval = first_xor->GetLiveInterval();
  ASSERT_EQ(interval->GetEnd(), last_xor->GetLifetimePosition());
  ASSERT_TRUE(interval->GetNextSibling() == nullptr);

  // We need a register for the output of the instruction.
  ASSERT_EQ(interval->FirstRegisterUse(), first_xor->GetLifetimePosition());

  // Split at the next instruction.
  interval = interval->SplitAt(first_xor->GetLifetimePosition() + 2);
  // The user of the split is the last add.
  ASSERT_EQ(interval->FirstRegisterUse(), last_xor->GetLifetimePosition());

  // Split before the last add.
  LiveInterval* new_interval = interval->SplitAt(last_xor->GetLifetimePosition() - 1);
  // Ensure the current interval has no register use...
  ASSERT_EQ(interval->FirstRegisterUse(), kNoLifetime);
  // And the new interval has it for the last add.
  ASSERT_EQ(new_interval->FirstRegisterUse(), last_xor->GetLifetimePosition());
}

void RegisterAllocatorTest::DeadPhi(Strategy strategy) {
  /* Test for a dead loop phi taking as back-edge input a phi that also has
   * this loop phi as input. Walking backwards in SsaDeadPhiElimination
   * does not solve the problem because the loop phi will be visited last.
   *
   * Test the following snippet:
   *  int a = 0
   *  do {
   *    if (true) {
   *      a = 2;
   *    }
   *  } while (true);
   */

  const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::CONST_4 | 1 << 8 | 0,
    Instruction::IF_NE | 1 << 8 | 1 << 12, 3,
    Instruction::CONST_4 | 2 << 12 | 0 << 8,
    Instruction::GOTO | 0xFD00,
    Instruction::RETURN_VOID);

  HGraph* graph = CreateCFG(data);
  SsaDeadPhiElimination(graph).Run();
  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
  liveness.Analyze();
  std::unique_ptr<RegisterAllocator> register_allocator =
      RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
  register_allocator->AllocateRegisters();
  ASSERT_TRUE(register_allocator->Validate(false));
}

TEST_ALL_STRATEGIES(DeadPhi);

/**
 * Test that the TryAllocateFreeReg method works in the presence of inactive intervals
 * that share the same register. It should split the interval it is currently
 * allocating for at the minimum lifetime position between the two inactive intervals.
 * This test only applies to the linear scan allocator.
 */
TEST_F(RegisterAllocatorTest, FreeUntil) {
  const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
    Instruction::CONST_4 | 0 | 0,
    Instruction::RETURN);

  HGraph* graph = CreateCFG(data);
  SsaDeadPhiElimination(graph).Run();
  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
  liveness.Analyze();
  RegisterAllocatorLinearScan register_allocator(GetScopedAllocator(), &codegen, liveness);

  // Add an artifical range to cover the temps that will be put in the unhandled list.
  LiveInterval* unhandled = graph->GetEntryBlock()->GetFirstInstruction()->GetLiveInterval();
  unhandled->AddLoopRange(0, 60);

  // Populate the instructions in the liveness object, to please the register allocator.
  for (size_t i = 0; i < 60; ++i) {
    liveness.instructions_from_lifetime_position_.push_back(
        graph->GetEntryBlock()->GetFirstInstruction());
  }

  // For SSA value intervals, only an interval resulted from a split may intersect
  // with inactive intervals.
  unhandled = register_allocator.Split(unhandled, 5);

  // Add three temps holding the same register, and starting at different positions.
  // Put the one that should be picked in the middle of the inactive list to ensure
  // we do not depend on an order.
  LiveInterval* interval =
      LiveInterval::MakeFixedInterval(GetScopedAllocator(), 0, DataType::Type::kInt32);
  interval->AddRange(40, 50);
  register_allocator.inactive_.push_back(interval);

  interval = LiveInterval::MakeFixedInterval(GetScopedAllocator(), 0, DataType::Type::kInt32);
  interval->AddRange(20, 30);
  register_allocator.inactive_.push_back(interval);

  interval = LiveInterval::MakeFixedInterval(GetScopedAllocator(), 0, DataType::Type::kInt32);
  interval->AddRange(60, 70);
  register_allocator.inactive_.push_back(interval);

  register_allocator.number_of_registers_ = 1;
  register_allocator.registers_array_ = GetAllocator()->AllocArray<size_t>(1);
  register_allocator.processing_core_registers_ = true;
  register_allocator.unhandled_ = &register_allocator.unhandled_core_intervals_;

  ASSERT_TRUE(register_allocator.TryAllocateFreeReg(unhandled));

  // Check that we have split the interval.
  ASSERT_EQ(1u, register_allocator.unhandled_->size());
  // Check that we know need to find a new register where the next interval
  // that uses the register starts.
  ASSERT_EQ(20u, register_allocator.unhandled_->front()->GetStart());
}

HGraph* RegisterAllocatorTest::BuildIfElseWithPhi(HPhi** phi,
                                                  HInstruction** input1,
                                                  HInstruction** input2) {
  HGraph* graph = CreateGraph();
  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);
  HInstruction* parameter = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
  entry->AddInstruction(parameter);

  HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(block);
  entry->AddSuccessor(block);

  HInstruction* test = new (GetAllocator()) HInstanceFieldGet(parameter,
                                                              nullptr,
                                                              DataType::Type::kBool,
                                                              MemberOffset(22),
                                                              false,
                                                              kUnknownFieldIndex,
                                                              kUnknownClassDefIndex,
                                                              graph->GetDexFile(),
                                                              0);
  block->AddInstruction(test);
  block->AddInstruction(new (GetAllocator()) HIf(test));
  HBasicBlock* then = new (GetAllocator()) HBasicBlock(graph);
  HBasicBlock* else_ = new (GetAllocator()) HBasicBlock(graph);
  HBasicBlock* join = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(then);
  graph->AddBlock(else_);
  graph->AddBlock(join);

  block->AddSuccessor(then);
  block->AddSuccessor(else_);
  then->AddSuccessor(join);
  else_->AddSuccessor(join);
  then->AddInstruction(new (GetAllocator()) HGoto());
  else_->AddInstruction(new (GetAllocator()) HGoto());

  *phi = new (GetAllocator()) HPhi(GetAllocator(), 0, 0, DataType::Type::kInt32);
  join->AddPhi(*phi);
  *input1 = new (GetAllocator()) HInstanceFieldGet(parameter,
                                                   nullptr,
                                                   DataType::Type::kInt32,
                                                   MemberOffset(42),
                                                   false,
                                                   kUnknownFieldIndex,
                                                   kUnknownClassDefIndex,
                                                   graph->GetDexFile(),
                                                   0);
  *input2 = new (GetAllocator()) HInstanceFieldGet(parameter,
                                                   nullptr,
                                                   DataType::Type::kInt32,
                                                   MemberOffset(42),
                                                   false,
                                                   kUnknownFieldIndex,
                                                   kUnknownClassDefIndex,
                                                   graph->GetDexFile(),
                                                   0);
  then->AddInstruction(*input1);
  else_->AddInstruction(*input2);
  join->AddInstruction(new (GetAllocator()) HExit());
  (*phi)->AddInput(*input1);
  (*phi)->AddInput(*input2);

  graph->BuildDominatorTree();
  graph->AnalyzeLoops();
  return graph;
}

void RegisterAllocatorTest::PhiHint(Strategy strategy) {
  HPhi *phi;
  HInstruction *input1, *input2;

  {
    HGraph* graph = BuildIfElseWithPhi(&phi, &input1, &input2);
    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
    SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
    liveness.Analyze();

    // Check that the register allocator is deterministic.
    std::unique_ptr<RegisterAllocator> register_allocator =
        RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
    register_allocator->AllocateRegisters();

    ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 0);
    ASSERT_EQ(input2->GetLiveInterval()->GetRegister(), 0);
    ASSERT_EQ(phi->GetLiveInterval()->GetRegister(), 0);
  }

  {
    HGraph* graph = BuildIfElseWithPhi(&phi, &input1, &input2);
    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
    SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
    liveness.Analyze();

    // Set the phi to a specific register, and check that the inputs get allocated
    // the same register.
    phi->GetLocations()->UpdateOut(Location::RegisterLocation(2));
    std::unique_ptr<RegisterAllocator> register_allocator =
        RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
    register_allocator->AllocateRegisters();

    ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 2);
    ASSERT_EQ(input2->GetLiveInterval()->GetRegister(), 2);
    ASSERT_EQ(phi->GetLiveInterval()->GetRegister(), 2);
  }

  {
    HGraph* graph = BuildIfElseWithPhi(&phi, &input1, &input2);
    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
    SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
    liveness.Analyze();

    // Set input1 to a specific register, and check that the phi and other input get allocated
    // the same register.
    input1->GetLocations()->UpdateOut(Location::RegisterLocation(2));
    std::unique_ptr<RegisterAllocator> register_allocator =
        RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
    register_allocator->AllocateRegisters();

    ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 2);
    ASSERT_EQ(input2->GetLiveInterval()->GetRegister(), 2);
    ASSERT_EQ(phi->GetLiveInterval()->GetRegister(), 2);
  }

  {
    HGraph* graph = BuildIfElseWithPhi(&phi, &input1, &input2);
    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
    SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
    liveness.Analyze();

    // Set input2 to a specific register, and check that the phi and other input get allocated
    // the same register.
    input2->GetLocations()->UpdateOut(Location::RegisterLocation(2));
    std::unique_ptr<RegisterAllocator> register_allocator =
        RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
    register_allocator->AllocateRegisters();

    ASSERT_EQ(input1->GetLiveInterval()->GetRegister(), 2);
    ASSERT_EQ(input2->GetLiveInterval()->GetRegister(), 2);
    ASSERT_EQ(phi->GetLiveInterval()->GetRegister(), 2);
  }
}

// TODO: Enable this test for graph coloring register allocation when iterative move
//       coalescing is merged.
TEST_F(RegisterAllocatorTest, PhiHint_LinearScan) {
  PhiHint(Strategy::kRegisterAllocatorLinearScan);
}

HGraph* RegisterAllocatorTest::BuildFieldReturn(HInstruction** field, HInstruction** ret) {
  HGraph* graph = CreateGraph();
  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);
  HInstruction* parameter = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
  entry->AddInstruction(parameter);

  HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(block);
  entry->AddSuccessor(block);

  *field = new (GetAllocator()) HInstanceFieldGet(parameter,
                                                  nullptr,
                                                  DataType::Type::kInt32,
                                                  MemberOffset(42),
                                                  false,
                                                  kUnknownFieldIndex,
                                                  kUnknownClassDefIndex,
                                                  graph->GetDexFile(),
                                                  0);
  block->AddInstruction(*field);
  *ret = new (GetAllocator()) HReturn(*field);
  block->AddInstruction(*ret);

  HBasicBlock* exit = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(exit);
  block->AddSuccessor(exit);
  exit->AddInstruction(new (GetAllocator()) HExit());

  graph->BuildDominatorTree();
  return graph;
}

void RegisterAllocatorTest::ExpectedInRegisterHint(Strategy strategy) {
  HInstruction *field, *ret;

  {
    HGraph* graph = BuildFieldReturn(&field, &ret);
    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
    SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
    liveness.Analyze();

    std::unique_ptr<RegisterAllocator> register_allocator =
        RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
    register_allocator->AllocateRegisters();

    // Sanity check that in normal conditions, the register should be hinted to 0 (EAX).
    ASSERT_EQ(field->GetLiveInterval()->GetRegister(), 0);
  }

  {
    HGraph* graph = BuildFieldReturn(&field, &ret);
    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
    SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
    liveness.Analyze();

    // Check that the field gets put in the register expected by its use.
    // Don't use SetInAt because we are overriding an already allocated location.
    ret->GetLocations()->inputs_[0] = Location::RegisterLocation(2);

    std::unique_ptr<RegisterAllocator> register_allocator =
        RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
    register_allocator->AllocateRegisters();

    ASSERT_EQ(field->GetLiveInterval()->GetRegister(), 2);
  }
}

// TODO: Enable this test for graph coloring register allocation when iterative move
//       coalescing is merged.
TEST_F(RegisterAllocatorTest, ExpectedInRegisterHint_LinearScan) {
  ExpectedInRegisterHint(Strategy::kRegisterAllocatorLinearScan);
}

HGraph* RegisterAllocatorTest::BuildTwoSubs(HInstruction** first_sub, HInstruction** second_sub) {
  HGraph* graph = CreateGraph();
  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);
  HInstruction* parameter = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32);
  entry->AddInstruction(parameter);

  HInstruction* constant1 = graph->GetIntConstant(1);
  HInstruction* constant2 = graph->GetIntConstant(2);

  HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(block);
  entry->AddSuccessor(block);

  *first_sub = new (GetAllocator()) HSub(DataType::Type::kInt32, parameter, constant1);
  block->AddInstruction(*first_sub);
  *second_sub = new (GetAllocator()) HSub(DataType::Type::kInt32, *first_sub, constant2);
  block->AddInstruction(*second_sub);

  block->AddInstruction(new (GetAllocator()) HExit());

  graph->BuildDominatorTree();
  return graph;
}

void RegisterAllocatorTest::SameAsFirstInputHint(Strategy strategy) {
  HInstruction *first_sub, *second_sub;

  {
    HGraph* graph = BuildTwoSubs(&first_sub, &second_sub);
    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
    SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
    liveness.Analyze();

    std::unique_ptr<RegisterAllocator> register_allocator =
        RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
    register_allocator->AllocateRegisters();

    // Sanity check that in normal conditions, the registers are the same.
    ASSERT_EQ(first_sub->GetLiveInterval()->GetRegister(), 1);
    ASSERT_EQ(second_sub->GetLiveInterval()->GetRegister(), 1);
  }

  {
    HGraph* graph = BuildTwoSubs(&first_sub, &second_sub);
    x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
    SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
    liveness.Analyze();

    // check that both adds get the same register.
    // Don't use UpdateOutput because output is already allocated.
    first_sub->InputAt(0)->GetLocations()->output_ = Location::RegisterLocation(2);
    ASSERT_EQ(first_sub->GetLocations()->Out().GetPolicy(), Location::kSameAsFirstInput);
    ASSERT_EQ(second_sub->GetLocations()->Out().GetPolicy(), Location::kSameAsFirstInput);

    std::unique_ptr<RegisterAllocator> register_allocator =
        RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
    register_allocator->AllocateRegisters();

    ASSERT_EQ(first_sub->GetLiveInterval()->GetRegister(), 2);
    ASSERT_EQ(second_sub->GetLiveInterval()->GetRegister(), 2);
  }
}

// TODO: Enable this test for graph coloring register allocation when iterative move
//       coalescing is merged.
TEST_F(RegisterAllocatorTest, SameAsFirstInputHint_LinearScan) {
  SameAsFirstInputHint(Strategy::kRegisterAllocatorLinearScan);
}

HGraph* RegisterAllocatorTest::BuildDiv(HInstruction** div) {
  HGraph* graph = CreateGraph();
  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);
  HInstruction* first = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32);
  HInstruction* second = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32);
  entry->AddInstruction(first);
  entry->AddInstruction(second);

  HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(block);
  entry->AddSuccessor(block);

  *div = new (GetAllocator()) HDiv(
      DataType::Type::kInt32, first, second, 0);  // don't care about dex_pc.
  block->AddInstruction(*div);

  block->AddInstruction(new (GetAllocator()) HExit());

  graph->BuildDominatorTree();
  return graph;
}

void RegisterAllocatorTest::ExpectedExactInRegisterAndSameOutputHint(Strategy strategy) {
  HInstruction *div;
  HGraph* graph = BuildDiv(&div);
  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
  liveness.Analyze();

  std::unique_ptr<RegisterAllocator> register_allocator =
      RegisterAllocator::Create(GetScopedAllocator(), &codegen, liveness, strategy);
  register_allocator->AllocateRegisters();

  // div on x86 requires its first input in eax and the output be the same as the first input.
  ASSERT_EQ(div->GetLiveInterval()->GetRegister(), 0);
}

// TODO: Enable this test for graph coloring register allocation when iterative move
//       coalescing is merged.
TEST_F(RegisterAllocatorTest, ExpectedExactInRegisterAndSameOutputHint_LinearScan) {
  ExpectedExactInRegisterAndSameOutputHint(Strategy::kRegisterAllocatorLinearScan);
}

// Test a bug in the register allocator, where allocating a blocked
// register would lead to spilling an inactive interval at the wrong
// position.
// This test only applies to the linear scan allocator.
TEST_F(RegisterAllocatorTest, SpillInactive) {
  // Create a synthesized graph to please the register_allocator and
  // ssa_liveness_analysis code.
  HGraph* graph = CreateGraph();
  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);
  HInstruction* one = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32);
  HInstruction* two = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32);
  HInstruction* three = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32);
  HInstruction* four = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kInt32);
  entry->AddInstruction(one);
  entry->AddInstruction(two);
  entry->AddInstruction(three);
  entry->AddInstruction(four);

  HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(block);
  entry->AddSuccessor(block);
  block->AddInstruction(new (GetAllocator()) HExit());

  // We create a synthesized user requesting a register, to avoid just spilling the
  // intervals.
  HPhi* user = new (GetAllocator()) HPhi(GetAllocator(), 0, 1, DataType::Type::kInt32);
  user->AddInput(one);
  user->SetBlock(block);
  LocationSummary* locations = new (GetAllocator()) LocationSummary(user, LocationSummary::kNoCall);
  locations->SetInAt(0, Location::RequiresRegister());
  static constexpr size_t phi_ranges[][2] = {{20, 30}};
  BuildInterval(phi_ranges, arraysize(phi_ranges), GetScopedAllocator(), -1, user);

  // Create an interval with lifetime holes.
  static constexpr size_t ranges1[][2] = {{0, 2}, {4, 6}, {8, 10}};
  LiveInterval* first = BuildInterval(ranges1, arraysize(ranges1), GetScopedAllocator(), -1, one);
  first->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, 0u, 8));
  first->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, 0u, 7));
  first->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, 0u, 6));

  locations = new (GetAllocator()) LocationSummary(first->GetDefinedBy(), LocationSummary::kNoCall);
  locations->SetOut(Location::RequiresRegister());
  first = first->SplitAt(1);

  // Create an interval that conflicts with the next interval, to force the next
  // interval to call `AllocateBlockedReg`.
  static constexpr size_t ranges2[][2] = {{2, 4}};
  LiveInterval* second = BuildInterval(ranges2, arraysize(ranges2), GetScopedAllocator(), -1, two);
  locations =
      new (GetAllocator()) LocationSummary(second->GetDefinedBy(), LocationSummary::kNoCall);
  locations->SetOut(Location::RequiresRegister());

  // Create an interval that will lead to splitting the first interval. The bug occured
  // by splitting at a wrong position, in this case at the next intersection between
  // this interval and the first interval. We would have then put the interval with ranges
  // "[0, 2(, [4, 6(" in the list of handled intervals, even though we haven't processed intervals
  // before lifetime position 6 yet.
  static constexpr size_t ranges3[][2] = {{2, 4}, {8, 10}};
  LiveInterval* third = BuildInterval(ranges3, arraysize(ranges3), GetScopedAllocator(), -1, three);
  third->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, 0u, 8));
  third->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, 0u, 4));
  third->uses_.push_front(*new (GetScopedAllocator()) UsePosition(user, 0u, 3));
  locations = new (GetAllocator()) LocationSummary(third->GetDefinedBy(), LocationSummary::kNoCall);
  locations->SetOut(Location::RequiresRegister());
  third = third->SplitAt(3);

  // Because the first part of the split interval was considered handled, this interval
  // was free to allocate the same register, even though it conflicts with it.
  static constexpr size_t ranges4[][2] = {{4, 6}};
  LiveInterval* fourth = BuildInterval(ranges4, arraysize(ranges4), GetScopedAllocator(), -1, four);
  locations =
      new (GetAllocator()) LocationSummary(fourth->GetDefinedBy(), LocationSummary::kNoCall);
  locations->SetOut(Location::RequiresRegister());

  x86::CodeGeneratorX86 codegen(graph, *compiler_options_);
  SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
  // Populate the instructions in the liveness object, to please the register allocator.
  for (size_t i = 0; i < 32; ++i) {
    liveness.instructions_from_lifetime_position_.push_back(user);
  }

  RegisterAllocatorLinearScan register_allocator(GetScopedAllocator(), &codegen, liveness);
  register_allocator.unhandled_core_intervals_.push_back(fourth);
  register_allocator.unhandled_core_intervals_.push_back(third);
  register_allocator.unhandled_core_intervals_.push_back(second);
  register_allocator.unhandled_core_intervals_.push_back(first);

  // Set just one register available to make all intervals compete for the same.
  register_allocator.number_of_registers_ = 1;
  register_allocator.registers_array_ = GetAllocator()->AllocArray<size_t>(1);
  register_allocator.processing_core_registers_ = true;
  register_allocator.unhandled_ = &register_allocator.unhandled_core_intervals_;
  register_allocator.LinearScan();

  // Test that there is no conflicts between intervals.
  ScopedArenaVector<LiveInterval*> intervals(GetScopedAllocator()->Adapter());
  intervals.push_back(first);
  intervals.push_back(second);
  intervals.push_back(third);
  intervals.push_back(fourth);
  ASSERT_TRUE(ValidateIntervals(intervals, codegen));
}

}  // namespace art
