// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/compiler/backend/constant_propagator.h"

#include "vm/compiler/backend/block_builder.h"
#include "vm/compiler/backend/il_printer.h"
#include "vm/compiler/backend/il_test_helper.h"
#include "vm/compiler/backend/type_propagator.h"
#include "vm/unit_test.h"

namespace dart {

// Test issue https://github.com/flutter/flutter/issues/53903.
//
// If graph contains a cyclic phi which participates in an EqualityCompare
// or StrictCompare with its input like phi(x, ...) == x then constant
// propagation might fail to converge by constantly revisiting this phi and
// its uses (which includes comparison and the phi itself).
ISOLATE_UNIT_TEST_CASE(ConstantPropagation_PhiUnwrappingAndConvergence) {
  using compiler::BlockBuilder;
  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
  FlowGraphBuilderHelper H;

  // We are going to build the following graph:
  //
  // B0[graph_entry]
  // B1[function_entry]:
  //   v0 <- Constant(0)
  //   goto B2
  // B2:
  //   v1 <- phi(v0, v1)
  //   v2 <- EqualityCompare(v1 == v0)
  //   if v2 == true then B4 else B3
  // B3:
  //   goto B2
  // B4:
  //   Return(v1)

  PhiInstr* v1;
  ConstantInstr* v0 = H.IntConstant(0);
  auto b1 = H.flow_graph()->graph_entry()->normal_entry();
  auto b2 = H.JoinEntry();
  auto b3 = H.TargetEntry();
  auto b4 = H.TargetEntry();

  {
    BlockBuilder builder(H.flow_graph(), b1);
    builder.AddInstruction(new GotoInstr(b2, S.GetNextDeoptId()));
  }

  {
    BlockBuilder builder(H.flow_graph(), b2);
    v1 = H.Phi(b2, {{b1, v0}, {b3, &v1}});
    builder.AddPhi(v1);
    auto v2 = builder.AddDefinition(
        new EqualityCompareInstr(InstructionSource(), Token::kEQ, new Value(v1),
                                 new Value(v0), kSmiCid, S.GetNextDeoptId()));
    builder.AddBranch(new StrictCompareInstr(
                          InstructionSource(), Token::kEQ_STRICT, new Value(v2),
                          new Value(H.flow_graph()->GetConstant(Bool::True())),
                          /*needs_number_check=*/false, S.GetNextDeoptId()),
                      b4, b3);
  }

  {
    BlockBuilder builder(H.flow_graph(), b3);
    builder.AddInstruction(new GotoInstr(b2, S.GetNextDeoptId()));
  }

  {
    BlockBuilder builder(H.flow_graph(), b4);
    builder.AddReturn(new Value(v1));
  }

  H.FinishGraph();

  // Graph transformations will attempt to copy deopt information from
  // branches and block entries which we did not assign.
  // To disable copying we mark graph to disable LICM.
  H.flow_graph()->disallow_licm();

  FlowGraphPrinter::PrintGraph("Before ConstantPropagator", H.flow_graph());
  ConstantPropagator::Optimize(H.flow_graph());
  FlowGraphPrinter::PrintGraph("After ConstantPropagator", H.flow_graph());

  auto& blocks = H.flow_graph()->reverse_postorder();
  EXPECT_EQ(2, blocks.length());
  EXPECT_PROPERTY(blocks[0], it.IsGraphEntry());
  EXPECT_PROPERTY(blocks[1], it.IsFunctionEntry());
  EXPECT_PROPERTY(blocks[1]->next(), it.IsReturn());
  EXPECT_PROPERTY(blocks[1]->next()->AsReturn(),
                  it.value()->definition() == v0);
}

// This test does not work on 32-bit platforms because it requires
// kUnboxedInt64 constants.
#if defined(ARCH_IS_64_BIT)
namespace {
struct FoldingResult {
  static FoldingResult NoFold() { return {false, 0}; }

