// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/compiler/decompression-optimizer.h"

#include "test/unittests/compiler/graph-unittest.h"

namespace v8 {
namespace internal {
namespace compiler {

class DecompressionOptimizerTest : public GraphTest {
 public:
  DecompressionOptimizerTest()
      : GraphTest(),
        machine_(zone(), MachineType::PointerRepresentation(),
                 MachineOperatorBuilder::kNoFlags) {}
  ~DecompressionOptimizerTest() override = default;

 protected:
  void Reduce() {
    DecompressionOptimizer decompression_optimizer(zone(), graph(), common(),
                                                   machine());
    decompression_optimizer.Reduce();
  }

  MachineRepresentation CompressedMachRep(MachineRepresentation mach_rep) {
    if (mach_rep == MachineRepresentation::kTagged) {
      return MachineRepresentation::kCompressed;
    } else {
      DCHECK_EQ(mach_rep, MachineRepresentation::kTaggedPointer);
      return MachineRepresentation::kCompressedPointer;
    }
  }

  MachineRepresentation CompressedMachRep(MachineType type) {
    return CompressedMachRep(type.representation());
  }

  MachineRepresentation LoadMachRep(Node* node) {
    return LoadRepresentationOf(node->op()).representation();
  }
  StoreRepresentation CreateStoreRep(MachineType type) {
    return StoreRepresentation(type.representation(),
                               WriteBarrierKind::kFullWriteBarrier);
  }

  const MachineType types[2] = {MachineType::AnyTagged(),
                                MachineType::TaggedPointer()};

  const Handle<HeapNumber> heap_constants[15] = {
      factory()->NewHeapNumber(0.0),
      factory()->NewHeapNumber(-0.0),
      factory()->NewHeapNumber(11.2),
      factory()->NewHeapNumber(-11.2),
      factory()->NewHeapNumber(3.1415 + 1.4142),
      factory()->NewHeapNumber(3.1415 - 1.4142),
      factory()->NewHeapNumber(0x0000000000000000),
      factory()->NewHeapNumber(0x0000000000000001),
      factory()->NewHeapNumber(0x0000FFFFFFFF0000),
      factory()->NewHeapNumber(0x7FFFFFFFFFFFFFFF),
      factory()->NewHeapNumber(0x8000000000000000),
      factory()->NewHeapNumber(0x8000000000000001),
      factory()->NewHeapNumber(0x8000FFFFFFFF0000),
      factory()->NewHeapNumber(0x8FFFFFFFFFFFFFFF),
      factory()->NewHeapNumber(0xFFFFFFFFFFFFFFFF)};

  MachineOperatorBuilder* machine() { return &machine_; }

 private:
  MachineOperatorBuilder machine_;
};

// -----------------------------------------------------------------------------
// Direct Load into Store.

TEST_F(DecompressionOptimizerTest, DirectLoadStore) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);

  // Test for both AnyTagged and TaggedPointer.
  for (size_t i = 0; i < arraysize(types); ++i) {
    // Create the graph.
    Node* base_pointer = graph()->NewNode(machine()->Load(types[i]), object,
                                          index, effect, control);
    Node* value = graph()->NewNode(machine()->Load(types[i]), base_pointer,
                                   index, effect, control);
    graph()->SetEnd(graph()->NewNode(machine()->Store(CreateStoreRep(types[i])),
                                     object, index, value, effect, control));

    // Change the nodes, and test the change.
    Reduce();
    EXPECT_EQ(LoadMachRep(base_pointer), types[i].representation());
    EXPECT_EQ(LoadMachRep(value), CompressedMachRep(types[i]));
  }
}

// -----------------------------------------------------------------------------
// Word32 Operations.

TEST_F(DecompressionOptimizerTest, Word32EqualTwoDecompresses) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);

  // Test for both AnyTagged and TaggedPointer, for both loads.
  for (size_t i = 0; i < arraysize(types); ++i) {
    for (size_t j = 0; j < arraysize(types); ++j) {
      // Create the graph.
      Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                      effect, control);
      Node* load_2 = graph()->NewNode(machine()->Load(types[j]), object, index,
                                      effect, control);
      Node* equal = graph()->NewNode(machine()->Word32Equal(), load_1, load_2);
      graph()->SetEnd(equal);

      // Change the nodes, and test the change.
      Reduce();
      EXPECT_EQ(LoadMachRep(load_1), CompressedMachRep(types[i]));
      EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[j]));
    }
  }
}

