/*
 * 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 "base/arena_allocator.h"
#include "base/stringprintf.h"
#include "builder.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "pretty_printer.h"

#include "gtest/gtest.h"

namespace art {

static HBasicBlock* createIfBlock(HGraph* graph, ArenaAllocator* allocator) {
  HBasicBlock* if_block = new (allocator) HBasicBlock(graph);
  graph->AddBlock(if_block);
  HInstruction* instr = graph->GetIntConstant(4);
  HInstruction* equal = new (allocator) HEqual(instr, instr);
  if_block->AddInstruction(equal);
  instr = new (allocator) HIf(equal);
  if_block->AddInstruction(instr);
  return if_block;
}

static HBasicBlock* createGotoBlock(HGraph* graph, ArenaAllocator* allocator) {
  HBasicBlock* block = new (allocator) HBasicBlock(graph);
  graph->AddBlock(block);
  HInstruction* got = new (allocator) HGoto();
  block->AddInstruction(got);
  return block;
}

static HBasicBlock* createEntryBlock(HGraph* graph, ArenaAllocator* allocator) {
  HBasicBlock* block = createGotoBlock(graph, allocator);
  graph->SetEntryBlock(block);
  return block;
}

static HBasicBlock* createReturnBlock(HGraph* graph, ArenaAllocator* allocator) {
  HBasicBlock* block = new (allocator) HBasicBlock(graph);
  graph->AddBlock(block);
  HInstruction* return_instr = new (allocator) HReturnVoid();
  block->AddInstruction(return_instr);
  return block;
}

static HBasicBlock* createExitBlock(HGraph* graph, ArenaAllocator* allocator) {
  HBasicBlock* block = new (allocator) HBasicBlock(graph);
  graph->AddBlock(block);
  HInstruction* exit_instr = new (allocator) HExit();
  block->AddInstruction(exit_instr);
  return block;
}


// Test that the successors of an if block stay consistent after a SimplifyCFG.
// This test sets the false block to be the return block.
TEST(GraphTest, IfSuccessorSimpleJoinBlock1) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = new (&allocator) HGraph(&allocator);
  HBasicBlock* entry_block = createEntryBlock(graph, &allocator);
  HBasicBlock* if_block = createIfBlock(graph, &allocator);
  HBasicBlock* if_true = createGotoBlock(graph, &allocator);
  HBasicBlock* return_block = createReturnBlock(graph, &allocator);
  HBasicBlock* exit_block = createExitBlock(graph, &allocator);

  entry_block->AddSuccessor(if_block);
  if_block->AddSuccessor(if_true);
  if_true->AddSuccessor(return_block);
  if_block->AddSuccessor(return_block);
  return_block->AddSuccessor(exit_block);

  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor(), if_true);
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor(), return_block);

  graph->SimplifyCFG();

  // Ensure we still have the same if true block.
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor(), if_true);

  // Ensure the critical edge has been removed.
  HBasicBlock* false_block = if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor();
  ASSERT_NE(false_block, return_block);

  // Ensure the new block branches to the join block.
  ASSERT_EQ(false_block->GetSuccessors().Get(0), return_block);
}

// Test that the successors of an if block stay consistent after a SimplifyCFG.
// This test sets the true block to be the return block.
TEST(GraphTest, IfSuccessorSimpleJoinBlock2) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = new (&allocator) HGraph(&allocator);
  HBasicBlock* entry_block = createEntryBlock(graph, &allocator);
  HBasicBlock* if_block = createIfBlock(graph, &allocator);
  HBasicBlock* if_false = createGotoBlock(graph, &allocator);
  HBasicBlock* return_block = createReturnBlock(graph, &allocator);
  HBasicBlock* exit_block = createExitBlock(graph, &allocator);

  entry_block->AddSuccessor(if_block);
  if_block->AddSuccessor(return_block);
  if_false->AddSuccessor(return_block);
  if_block->AddSuccessor(if_false);
  return_block->AddSuccessor(exit_block);

  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor(), return_block);
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor(), if_false);

  graph->SimplifyCFG();

  // Ensure we still have the same if true block.
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor(), if_false);

  // Ensure the critical edge has been removed.
  HBasicBlock* true_block = if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor();
  ASSERT_NE(true_block, return_block);

  // Ensure the new block branches to the join block.
  ASSERT_EQ(true_block->GetSuccessors().Get(0), return_block);
}

// Test that the successors of an if block stay consistent after a SimplifyCFG.
// This test sets the true block to be the loop header.
TEST(GraphTest, IfSuccessorMultipleBackEdges1) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = new (&allocator) HGraph(&allocator);
  HBasicBlock* entry_block = createEntryBlock(graph, &allocator);
  HBasicBlock* if_block = createIfBlock(graph, &allocator);
  HBasicBlock* return_block = createReturnBlock(graph, &allocator);
  HBasicBlock* exit_block = createExitBlock(graph, &allocator);

  entry_block->AddSuccessor(if_block);
  if_block->AddSuccessor(if_block);
  if_block->AddSuccessor(return_block);
  return_block->AddSuccessor(exit_block);

  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor(), if_block);
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor(), return_block);

  graph->BuildDominatorTree();

  // Ensure we still have the same if false block.
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor(), return_block);

  // Ensure there is only one back edge.
  ASSERT_EQ(if_block->GetPredecessors().Size(), 2u);
  ASSERT_EQ(if_block->GetPredecessors().Get(0), entry_block);
  ASSERT_NE(if_block->GetPredecessors().Get(1), if_block);

  // Ensure the new block is the back edge.
  ASSERT_EQ(if_block->GetPredecessors().Get(1),
            if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor());
}

// Test that the successors of an if block stay consistent after a SimplifyCFG.
// This test sets the false block to be the loop header.
TEST(GraphTest, IfSuccessorMultipleBackEdges2) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = new (&allocator) HGraph(&allocator);
  HBasicBlock* entry_block = createEntryBlock(graph, &allocator);
  HBasicBlock* if_block = createIfBlock(graph, &allocator);
  HBasicBlock* return_block = createReturnBlock(graph, &allocator);
  HBasicBlock* exit_block = createExitBlock(graph, &allocator);

  entry_block->AddSuccessor(if_block);
  if_block->AddSuccessor(return_block);
  if_block->AddSuccessor(if_block);
  return_block->AddSuccessor(exit_block);

  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor(), return_block);
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor(), if_block);

  graph->BuildDominatorTree();

  // Ensure we still have the same if true block.
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor(), return_block);

  // Ensure there is only one back edge.
  ASSERT_EQ(if_block->GetPredecessors().Size(), 2u);
  ASSERT_EQ(if_block->GetPredecessors().Get(0), entry_block);
  ASSERT_NE(if_block->GetPredecessors().Get(1), if_block);

  // Ensure the new block is the back edge.
  ASSERT_EQ(if_block->GetPredecessors().Get(1),
            if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor());
}

// Test that the successors of an if block stay consistent after a SimplifyCFG.
// This test sets the true block to be a loop header with multiple pre headers.
TEST(GraphTest, IfSuccessorMultiplePreHeaders1) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = new (&allocator) HGraph(&allocator);
  HBasicBlock* entry_block = createEntryBlock(graph, &allocator);
  HBasicBlock* first_if_block = createIfBlock(graph, &allocator);
  HBasicBlock* if_block = createIfBlock(graph, &allocator);
  HBasicBlock* loop_block = createGotoBlock(graph, &allocator);
  HBasicBlock* return_block = createReturnBlock(graph, &allocator);

  entry_block->AddSuccessor(first_if_block);
  first_if_block->AddSuccessor(if_block);
  first_if_block->AddSuccessor(loop_block);
  loop_block->AddSuccessor(loop_block);
  if_block->AddSuccessor(loop_block);
  if_block->AddSuccessor(return_block);


  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor(), loop_block);
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor(), return_block);

  graph->BuildDominatorTree();

  HIf* if_instr = if_block->GetLastInstruction()->AsIf();
  // Ensure we still have the same if false block.
  ASSERT_EQ(if_instr->IfFalseSuccessor(), return_block);

  // Ensure there is only one pre header..
  ASSERT_EQ(loop_block->GetPredecessors().Size(), 2u);

  // Ensure the new block is the successor of the true block.
  ASSERT_EQ(if_instr->IfTrueSuccessor()->GetSuccessors().Size(), 1u);
  ASSERT_EQ(if_instr->IfTrueSuccessor()->GetSuccessors().Get(0),
            loop_block->GetLoopInformation()->GetPreHeader());
}

// Test that the successors of an if block stay consistent after a SimplifyCFG.
// This test sets the false block to be a loop header with multiple pre headers.
TEST(GraphTest, IfSuccessorMultiplePreHeaders2) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = new (&allocator) HGraph(&allocator);
  HBasicBlock* entry_block = createEntryBlock(graph, &allocator);
  HBasicBlock* first_if_block = createIfBlock(graph, &allocator);
  HBasicBlock* if_block = createIfBlock(graph, &allocator);
  HBasicBlock* loop_block = createGotoBlock(graph, &allocator);
  HBasicBlock* return_block = createReturnBlock(graph, &allocator);

  entry_block->AddSuccessor(first_if_block);
  first_if_block->AddSuccessor(if_block);
  first_if_block->AddSuccessor(loop_block);
  loop_block->AddSuccessor(loop_block);
  if_block->AddSuccessor(return_block);
  if_block->AddSuccessor(loop_block);

  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfTrueSuccessor(), return_block);
  ASSERT_EQ(if_block->GetLastInstruction()->AsIf()->IfFalseSuccessor(), loop_block);

  graph->BuildDominatorTree();

  HIf* if_instr = if_block->GetLastInstruction()->AsIf();
  // Ensure we still have the same if true block.
  ASSERT_EQ(if_instr->IfTrueSuccessor(), return_block);

  // Ensure there is only one pre header..
  ASSERT_EQ(loop_block->GetPredecessors().Size(), 2u);

  // Ensure the new block is the successor of the false block.
  ASSERT_EQ(if_instr->IfFalseSuccessor()->GetSuccessors().Size(), 1u);
  ASSERT_EQ(if_instr->IfFalseSuccessor()->GetSuccessors().Get(0),
            loop_block->GetLoopInformation()->GetPreHeader());
}

TEST(GraphTest, InsertInstructionBefore) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = new (&allocator) HGraph(&allocator);
  HBasicBlock* block = createGotoBlock(graph, &allocator);
  HInstruction* got = block->GetLastInstruction();
  ASSERT_TRUE(got->IsControlFlow());

  // Test at the beginning of the block.
  HInstruction* first_instruction = new (&allocator) HIntConstant(4);
  block->InsertInstructionBefore(first_instruction, got);

  ASSERT_NE(first_instruction->GetId(), -1);
  ASSERT_EQ(first_instruction->GetBlock(), block);
  ASSERT_EQ(block->GetFirstInstruction(), first_instruction);
  ASSERT_EQ(block->GetLastInstruction(), got);
  ASSERT_EQ(first_instruction->GetNext(), got);
  ASSERT_EQ(first_instruction->GetPrevious(), nullptr);
  ASSERT_EQ(got->GetNext(), nullptr);
  ASSERT_EQ(got->GetPrevious(), first_instruction);

  // Test in the middle of the block.
  HInstruction* second_instruction = new (&allocator) HIntConstant(4);
  block->InsertInstructionBefore(second_instruction, got);

  ASSERT_NE(second_instruction->GetId(), -1);
  ASSERT_EQ(second_instruction->GetBlock(), block);
  ASSERT_EQ(block->GetFirstInstruction(), first_instruction);
  ASSERT_EQ(block->GetLastInstruction(), got);
  ASSERT_EQ(first_instruction->GetNext(), second_instruction);
  ASSERT_EQ(first_instruction->GetPrevious(), nullptr);
  ASSERT_EQ(second_instruction->GetNext(), got);
  ASSERT_EQ(second_instruction->GetPrevious(), first_instruction);
  ASSERT_EQ(got->GetNext(), nullptr);
  ASSERT_EQ(got->GetPrevious(), second_instruction);
}

}  // namespace art
