/*
 * 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 "builder.h"
#include "gvn.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
#include "side_effects_analysis.h"

namespace art {

class GVNTest : public CommonCompilerTest {};

TEST_F(GVNTest, LocalFieldElimination) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = CreateGraph(&allocator);
  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);
  HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
                                                             dex::TypeIndex(0),
                                                             0,
                                                             Primitive::kPrimNot);
  entry->AddInstruction(parameter);

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

  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                           nullptr,
                                                           Primitive::kPrimNot,
                                                           MemberOffset(42),
                                                           false,
                                                           kUnknownFieldIndex,
                                                           kUnknownClassDefIndex,
                                                           graph->GetDexFile(),
                                                           0));
  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                           nullptr,
                                                           Primitive::kPrimNot,
                                                           MemberOffset(42),
                                                           false,
                                                           kUnknownFieldIndex,
                                                           kUnknownClassDefIndex,
                                                           graph->GetDexFile(),
                                                           0));
  HInstruction* to_remove = block->GetLastInstruction();
  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                           nullptr,
                                                           Primitive::kPrimNot,
                                                           MemberOffset(43),
                                                           false,
                                                           kUnknownFieldIndex,
                                                           kUnknownClassDefIndex,
                                                           graph->GetDexFile(),
                                                           0));
  HInstruction* different_offset = block->GetLastInstruction();
  // Kill the value.
  block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
                                                           parameter,
                                                           nullptr,
                                                           Primitive::kPrimNot,
                                                           MemberOffset(42),
                                                           false,
                                                           kUnknownFieldIndex,
                                                           kUnknownClassDefIndex,
                                                           graph->GetDexFile(),
                                                           0));
  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                           nullptr,
                                                           Primitive::kPrimNot,
                                                           MemberOffset(42),
                                                           false,
                                                           kUnknownFieldIndex,
                                                           kUnknownClassDefIndex,
                                                           graph->GetDexFile(),
                                                           0));
  HInstruction* use_after_kill = block->GetLastInstruction();
  block->AddInstruction(new (&allocator) HExit());

  ASSERT_EQ(to_remove->GetBlock(), block);
  ASSERT_EQ(different_offset->GetBlock(), block);
  ASSERT_EQ(use_after_kill->GetBlock(), block);

  graph->BuildDominatorTree();
  SideEffectsAnalysis side_effects(graph);
  side_effects.Run();
  GVNOptimization(graph, side_effects).Run();

  ASSERT_TRUE(to_remove->GetBlock() == nullptr);
  ASSERT_EQ(different_offset->GetBlock(), block);
  ASSERT_EQ(use_after_kill->GetBlock(), block);
}

TEST_F(GVNTest, GlobalFieldElimination) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = CreateGraph(&allocator);
  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);
  HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
                                                             dex::TypeIndex(0),
                                                             0,
                                                             Primitive::kPrimNot);
  entry->AddInstruction(parameter);

  HBasicBlock* block = new (&allocator) HBasicBlock(graph);
  graph->AddBlock(block);
  entry->AddSuccessor(block);
  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                           nullptr,
                                                           Primitive::kPrimBoolean,
                                                           MemberOffset(42),
                                                           false,
                                                           kUnknownFieldIndex,
                                                           kUnknownClassDefIndex,
                                                           graph->GetDexFile(),
                                                           0));

  block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
  HBasicBlock* then = new (&allocator) HBasicBlock(graph);
  HBasicBlock* else_ = new (&allocator) HBasicBlock(graph);
  HBasicBlock* join = new (&allocator) 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 (&allocator) HInstanceFieldGet(parameter,
                                                          nullptr,
                                                          Primitive::kPrimBoolean,
                                                          MemberOffset(42),
                                                          false,
                                                          kUnknownFieldIndex,
                                                          kUnknownClassDefIndex,
                                                          graph->GetDexFile(),
                                                          0));
  then->AddInstruction(new (&allocator) HGoto());
  else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                           nullptr,
                                                           Primitive::kPrimBoolean,
                                                           MemberOffset(42),
                                                           false,
                                                           kUnknownFieldIndex,
                                                           kUnknownClassDefIndex,
                                                           graph->GetDexFile(),
                                                           0));
  else_->AddInstruction(new (&allocator) HGoto());
  join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                          nullptr,
                                                          Primitive::kPrimBoolean,
                                                          MemberOffset(42),
                                                          false,
                                                          kUnknownFieldIndex,
                                                          kUnknownClassDefIndex,
                                                          graph->GetDexFile(),
                                                          0));
  join->AddInstruction(new (&allocator) HExit());

  graph->BuildDominatorTree();
  SideEffectsAnalysis side_effects(graph);
  side_effects.Run();
  GVNOptimization(graph, side_effects).Run();

  // Check that all field get instructions have been GVN'ed.
  ASSERT_TRUE(then->GetFirstInstruction()->IsGoto());
  ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto());
  ASSERT_TRUE(join->GetFirstInstruction()->IsExit());
}

TEST_F(GVNTest, LoopFieldElimination) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  HGraph* graph = CreateGraph(&allocator);
  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);

  HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
                                                             dex::TypeIndex(0),
                                                             0,
                                                             Primitive::kPrimNot);
  entry->AddInstruction(parameter);

  HBasicBlock* block = new (&allocator) HBasicBlock(graph);
  graph->AddBlock(block);
  entry->AddSuccessor(block);
  block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                           nullptr,
                                                           Primitive::kPrimBoolean,
                                                           MemberOffset(42),
                                                           false,
                                                           kUnknownFieldIndex,
                                                           kUnknownClassDefIndex,
                                                           graph->GetDexFile(),
                                                           0));
  block->AddInstruction(new (&allocator) HGoto());

  HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph);
  HBasicBlock* loop_body = new (&allocator) HBasicBlock(graph);
  HBasicBlock* exit = new (&allocator) HBasicBlock(graph);

  graph->AddBlock(loop_header);
  graph->AddBlock(loop_body);
  graph->AddBlock(exit);
  block->AddSuccessor(loop_header);
  loop_header->AddSuccessor(loop_body);
  loop_header->AddSuccessor(exit);
  loop_body->AddSuccessor(loop_header);

  loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                                 nullptr,
                                                                 Primitive::kPrimBoolean,
                                                                 MemberOffset(42),
                                                                 false,
                                                                 kUnknownFieldIndex,
                                                                 kUnknownClassDefIndex,
                                                                 graph->GetDexFile(),
                                                                 0));
  HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
  loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));

  // Kill inside the loop body to prevent field gets inside the loop header
  // and the body to be GVN'ed.
  loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
                                                               parameter,
                                                               nullptr,
                                                               Primitive::kPrimBoolean,
                                                               MemberOffset(42),
                                                               false,
                                                               kUnknownFieldIndex,
                                                               kUnknownClassDefIndex,
                                                               graph->GetDexFile(),
                                                               0));
  HInstruction* field_set = loop_body->GetLastInstruction();
  loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                               nullptr,
                                                               Primitive::kPrimBoolean,
                                                               MemberOffset(42),
                                                               false,
                                                               kUnknownFieldIndex,
                                                               kUnknownClassDefIndex,
                                                               graph->GetDexFile(),
                                                               0));
  HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
  loop_body->AddInstruction(new (&allocator) HGoto());

  exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
                                                          nullptr,
                                                          Primitive::kPrimBoolean,
                                                          MemberOffset(42),
                                                          false,
                                                          kUnknownFieldIndex,
                                                          kUnknownClassDefIndex,
                                                          graph->GetDexFile(),
                                                          0));
  HInstruction* field_get_in_exit = exit->GetLastInstruction();
  exit->AddInstruction(new (&allocator) HExit());

  ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
  ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
  ASSERT_EQ(field_get_in_exit->GetBlock(), exit);

  graph->BuildDominatorTree();
  {
    SideEffectsAnalysis side_effects(graph);
    side_effects.Run();
    GVNOptimization(graph, side_effects).Run();
  }

  // Check that all field get instructions are still there.
  ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
  ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
  // The exit block is dominated by the loop header, whose field get
  // does not get killed by the loop flags.
  ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);

  // Now remove the field set, and check that all field get instructions have been GVN'ed.
  loop_body->RemoveInstruction(field_set);
  {
    SideEffectsAnalysis side_effects(graph);
    side_effects.Run();
    GVNOptimization(graph, side_effects).Run();
  }

  ASSERT_TRUE(field_get_in_loop_header->GetBlock() == nullptr);
  ASSERT_TRUE(field_get_in_loop_body->GetBlock() == nullptr);
  ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
}

// Test that inner loops affect the side effects of the outer loop.
TEST_F(GVNTest, LoopSideEffects) {
  ArenaPool pool;
  ArenaAllocator allocator(&pool);

  static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC();

  HGraph* graph = CreateGraph(&allocator);
  HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
  graph->AddBlock(entry);
  graph->SetEntryBlock(entry);

  HBasicBlock* outer_loop_header = new (&allocator) HBasicBlock(graph);
  HBasicBlock* outer_loop_body = new (&allocator) HBasicBlock(graph);
  HBasicBlock* outer_loop_exit = new (&allocator) HBasicBlock(graph);
  HBasicBlock* inner_loop_header = new (&allocator) HBasicBlock(graph);
  HBasicBlock* inner_loop_body = new (&allocator) HBasicBlock(graph);
  HBasicBlock* inner_loop_exit = new (&allocator) HBasicBlock(graph);

  graph->AddBlock(outer_loop_header);
  graph->AddBlock(outer_loop_body);
  graph->AddBlock(outer_loop_exit);
  graph->AddBlock(inner_loop_header);
  graph->AddBlock(inner_loop_body);
  graph->AddBlock(inner_loop_exit);

  entry->AddSuccessor(outer_loop_header);
  outer_loop_header->AddSuccessor(outer_loop_body);
  outer_loop_header->AddSuccessor(outer_loop_exit);
  outer_loop_body->AddSuccessor(inner_loop_header);
  inner_loop_header->AddSuccessor(inner_loop_body);
  inner_loop_header->AddSuccessor(inner_loop_exit);
  inner_loop_body->AddSuccessor(inner_loop_header);
  inner_loop_exit->AddSuccessor(outer_loop_header);

  HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
                                                             dex::TypeIndex(0),
                                                             0,
                                                             Primitive::kPrimBoolean);
  entry->AddInstruction(parameter);
  entry->AddInstruction(new (&allocator) HGoto());
  outer_loop_header->AddInstruction(new (&allocator) HSuspendCheck());
  outer_loop_header->AddInstruction(new (&allocator) HIf(parameter));
  outer_loop_body->AddInstruction(new (&allocator) HGoto());
  inner_loop_header->AddInstruction(new (&allocator) HSuspendCheck());
  inner_loop_header->AddInstruction(new (&allocator) HIf(parameter));
  inner_loop_body->AddInstruction(new (&allocator) HGoto());
  inner_loop_exit->AddInstruction(new (&allocator) HGoto());
  outer_loop_exit->AddInstruction(new (&allocator) HExit());

  graph->BuildDominatorTree();

  ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
      *outer_loop_header->GetLoopInformation()));

  // Check that the only side effect of loops is to potentially trigger GC.
  {
    // Make one block with a side effect.
    entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
                                                             parameter,
                                                             nullptr,
                                                             Primitive::kPrimNot,
                                                             MemberOffset(42),
                                                             false,
                                                             kUnknownFieldIndex,
                                                             kUnknownClassDefIndex,
                                                             graph->GetDexFile(),
                                                             0));

    SideEffectsAnalysis side_effects(graph);
    side_effects.Run();

    ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
    ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
    ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
    ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
    ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).Equals(kCanTriggerGC));
    ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
  }

  // Check that the side effects of the outer loop does not affect the inner loop.
  {
    outer_loop_body->InsertInstructionBefore(
        new (&allocator) HInstanceFieldSet(parameter,
                                           parameter,
                                           nullptr,
                                           Primitive::kPrimNot,
                                           MemberOffset(42),
                                           false,
                                           kUnknownFieldIndex,
                                           kUnknownClassDefIndex,
                                           graph->GetDexFile(),
                                           0),
        outer_loop_body->GetLastInstruction());

    SideEffectsAnalysis side_effects(graph);
    side_effects.Run();

    ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
    ASSERT_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
    ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
    ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
    ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
  }

  // Check that the side effects of the inner loop affects the outer loop.
  {
    outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
    inner_loop_body->InsertInstructionBefore(
        new (&allocator) HInstanceFieldSet(parameter,
                                           parameter,
                                           nullptr,
                                           Primitive::kPrimNot,
                                           MemberOffset(42),
                                           false,
                                           kUnknownFieldIndex,
                                           kUnknownClassDefIndex,
                                           graph->GetDexFile(),
                                           0),
        inner_loop_body->GetLastInstruction());

    SideEffectsAnalysis side_effects(graph);
    side_effects.Run();

    ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
    ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
    ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
    ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
  }
}
}  // namespace art