TEST_F(DecompressionOptimizerTest, Word32EqualDecompressAndConstant) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);

  // Test for both AnyTagged and TaggedPointer.
  for (size_t i = 0; i < arraysize(types); ++i) {
    for (size_t j = 0; j < arraysize(heap_constants); ++j) {
      // Create the graph.
      Node* load = graph()->NewNode(machine()->Load(types[i]), object, index,
                                    effect, control);
      Node* constant =
          graph()->NewNode(common()->HeapConstant(heap_constants[j]));
      Node* equal = graph()->NewNode(machine()->Word32Equal(), load, constant);
      graph()->SetEnd(equal);

      // Change the nodes, and test the change.
      Reduce();
      EXPECT_EQ(LoadMachRep(load), CompressedMachRep(types[i]));
      EXPECT_EQ(constant->opcode(), IrOpcode::kCompressedHeapConstant);
    }
  }
}

TEST_F(DecompressionOptimizerTest, Word32AndSmiCheck) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);

  // Test for both AnyTagged and TaggedPointer.
  for (size_t i = 0; i < arraysize(types); ++i) {
    // Create the graph.
    Node* load = graph()->NewNode(machine()->Load(types[i]), object, index,
                                  effect, control);
    Node* smi_tag_mask = graph()->NewNode(common()->Int32Constant(kSmiTagMask));
    Node* word32_and =
        graph()->NewNode(machine()->Word32And(), load, smi_tag_mask);
    Node* smi_tag = graph()->NewNode(common()->Int32Constant(kSmiTag));
    graph()->SetEnd(
        graph()->NewNode(machine()->Word32Equal(), word32_and, smi_tag));
    // Change the nodes, and test the change.
    Reduce();
    EXPECT_EQ(LoadMachRep(load), CompressedMachRep(types[i]));
  }
}

TEST_F(DecompressionOptimizerTest, Word32ShlSmiTag) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);

  // Test only for AnyTagged, since TaggedPointer can't be Smi tagged.
  // Create the graph.
  Node* load = graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
                                object, index, effect, control);
  Node* smi_shift_bits =
      graph()->NewNode(common()->Int32Constant(kSmiShiftSize + kSmiTagSize));
  Node* word32_shl =
      graph()->NewNode(machine()->Word32Shl(), load, smi_shift_bits);
  graph()->SetEnd(
      graph()->NewNode(machine()->BitcastWord32ToWord64(), word32_shl));
  // Change the nodes, and test the change.
  Reduce();
  EXPECT_EQ(LoadMachRep(load), CompressedMachRep(MachineType::AnyTagged()));
}

TEST_F(DecompressionOptimizerTest, Word32SarSmiUntag) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);

  // Test only for AnyTagged, since TaggedPointer can't be Smi tagged.
  // Create the graph.
  Node* load = graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
                                object, index, effect, control);
  Node* truncation = graph()->NewNode(machine()->TruncateInt64ToInt32(), load);
  Node* smi_shift_bits =
      graph()->NewNode(common()->Int32Constant(kSmiShiftSize + kSmiTagSize));
  Node* word32_sar =
      graph()->NewNode(machine()->Word32Sar(), truncation, smi_shift_bits);
  graph()->SetEnd(
      graph()->NewNode(machine()->ChangeInt32ToInt64(), word32_sar));
  // Change the nodes, and test the change.
  Reduce();
  EXPECT_EQ(LoadMachRep(load), CompressedMachRep(MachineType::AnyTagged()));
}

// -----------------------------------------------------------------------------
// FrameState and TypedStateValues interaction.

