/*
 * 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 "nodes.h"

#include "base/arena_allocator.h"
#include "optimizing_unit_test.h"

#include "gtest/gtest.h"

namespace art {

class NodeTest : public OptimizingUnitTest {};

/**
 * Test that we can clear loop and dominator information in either order.
 * Code is:
 * while (true) {
 *   if (foobar) { break; }
 *   if (baz) { xyz; } else { abc; }
 * }
 * dosomething();
 */
TEST_F(NodeTest, ClearLoopThenDominanceInformation) {
  CreateGraph();
  AdjacencyListGraph alg(graph_,
                         GetAllocator(),
                         "entry",
                         "exit",
                         {{"entry", "loop_pre_header"},

                          {"loop_pre_header", "loop_header"},
                          {"loop_header", "critical_break"},
                          {"loop_header", "loop_body"},
                          {"loop_body", "loop_if_left"},
                          {"loop_body", "loop_if_right"},
                          {"loop_if_left", "loop_merge"},
                          {"loop_if_right", "loop_merge"},
                          {"loop_merge", "loop_header"},

                          {"critical_break", "breturn"},
                          {"breturn", "exit"}});
  graph_->ClearDominanceInformation();
  graph_->BuildDominatorTree();

  // Test
  EXPECT_TRUE(
      std::all_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
        return b == graph_->GetEntryBlock() || b == nullptr || b->GetDominator() != nullptr;
      }));
  EXPECT_TRUE(
      std::any_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
        return b != nullptr && b->GetLoopInformation() != nullptr;
      }));

  // Clear
  graph_->ClearLoopInformation();
  graph_->ClearDominanceInformation();

  // Test
  EXPECT_TRUE(
      std::none_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
        return b != nullptr && b->GetDominator() != nullptr;
      }));
  EXPECT_TRUE(
      std::all_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
        return b == nullptr || b->GetLoopInformation() == nullptr;
      }));
}

/**
 * Test that we can clear loop and dominator information in either order.
 * Code is:
 * while (true) {
 *   if (foobar) { break; }
 *   if (baz) { xyz; } else { abc; }
 * }
 * dosomething();
 */
TEST_F(NodeTest, ClearDominanceThenLoopInformation) {
  CreateGraph();
  AdjacencyListGraph alg(graph_,
                         GetAllocator(),
                         "entry",
                         "exit",
                         {{"entry", "loop_pre_header"},

                          {"loop_pre_header", "loop_header"},
                          {"loop_header", "critical_break"},
                          {"loop_header", "loop_body"},
                          {"loop_body", "loop_if_left"},
                          {"loop_body", "loop_if_right"},
                          {"loop_if_left", "loop_merge"},
                          {"loop_if_right", "loop_merge"},
                          {"loop_merge", "loop_header"},

                          {"critical_break", "breturn"},
                          {"breturn", "exit"}});
  graph_->ClearDominanceInformation();
  graph_->BuildDominatorTree();

  // Test
  EXPECT_TRUE(
      std::all_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
        return b == graph_->GetEntryBlock() || b == nullptr || b->GetDominator() != nullptr;
      }));
  EXPECT_TRUE(
      std::any_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
        return b != nullptr && b->GetLoopInformation() != nullptr;
      }));

  // Clear
  graph_->ClearDominanceInformation();
  graph_->ClearLoopInformation();

  // Test
  EXPECT_TRUE(
      std::none_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
        return b != nullptr && b->GetDominator() != nullptr;
      }));
  EXPECT_TRUE(
      std::all_of(graph_->GetBlocks().begin(), graph_->GetBlocks().end(), [&](HBasicBlock* b) {
        return b == nullptr || b->GetLoopInformation() == nullptr;
      }));
}

/**
 * Test that removing instruction from the graph removes itself from user lists
 * and environment lists.
 */