  static FoldingResult FoldsTo(int64_t result) { return {true, result}; }

  bool should_fold;
  int64_t result;
};

static void ConstantPropagatorUnboxedOpTest(
    Thread* thread,
    int64_t lhs,
    int64_t rhs,
    std::function<Definition*(Definition*, Definition*, intptr_t)> make_op,
    bool redundant_phi,
    FoldingResult expected) {
  using compiler::BlockBuilder;

  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
  FlowGraphBuilderHelper H;

  // Add a variable into the scope which would provide static type for the
  // parameter.
  LocalVariable* v0_var =
      new LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                        String::Handle(Symbols::New(thread, "v0")),
                        AbstractType::ZoneHandle(Type::IntType()));
  v0_var->set_type_check_mode(LocalVariable::kTypeCheckedByCaller);
  H.flow_graph()->parsed_function().scope()->AddVariable(v0_var);

  // We are going to build the following graph:
  //
  // B0[graph_entry]
  // B1[function_entry]:
  //   v0 <- Parameter(0)
  //   if 1 == ${redundant_phi ? 1 : v0} then B2 else B3
  // B2:
  //   goto B4
  // B3:
  //   goto B4
  // B4:
  //   v1 <- Phi(lhs, ${redundant_phi ? -1 : lhs}) repr
  //   v2 <- Constant(rhs)
  //   v3 <- make_op(v1, v2)
  //   Return(v3)
  //
  // Note that we test both the case when v1 is fully redundant (has a single
  // live predecessor) and when it is not redundant but has a constant value.
  // These two cases are handled by different code paths - so we need to cover
  // them both to ensure that we properly insert any unbox operations
  // which are needed.

  auto b1 = H.flow_graph()->graph_entry()->normal_entry();
  auto b2 = H.TargetEntry();
  auto b3 = H.TargetEntry();
  auto b4 = H.JoinEntry();
  ReturnInstr* ret;

  {
    BlockBuilder builder(H.flow_graph(), b1);
    auto v0 = builder.AddParameter(/*index=*/0, /*param_offset=*/0,
                                   /*with_frame=*/true, kTagged);
    builder.AddBranch(
        new StrictCompareInstr(
            InstructionSource(), Token::kEQ_STRICT, new Value(H.IntConstant(1)),
            new Value(redundant_phi ? H.IntConstant(1) : v0),
            /*needs_number_check=*/false, S.GetNextDeoptId()),
        b2, b3);
  }

  {
    BlockBuilder builder(H.flow_graph(), b2);
    builder.AddInstruction(new GotoInstr(b4, S.GetNextDeoptId()));
  }

  {
    BlockBuilder builder(H.flow_graph(), b3);
    builder.AddInstruction(new GotoInstr(b4, S.GetNextDeoptId()));
  }

  PhiInstr* v1;
  Definition* op;
  {
    BlockBuilder builder(H.flow_graph(), b4);
    v1 = H.Phi(b4, {{b2, H.IntConstant(lhs)},
                    {b3, H.IntConstant(redundant_phi ? -1 : lhs)}});
    builder.AddPhi(v1);
    op = builder.AddDefinition(
        make_op(v1, H.IntConstant(rhs), S.GetNextDeoptId()));
    ret = builder.AddReturn(new Value(op));
  }

  H.FinishGraph();
  FlowGraphPrinter::PrintGraph("Before Optimization", H.flow_graph());
  FlowGraphTypePropagator::Propagate(H.flow_graph());
  FlowGraphPrinter::PrintGraph("After Propagate", H.flow_graph());
  // Force phi unboxing independent of heuristics.
  v1->set_representation(op->representation());
  H.flow_graph()->SelectRepresentations();
  FlowGraphPrinter::PrintGraph("After SelectRepresentations", H.flow_graph());
  H.flow_graph()->Canonicalize();
  FlowGraphPrinter::PrintGraph("After Canonicalize", H.flow_graph());
  if (!expected.should_fold) {
    EXPECT_PROPERTY(ret->value()->definition(),
                    it.IsBoxInteger() && it.RequiredInputRepresentation(0) ==
                                             op->representation());
  }