TEST_F(DecompressionOptimizerTest, TypedStateValues) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  const int number_of_inputs = 2;
  const ZoneVector<MachineType>* types_for_state_values =
      graph()->zone()->New<ZoneVector<MachineType>>(number_of_inputs,
                                                    graph()->zone());
  SparseInputMask dense = SparseInputMask::Dense();

  // Test for both AnyTagged and TaggedPointer.
  for (size_t i = 0; i < arraysize(types); ++i) {
    for (size_t j = 0; j < arraysize(heap_constants); ++j) {
      // Create the graph.
      Node* load = graph()->NewNode(machine()->Load(types[i]), object, index,
                                    effect, control);
      Node* constant_1 =
          graph()->NewNode(common()->HeapConstant(heap_constants[j]));
      Node* typed_state_values = graph()->NewNode(
          common()->TypedStateValues(types_for_state_values, dense), load,
          constant_1);
      Node* constant_2 =
          graph()->NewNode(common()->HeapConstant(heap_constants[j]));
      graph()->SetEnd(graph()->NewNode(
          common()->FrameState(BailoutId::None(),
                               OutputFrameStateCombine::Ignore(), nullptr),
          typed_state_values, typed_state_values, typed_state_values,
          constant_2, UndefinedConstant(), graph()->start()));

      // Change the nodes, and test the change.
      Reduce();
      EXPECT_EQ(LoadMachRep(load), CompressedMachRep(types[i]));
      EXPECT_EQ(constant_1->opcode(), IrOpcode::kCompressedHeapConstant);
      EXPECT_EQ(constant_2->opcode(), IrOpcode::kCompressedHeapConstant);
    }
  }
}

// -----------------------------------------------------------------------------
// Phi

TEST_F(DecompressionOptimizerTest, PhiDecompressOrNot) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  const int number_of_inputs = 2;

  // Test for both AnyTagged and TaggedPointer.
  for (size_t i = 0; i < arraysize(types); ++i) {
    for (size_t j = 0; j < arraysize(heap_constants); ++j) {
      // Create the graph.
      // Base pointer
      Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                      effect, control);
      Node* constant_1 =
          graph()->NewNode(common()->HeapConstant(heap_constants[j]));
      Node* phi_1 = graph()->NewNode(
          common()->Phi(types[i].representation(), number_of_inputs), load_1,
          constant_1, control);

      // Value
      Node* load_2 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                      effect, control);
      Node* constant_2 =
          graph()->NewNode(common()->HeapConstant(heap_constants[j]));
      Node* phi_2 = graph()->NewNode(
          common()->Phi(types[i].representation(), number_of_inputs), load_2,
          constant_2, control);

      graph()->SetEnd(
          graph()->NewNode(machine()->Store(CreateStoreRep(types[i])), phi_1,
                           index, phi_2, effect, control));

      // Change the nodes, and test the change.
      Reduce();
      // Base pointer should not be compressed.
      EXPECT_EQ(LoadMachRep(load_1), types[i].representation());
      EXPECT_EQ(constant_1->opcode(), IrOpcode::kHeapConstant);
      EXPECT_EQ(PhiRepresentationOf(phi_1->op()), types[i].representation());
      // Value should be compressed.
      EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[i]));
      EXPECT_EQ(constant_2->opcode(), IrOpcode::kCompressedHeapConstant);
      EXPECT_EQ(PhiRepresentationOf(phi_2->op()), CompressedMachRep(types[i]));
    }
  }
}

TEST_F(DecompressionOptimizerTest, CascadingPhi) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  const int number_of_inputs = 2;

  // Test for both AnyTagged and TaggedPointer.
  for (size_t i = 0; i < arraysize(types); ++i) {
    // Create the graph.
    Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                    effect, control);
    Node* load_2 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                    effect, control);
    Node* load_3 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                    effect, control);
    Node* load_4 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                    effect, control);

    Node* phi_1 = graph()->NewNode(
        common()->Phi(types[i].representation(), number_of_inputs), load_1,
        load_2, control);
    Node* phi_2 = graph()->NewNode(
        common()->Phi(types[i].representation(), number_of_inputs), load_3,
        load_4, control);

    Node* final_phi = graph()->NewNode(
        common()->Phi(types[i].representation(), number_of_inputs), phi_1,
        phi_2, control);

    // Value
    graph()->SetEnd(final_phi);
    // Change the nodes, and test the change.
    Reduce();
    // Loads are all compressed
    EXPECT_EQ(LoadMachRep(load_1), CompressedMachRep(types[i]));
    EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[i]));
    EXPECT_EQ(LoadMachRep(load_3), CompressedMachRep(types[i]));
    EXPECT_EQ(LoadMachRep(load_4), CompressedMachRep(types[i]));
    // Phis too
    EXPECT_EQ(PhiRepresentationOf(phi_1->op()), CompressedMachRep(types[i]));
    EXPECT_EQ(PhiRepresentationOf(phi_2->op()), CompressedMachRep(types[i]));
    EXPECT_EQ(PhiRepresentationOf(final_phi->op()),
              CompressedMachRep(types[i]));
  }
}