TEST_F(NodeTest, RemoveInstruction) {
  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);
  entry->AddInstruction(new (GetAllocator()) HGoto());

  HBasicBlock* first_block = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(first_block);
  entry->AddSuccessor(first_block);
  HInstruction* null_check = new (GetAllocator()) HNullCheck(parameter, 0);
  first_block->AddInstruction(null_check);
  first_block->AddInstruction(new (GetAllocator()) HReturnVoid());

  HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(exit_block);
  first_block->AddSuccessor(exit_block);
  exit_block->AddInstruction(new (GetAllocator()) HExit());

  HEnvironment* environment = new (GetAllocator()) HEnvironment(
      GetAllocator(), 1, graph->GetArtMethod(), 0, null_check);
  null_check->SetRawEnvironment(environment);
  environment->SetRawEnvAt(0, parameter);
  parameter->AddEnvUseAt(null_check->GetEnvironment(), 0);

  ASSERT_TRUE(parameter->HasEnvironmentUses());
  ASSERT_TRUE(parameter->HasUses());

  first_block->RemoveInstruction(null_check);

  ASSERT_FALSE(parameter->HasEnvironmentUses());
  ASSERT_FALSE(parameter->HasUses());
}

/**
 * Test that inserting an instruction in the graph updates user lists.
 */
TEST_F(NodeTest, InsertInstruction) {
  HGraph* graph = CreateGraph();
  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);
  HInstruction* parameter1 = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
  HInstruction* parameter2 = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
  entry->AddInstruction(parameter1);
  entry->AddInstruction(parameter2);
  entry->AddInstruction(new (GetAllocator()) HExit());

  ASSERT_FALSE(parameter1->HasUses());

  HInstruction* to_insert = new (GetAllocator()) HNullCheck(parameter1, 0);
  entry->InsertInstructionBefore(to_insert, parameter2);

  ASSERT_TRUE(parameter1->HasUses());
  ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());
}

/**
 * Test that adding an instruction in the graph updates user lists.
 */
TEST_F(NodeTest, AddInstruction) {
  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);

  ASSERT_FALSE(parameter->HasUses());

  HInstruction* to_add = new (GetAllocator()) HNullCheck(parameter, 0);
  entry->AddInstruction(to_add);

  ASSERT_TRUE(parameter->HasUses());
  ASSERT_TRUE(parameter->GetUses().HasExactlyOneElement());
}

TEST_F(NodeTest, ParentEnvironment) {
  HGraph* graph = CreateGraph();
  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);
  HInstruction* parameter1 = new (GetAllocator()) HParameterValue(
      graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference);
  HInstruction* with_environment = new (GetAllocator()) HNullCheck(parameter1, 0);
  entry->AddInstruction(parameter1);
  entry->AddInstruction(with_environment);
  entry->AddInstruction(new (GetAllocator()) HExit());

  ASSERT_TRUE(parameter1->HasUses());
  ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement());

  HEnvironment* environment = new (GetAllocator()) HEnvironment(
      GetAllocator(), 1, graph->GetArtMethod(), 0, with_environment);
  HInstruction* const array[] = { parameter1 };

  environment->CopyFrom(ArrayRef<HInstruction* const>(array));
  with_environment->SetRawEnvironment(environment);

  ASSERT_TRUE(parameter1->HasEnvironmentUses());
  ASSERT_TRUE(parameter1->GetEnvUses().HasExactlyOneElement());

  HEnvironment* parent1 = new (GetAllocator()) HEnvironment(
      GetAllocator(), 1, graph->GetArtMethod(), 0, nullptr);
  parent1->CopyFrom(ArrayRef<HInstruction* const>(array));

  ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u);

  HEnvironment* parent2 = new (GetAllocator()) HEnvironment(
      GetAllocator(), 1, graph->GetArtMethod(), 0, nullptr);
  parent2->CopyFrom(ArrayRef<HInstruction* const>(array));
  parent1->SetAndCopyParentChain(GetAllocator(), parent2);

  // One use for parent2, and one other use for the new parent of parent1.
  ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 4u);

  // We have copied the parent chain. So we now have two more uses.
  environment->SetAndCopyParentChain(GetAllocator(), parent1);
  ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 6u);
}

}  // namespace art