  ConstantPropagator::Optimize(H.flow_graph());
  FlowGraphPrinter::PrintGraph("After ConstantPropagator", H.flow_graph());

  // If |should_fold| then check that resulting graph is
  //
  //         Return(Constant(result))
  //
  // otherwise check that the graph is
  //
  //         Return(Box(op))
  //
  {
    auto ret_val = ret->value()->definition();
    if (expected.should_fold) {
      EXPECT_PROPERTY(ret_val,
                      it.IsConstant() && it.representation() == kTagged);
      EXPECT_EQ(expected.result,
                Integer::Cast(ret_val->AsConstant()->value()).AsInt64Value());
    } else {
      EXPECT_PROPERTY(ret_val,
                      it.IsBoxInteger() && it.RequiredInputRepresentation(0) ==
                                               op->representation());
      auto boxed_value = ret_val->AsBoxInteger()->value()->definition();
      EXPECT_PROPERTY(boxed_value, &it == op);
    }
  }
}

void ConstantPropagatorUnboxedOpTest(
    Thread* thread,
    int64_t lhs,
    int64_t rhs,
    std::function<Definition*(Definition*, Definition*, intptr_t)> make_op,
    FoldingResult expected) {
  ConstantPropagatorUnboxedOpTest(thread, lhs, rhs, make_op,
                                  /*redundant_phi=*/false, expected);
  ConstantPropagatorUnboxedOpTest(thread, lhs, rhs, make_op,
                                  /*redundant_phi=*/true, expected);
}

}  // namespace

// This test verifies that constant propagation respects representations when
// replacing unboxed operations.
ISOLATE_UNIT_TEST_CASE(ConstantPropagator_Regress35371) {
  auto make_int64_add = [](Definition* lhs, Definition* rhs,
                           intptr_t deopt_id) {
    return new BinaryInt64OpInstr(Token::kADD, new Value(lhs), new Value(rhs),
                                  deopt_id, Instruction::kNotSpeculative);
  };

  auto make_int32_add = [](Definition* lhs, Definition* rhs,
                           intptr_t deopt_id) {
    return new BinaryInt32OpInstr(Token::kADD, new Value(lhs), new Value(rhs),
                                  deopt_id);
  };

  auto make_int32_truncating_add = [](Definition* lhs, Definition* rhs,
                                      intptr_t deopt_id) {
    auto op = new BinaryInt32OpInstr(Token::kADD, new Value(lhs),
                                     new Value(rhs), deopt_id);
    op->mark_truncating();
    return op;
  };

  ConstantPropagatorUnboxedOpTest(thread, /*lhs=*/1, /*lhs=*/2, make_int64_add,
                                  FoldingResult::FoldsTo(3));
  ConstantPropagatorUnboxedOpTest(thread, /*lhs=*/kMaxInt64, /*lhs=*/1,
                                  make_int64_add,
                                  FoldingResult::FoldsTo(kMinInt64));

  ConstantPropagatorUnboxedOpTest(thread, /*lhs=*/1, /*lhs=*/2, make_int32_add,
                                  FoldingResult::FoldsTo(3));
  ConstantPropagatorUnboxedOpTest(thread, /*lhs=*/kMaxInt32 - 1, /*lhs=*/1,
                                  make_int32_add,
                                  FoldingResult::FoldsTo(kMaxInt32));

  // Overflow of int32 representation and operation is not marked as
  // truncating.
  ConstantPropagatorUnboxedOpTest(thread, /*lhs=*/kMaxInt32, /*lhs=*/1,
                                  make_int32_add, FoldingResult::NoFold());

  // Overflow of int32 representation and operation is marked as truncating.
  ConstantPropagatorUnboxedOpTest(thread, /*lhs=*/kMaxInt32, /*lhs=*/1,
                                  make_int32_truncating_add,
                                  FoldingResult::FoldsTo(kMinInt32));
}
#endif