TEST_F(DecompressionOptimizerTest, PhiWithOneCompressedAndOneTagged) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  const int number_of_inputs = 2;

  // Test for both AnyTagged and TaggedPointer.
  for (size_t i = 0; i < arraysize(types); ++i) {
    for (size_t j = 0; j < arraysize(heap_constants); ++j) {
      // Create the graph.
      // Base pointer in load_2, and phi input for value
      Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                      effect, control);

      // load_2 blocks load_1 from being compressed.
      Node* load_2 = graph()->NewNode(machine()->Load(types[i]), load_1, index,
                                      effect, control);
      Node* phi = graph()->NewNode(
          common()->Phi(types[i].representation(), number_of_inputs), load_1,
          load_2, control);

      graph()->SetEnd(
          graph()->NewNode(machine()->Store(CreateStoreRep(types[i])), object,
                           index, phi, effect, control));

      // Change the nodes, and test the change.
      Reduce();
      EXPECT_EQ(LoadMachRep(load_1), types[i].representation());
      EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[i]));
      EXPECT_EQ(PhiRepresentationOf(phi->op()), CompressedMachRep(types[i]));
    }
  }
}

// -----------------------------------------------------------------------------
// Int cases.

TEST_F(DecompressionOptimizerTest, Int32LessThanOrEqualFromSpeculative) {
  // This case tests for what SpeculativeNumberLessThanOrEqual is lowered to.
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);

  // Test only for AnyTagged, since TaggedPointer can't be a Smi.
  // Create the graph.
  Node* load = graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
                                object, index, effect, control);
  Node* constant = graph()->NewNode(common()->Int64Constant(5));
  graph()->SetEnd(
      graph()->NewNode(machine()->Int32LessThanOrEqual(), load, constant));
  // Change the nodes, and test the change.
  Reduce();
  EXPECT_EQ(LoadMachRep(load), CompressedMachRep(MachineType::AnyTagged()));
}

// -----------------------------------------------------------------------------
// Bitcast cases.

TEST_F(DecompressionOptimizerTest, BitcastTaggedToWord) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);

  // Test for both AnyTagged and TaggedPointer, for both loads.
  for (size_t i = 0; i < arraysize(types); ++i) {
    for (size_t j = 0; j < arraysize(types); ++j) {
      // Create the graph.
      Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                      effect, control);
      Node* bitcast_1 = graph()->NewNode(machine()->BitcastTaggedToWord(),
                                         load_1, effect, control);
      Node* load_2 = graph()->NewNode(machine()->Load(types[j]), object, index,
                                      effect, control);
      Node* bitcast_2 = graph()->NewNode(machine()->BitcastTaggedToWord(),
                                         load_2, effect, control);
      Node* equal =
          graph()->NewNode(machine()->Word32Equal(), bitcast_1, bitcast_2);
      graph()->SetEnd(equal);

      // Change the nodes, and test the change.
      Reduce();
      EXPECT_EQ(LoadMachRep(load_1), CompressedMachRep(types[i]));
      EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[j]));
    }
  }
}

TEST_F(DecompressionOptimizerTest, BitcastTaggedToWordForTagAndSmiBits) {
  // Define variables.
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);

  // Test for both AnyTagged and TaggedPointer, for both loads.
  for (size_t i = 0; i < arraysize(types); ++i) {
    for (size_t j = 0; j < arraysize(types); ++j) {
      // Create the graph.
      Node* load_1 = graph()->NewNode(machine()->Load(types[i]), object, index,
                                      effect, control);
      Node* bitcast_1 = graph()->NewNode(
          machine()->BitcastTaggedToWordForTagAndSmiBits(), load_1);
      Node* load_2 = graph()->NewNode(machine()->Load(types[j]), object, index,
                                      effect, control);
      Node* bitcast_2 = graph()->NewNode(
          machine()->BitcastTaggedToWordForTagAndSmiBits(), load_2);
      Node* equal =
          graph()->NewNode(machine()->Word32Equal(), bitcast_1, bitcast_2);
      graph()->SetEnd(equal);

      // Change the nodes, and test the change.
      Reduce();
      EXPECT_EQ(LoadMachRep(load_1), CompressedMachRep(types[i]));
      EXPECT_EQ(LoadMachRep(load_2), CompressedMachRep(types[j]));
    }
  }
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