void StrictCompareSentinel(Thread* thread,
                           bool negate,
                           bool non_sentinel_on_left) {
  const char* kScript = R"(
    late final int x = 4;
  )";
  Zone* const Z = Thread::Current()->zone();
  const auto& root_library = Library::CheckedHandle(Z, LoadTestScript(kScript));
  const auto& toplevel = Class::Handle(Z, root_library.toplevel_class());
  const auto& field_x = Field::Handle(
      Z, toplevel.LookupStaticField(String::Handle(Z, String::New("x"))));

  using compiler::BlockBuilder;
  CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
  FlowGraphBuilderHelper H;

  auto b1 = H.flow_graph()->graph_entry()->normal_entry();

  {
    BlockBuilder builder(H.flow_graph(), b1);
    auto v_load = builder.AddDefinition(new LoadStaticFieldInstr(
        field_x, {},
        /*calls_initializer=*/true, S.GetNextDeoptId()));
    auto v_sentinel = H.flow_graph()->GetConstant(Object::sentinel());
    Value* const left_value =
        non_sentinel_on_left ? new Value(v_load) : new Value(v_sentinel);
    Value* const right_value =
        non_sentinel_on_left ? new Value(v_sentinel) : new Value(v_load);
    auto v_compare = builder.AddDefinition(new StrictCompareInstr(
        {}, negate ? Token::kNE_STRICT : Token::kEQ_STRICT, left_value,
        right_value,
        /*needs_number_check=*/false, S.GetNextDeoptId()));
    builder.AddReturn(new Value(v_compare));
  }

  H.FinishGraph();

  FlowGraphPrinter::PrintGraph("Before TypePropagator", H.flow_graph());
  FlowGraphTypePropagator::Propagate(H.flow_graph());
  FlowGraphPrinter::PrintGraph("After TypePropagator", H.flow_graph());
  GrowableArray<BlockEntryInstr*> ignored;
  ConstantPropagator::Optimize(H.flow_graph());
  FlowGraphPrinter::PrintGraph("After ConstantPropagator", H.flow_graph());

  ReturnInstr* ret = nullptr;

  ILMatcher cursor(H.flow_graph(),
                   H.flow_graph()->graph_entry()->normal_entry(), true);
  RELEASE_ASSERT(cursor.TryMatch({
      kMatchAndMoveFunctionEntry,
      kMatchAndMoveLoadStaticField,
      // The StrictCompare instruction should be removed.
      {kMatchReturn, &ret},
  }));

  EXPECT_PROPERTY(ret, it.value()->BindsToConstant());
  EXPECT_PROPERTY(&ret->value()->BoundConstant(), it.IsBool());
  EXPECT_PROPERTY(&ret->value()->BoundConstant(),
                  Bool::Cast(it).value() == negate);
}

ISOLATE_UNIT_TEST_CASE(ConstantPropagator_StrictCompareEqualsSentinelLeft) {
  StrictCompareSentinel(thread, /*negate=*/false,
                        /*non_sentinel_on_left=*/true);
}

ISOLATE_UNIT_TEST_CASE(ConstantPropagator_StrictCompareEqualsSentinelRightt) {
  StrictCompareSentinel(thread, /*negate=*/false,
                        /*non_sentinel_on_left=*/false);
}

ISOLATE_UNIT_TEST_CASE(ConstantPropagator_StrictCompareNotEqualsSentinelLeft) {
  StrictCompareSentinel(thread, /*negate=*/true,
                        /*non_sentinel_on_left=*/true);
}

ISOLATE_UNIT_TEST_CASE(ConstantPropagator_StrictCompareNotEqualsSentinelRight) {
  StrictCompareSentinel(thread, /*negate=*/true,
                        /*non_sentinel_on_left=*/false);
}

}  // namespace dart
