// 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-elimination.h"
#include "src/compiler/simplified-operator.h"
#include "test/unittests/compiler/graph-reducer-unittest.h"
#include "test/unittests/compiler/graph-unittest.h"
#include "test/unittests/compiler/node-test-utils.h"

using testing::StrictMock;

namespace v8 {
namespace internal {
namespace compiler {

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

 protected:
  Reduction Reduce(Node* node) {
    StrictMock<MockAdvancedReducerEditor> editor;
    DecompressionElimination decompression_elimination(&editor, graph(),
                                                       machine(), common());
    return decompression_elimination.Reduce(node);
  }
  MachineOperatorBuilder* machine() { return &machine_; }
  SimplifiedOperatorBuilder* simplified() { return &simplified_; }

 private:
  MachineOperatorBuilder machine_;
  SimplifiedOperatorBuilder simplified_;
};

// -----------------------------------------------------------------------------
// Direct Decompression & Compression

TEST_F(DecompressionEliminationTest, BasicDecompressionCompression) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // Define variables
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  ElementAccess const access = {kTaggedBase, kTaggedSize, Type::Any(),
                                MachineType::AnyTagged(), kNoWriteBarrier};

  // Create the graph
  Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
                                index, effect, control);
  Node* changeToTagged =
      graph()->NewNode(machine()->ChangeCompressedToTagged(), load);
  Node* changeToCompressed =
      graph()->NewNode(machine()->ChangeTaggedToCompressed(), changeToTagged);
  effect = graph()->NewNode(simplified()->StoreElement(access), object, index,
                            changeToCompressed, effect, control);

  // Reduce
  Reduction r = Reduce(changeToCompressed);
  ASSERT_TRUE(r.Changed());
  EXPECT_EQ(load, r.replacement());
}

TEST_F(DecompressionEliminationTest, BasicDecompressionCompressionSigned) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // Define variables
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  ElementAccess const access = {kTaggedBase, kTaggedSize, Type::Any(),
                                MachineType::TaggedSigned(), kNoWriteBarrier};

  // Create the graph
  Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
                                index, effect, control);
  Node* changeToTagged =
      graph()->NewNode(machine()->ChangeCompressedSignedToTaggedSigned(), load);
  Node* changeToCompressed = graph()->NewNode(
      machine()->ChangeTaggedSignedToCompressedSigned(), changeToTagged);
  effect = graph()->NewNode(simplified()->StoreElement(access), object, index,
                            changeToCompressed, effect, control);

  // Reduce
  Reduction r = Reduce(changeToCompressed);
  ASSERT_TRUE(r.Changed());
  EXPECT_EQ(load, r.replacement());
}

TEST_F(DecompressionEliminationTest, BasicDecompressionCompressionPointer) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // Define variables
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  ElementAccess const access = {kTaggedBase, kTaggedSize, Type::Any(),
                                MachineType::TaggedPointer(), kNoWriteBarrier};

  // Create the graph
  Node* load = graph()->NewNode(simplified()->LoadElement(access), object,
                                index, effect, control);
  Node* changeToTagged = graph()->NewNode(
      machine()->ChangeCompressedPointerToTaggedPointer(), load);
  Node* changeToCompressed = graph()->NewNode(
      machine()->ChangeTaggedPointerToCompressedPointer(), changeToTagged);
  effect = graph()->NewNode(simplified()->StoreElement(access), object, index,
                            changeToCompressed, effect, control);

  // Reduce
  Reduction r = Reduce(changeToCompressed);
  ASSERT_TRUE(r.Changed());
  EXPECT_EQ(load, r.replacement());
}

// -----------------------------------------------------------------------------
// Direct Decompression & Compression - border cases

// For example, if we are lowering a CheckedCompressedToTaggedPointer in the
// effect linearization phase we will change that to
// ChangeCompressedPointerToTaggedPointer. Then, we might end up with a chain of
// Parent <- ChangeCompressedPointerToTaggedPointer <- ChangeTaggedToCompressed
// <- Child.
// Similarly, we have cases with Signed instead of pointer.
// The following border case tests will test that the functionality is robust
// enough to handle that.

TEST_F(DecompressionEliminationTest,
       BasicDecompressionCompressionBorderCaseSigned) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // Define variables
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  ElementAccess const loadAccess = {kTaggedBase, kTaggedSize, Type::Any(),
                                    MachineType::AnyTagged(), kNoWriteBarrier};
  ElementAccess const storeAccess = {kTaggedBase, kTaggedSize, Type::Any(),
                                     MachineType::TaggedSigned(),
                                     kNoWriteBarrier};

  // Create the graph
  Node* load = graph()->NewNode(simplified()->LoadElement(loadAccess), object,
                                index, effect, control);
  Node* changeToTagged =
      graph()->NewNode(machine()->ChangeCompressedSignedToTaggedSigned(), load);
  Node* changeToCompressed =
      graph()->NewNode(machine()->ChangeTaggedToCompressed(), changeToTagged);
  effect = graph()->NewNode(simplified()->StoreElement(storeAccess), object,
                            index, changeToCompressed, effect, control);

  // Reduce
  Reduction r = Reduce(changeToCompressed);
  ASSERT_TRUE(r.Changed());
  EXPECT_EQ(load, r.replacement());
}

TEST_F(DecompressionEliminationTest,
       BasicDecompressionCompressionBorderCasePointer) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // Define variables
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  ElementAccess const loadAccess = {kTaggedBase, kTaggedSize, Type::Any(),
                                    MachineType::AnyTagged(), kNoWriteBarrier};
  ElementAccess const storeAccess = {kTaggedBase, kTaggedSize, Type::Any(),
                                     MachineType::TaggedPointer(),
                                     kNoWriteBarrier};

  // Create the graph
  Node* load = graph()->NewNode(simplified()->LoadElement(loadAccess), object,
                                index, effect, control);
  Node* changeToTagged = graph()->NewNode(
      machine()->ChangeCompressedPointerToTaggedPointer(), load);
  Node* changeToCompressed =
      graph()->NewNode(machine()->ChangeTaggedToCompressed(), changeToTagged);
  effect = graph()->NewNode(simplified()->StoreElement(storeAccess), object,
                            index, changeToCompressed, effect, control);

  // Reduce
  Reduction r = Reduce(changeToCompressed);
  ASSERT_TRUE(r.Changed());
  EXPECT_EQ(load, r.replacement());
}

// We also have cases of ChangeCompressedToTagged <-
// ChangeTaggedPointerToCompressedPointer, where the
// ChangeTaggedPointerToCompressedPointer was introduced while lowering a
// NewConsString on effect control linearizer

TEST_F(DecompressionEliminationTest,
       BasicDecompressionCompressionBorderCasePointerDecompression) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // Define variables
  Node* const control = graph()->start();
  Node* object = Parameter(Type::Any(), 0);
  Node* effect = graph()->start();
  Node* index = Parameter(Type::UnsignedSmall(), 1);
  ElementAccess const loadAccess = {kTaggedBase, kTaggedSize, Type::Any(),
                                    MachineType::TaggedPointer(),
                                    kNoWriteBarrier};
  ElementAccess const storeAccess = {kTaggedBase, kTaggedSize, Type::Any(),
                                     MachineType::AnyTagged(), kNoWriteBarrier};

  // Create the graph
  Node* load = graph()->NewNode(simplified()->LoadElement(loadAccess), object,
                                index, effect, control);
  Node* changeToTagged = graph()->NewNode(
      machine()->ChangeCompressedPointerToTaggedPointer(), load);
  Node* changeToCompressed =
      graph()->NewNode(machine()->ChangeTaggedToCompressed(), changeToTagged);
  effect = graph()->NewNode(simplified()->StoreElement(storeAccess), object,
                            index, changeToCompressed, effect, control);

  // Reduce
  Reduction r = Reduce(changeToCompressed);
  ASSERT_TRUE(r.Changed());
  EXPECT_EQ(load, r.replacement());
}

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

TEST_F(DecompressionEliminationTest, PhiOneDecompress) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // 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 = 1;

  const Operator* decompression_ops[] = {
      machine()->ChangeCompressedToTagged(),
      machine()->ChangeCompressedSignedToTaggedSigned(),
      machine()->ChangeCompressedPointerToTaggedPointer()};

  const ElementAccess element_accesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyCompressed(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
       kNoWriteBarrier}};

  const IrOpcode::Value opcodes[] = {
      IrOpcode::kChangeCompressedToTagged,
      IrOpcode::kChangeCompressedSignedToTaggedSigned,
      IrOpcode::kChangeCompressedPointerToTaggedPointer};

  ASSERT_EQ(arraysize(decompression_ops), arraysize(element_accesses));
  ASSERT_EQ(arraysize(opcodes), arraysize(element_accesses));

  // For every access
  for (size_t i = 0; i < arraysize(element_accesses); ++i) {
    // Create the graph
    Node* load =
        graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
                         index, effect, control);
    Node* change_to_tagged = graph()->NewNode(decompression_ops[i], load);
    Node* phi = graph()->NewNode(
        common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
        change_to_tagged, control);

    // Reduce
    Reduction r = Reduce(phi);
    ASSERT_TRUE(r.Changed());
    EXPECT_EQ(opcodes[i], r.replacement()->opcode());
  }
}

TEST_F(DecompressionEliminationTest, PhiThreeDecompressSameRepresentation) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // 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 = 3;

  const Operator* decompression_ops[] = {
      machine()->ChangeCompressedToTagged(),
      machine()->ChangeCompressedSignedToTaggedSigned(),
      machine()->ChangeCompressedPointerToTaggedPointer()};

  const ElementAccess element_accesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyCompressed(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedPointer(),
       kNoWriteBarrier}};

  const IrOpcode::Value opcodes[] = {
      IrOpcode::kChangeCompressedToTagged,
      IrOpcode::kChangeCompressedSignedToTaggedSigned,
      IrOpcode::kChangeCompressedPointerToTaggedPointer};

  ASSERT_EQ(arraysize(decompression_ops), arraysize(element_accesses));
  ASSERT_EQ(arraysize(opcodes), arraysize(element_accesses));

  // For every access
  for (size_t i = 0; i < arraysize(element_accesses); ++i) {
    // Create the graph
    Node* load1 =
        graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
                         index, effect, control);
    Node* load2 =
        graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
                         index, effect, control);
    Node* load3 =
        graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
                         index, effect, control);
    Node* change_to_tagged1 = graph()->NewNode(decompression_ops[i], load1);
    Node* change_to_tagged2 = graph()->NewNode(decompression_ops[i], load2);
    Node* change_to_tagged3 = graph()->NewNode(decompression_ops[i], load3);

    Node* phi = graph()->NewNode(
        common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
        change_to_tagged1, change_to_tagged2, change_to_tagged3, control);

    // Reduce
    Reduction r = Reduce(phi);
    ASSERT_TRUE(r.Changed());
    EXPECT_EQ(opcodes[i], r.replacement()->opcode());
  }
}

TEST_F(DecompressionEliminationTest, PhiThreeDecompressOneAnyRepresentation) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // 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 = 3;

  const Operator* decompression_ops[] = {
      machine()->ChangeCompressedSignedToTaggedSigned(),
      machine()->ChangeCompressedPointerToTaggedPointer()};

  const ElementAccess element_accesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedPointer(),
       kNoWriteBarrier}};

  const ElementAccess any_access = {kTaggedBase, kTaggedSize, Type::Any(),
                                    MachineType::AnyCompressed(),
                                    kNoWriteBarrier};

  ASSERT_EQ(arraysize(decompression_ops), arraysize(element_accesses));

  // For every access
  for (size_t i = 0; i < arraysize(element_accesses); ++i) {
    // Create the graph
    Node* load1 =
        graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
                         index, effect, control);
    Node* load2 =
        graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
                         index, effect, control);
    // Note that load3 loads a CompressedAny instead of element_accesses[i]
    Node* load3 = graph()->NewNode(simplified()->LoadElement(any_access),
                                   object, index, effect, control);
    Node* change_to_tagged1 = graph()->NewNode(decompression_ops[i], load1);
    Node* change_to_tagged2 = graph()->NewNode(decompression_ops[i], load2);
    Node* change_to_tagged3 =
        graph()->NewNode(machine()->ChangeCompressedToTagged(), load3);

    Node* phi = graph()->NewNode(
        common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
        change_to_tagged1, change_to_tagged2, change_to_tagged3, control);

    // Reduce
    Reduction r = Reduce(phi);
    ASSERT_TRUE(r.Changed());
    EXPECT_EQ(IrOpcode::kChangeCompressedToTagged, r.replacement()->opcode());
  }
}

TEST_F(DecompressionEliminationTest, PhiThreeInputsOneNotDecompressed) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // 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 = 3;

  const Operator* decompression_ops[] = {
      machine()->ChangeCompressedToTagged(),
      machine()->ChangeCompressedSignedToTaggedSigned(),
      machine()->ChangeCompressedPointerToTaggedPointer()};

  const ElementAccess element_accesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyCompressed(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::CompressedPointer(),
       kNoWriteBarrier}};

  const IrOpcode::Value opcodes[] = {
      IrOpcode::kChangeCompressedToTagged,
      IrOpcode::kChangeCompressedSignedToTaggedSigned,
      IrOpcode::kChangeCompressedPointerToTaggedPointer};

  ASSERT_EQ(arraysize(decompression_ops), arraysize(element_accesses));
  ASSERT_EQ(arraysize(opcodes), arraysize(element_accesses));

  // For every access
  for (size_t i = 0; i < arraysize(element_accesses); ++i) {
    // Create the graph
    Node* load1 =
        graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
                         index, effect, control);
    Node* load2 =
        graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
                         index, effect, control);
    Node* load3 =
        graph()->NewNode(simplified()->LoadElement(element_accesses[i]), object,
                         index, effect, control);
    Node* change_to_tagged1 = graph()->NewNode(decompression_ops[i], load1);
    Node* change_to_tagged2 = graph()->NewNode(decompression_ops[i], load2);

    Node* phi = graph()->NewNode(
        common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
        change_to_tagged1, change_to_tagged2, load3, control);

    // Reduce
    Reduction r = Reduce(phi);
    ASSERT_FALSE(r.Changed());
  }
}

// In the case of having one decompress Signed and one Pointer, we have to
// generate the conservative decompress any after the Phi.
TEST_F(DecompressionEliminationTest, PhiTwoDecompressesOneSignedOnePointer) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // 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 ElementAccess signed_access = {kTaggedBase, kTaggedSize, Type::Any(),
                                       MachineType::CompressedSigned(),
                                       kNoWriteBarrier};
  const ElementAccess pointer_access = {kTaggedBase, kTaggedSize, Type::Any(),
                                        MachineType::CompressedPointer(),
                                        kNoWriteBarrier};

  // Create the graph
  Node* load1 = graph()->NewNode(simplified()->LoadElement(signed_access),
                                 object, index, effect, control);
  Node* load2 = graph()->NewNode(simplified()->LoadElement(pointer_access),
                                 object, index, effect, control);
  Node* change_to_tagged1 = graph()->NewNode(
      machine()->ChangeCompressedSignedToTaggedSigned(), load1);
  Node* change_to_tagged2 = graph()->NewNode(
      machine()->ChangeCompressedPointerToTaggedPointer(), load2);

  Node* phi = graph()->NewNode(
      common()->Phi(MachineRepresentation::kTagged, number_of_inputs),
      change_to_tagged1, change_to_tagged2, control);

  // Reduce
  Reduction r = Reduce(phi);
  ASSERT_TRUE(r.Changed());
  EXPECT_EQ(IrOpcode::kChangeCompressedToTagged, r.replacement()->opcode());
}

// -----------------------------------------------------------------------------
// TypedStateValues

TEST_F(DecompressionEliminationTest, TypedStateValuesOneDecompress) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // 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 numberOfInputs = 1;
  const ZoneVector<MachineType>* types =
      new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
          ZoneVector<MachineType>(numberOfInputs, graph()->zone());
  SparseInputMask dense = SparseInputMask::Dense();

  const ElementAccess ElementAccesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
       kNoWriteBarrier}};

  // For every access
  for (size_t i = 0; i < arraysize(ElementAccesses); ++i) {
    // Create the graph
    Node* load = graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]),
                                  object, index, effect, control);
    Node* changeToTagged = graph()->NewNode(
        machine()->ChangeCompressedPointerToTaggedPointer(), load);
    Node* typedStateValuesOneDecompress = graph()->NewNode(
        common()->TypedStateValues(types, dense), changeToTagged);

    // Reduce
    StrictMock<MockAdvancedReducerEditor> editor;
    DecompressionElimination decompression_elimination(&editor, graph(),
                                                       machine(), common());
    Reduction r =
        decompression_elimination.Reduce(typedStateValuesOneDecompress);
    ASSERT_TRUE(r.Changed());
  }
}

TEST_F(DecompressionEliminationTest, TypedStateValuesTwoDecompresses) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // 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 numberOfInputs = 3;
  const ZoneVector<MachineType>* types =
      new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
          ZoneVector<MachineType>(numberOfInputs, graph()->zone());
  SparseInputMask dense = SparseInputMask::Dense();
  const ElementAccess ElementAccesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
       kNoWriteBarrier}};

  // For every access
  for (size_t i = 0; i < arraysize(ElementAccesses); ++i) {
    // Create the graph
    Node* load1 =
        graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
                         index, effect, control);
    Node* changeToTagged1 = graph()->NewNode(
        machine()->ChangeCompressedPointerToTaggedPointer(), load1);
    Node* load2 =
        graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
                         index, effect, control);
    Node* changeToTagged2 = graph()->NewNode(
        machine()->ChangeCompressedPointerToTaggedPointer(), load2);
    Node* typedStateValuesOneDecompress =
        graph()->NewNode(common()->TypedStateValues(types, dense),
                         changeToTagged1, load1, changeToTagged2);

    // Reduce
    StrictMock<MockAdvancedReducerEditor> editor;
    DecompressionElimination decompression_elimination(&editor, graph(),
                                                       machine(), common());
    Reduction r =
        decompression_elimination.Reduce(typedStateValuesOneDecompress);
    ASSERT_TRUE(r.Changed());
  }
}

TEST_F(DecompressionEliminationTest, TypedStateValuesAllDecompresses) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // 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 numberOfInputs = 3;
  const ZoneVector<MachineType>* types =
      new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
          ZoneVector<MachineType>(numberOfInputs, graph()->zone());
  SparseInputMask dense = SparseInputMask::Dense();
  const ElementAccess ElementAccesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
       kNoWriteBarrier}};

  // For every access
  for (size_t i = 0; i < arraysize(ElementAccesses); ++i) {
    // Create the graph
    Node* load1 =
        graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
                         index, effect, control);
    Node* changeToTagged1 = graph()->NewNode(
        machine()->ChangeCompressedPointerToTaggedPointer(), load1);
    Node* load2 =
        graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
                         index, effect, control);
    Node* changeToTagged2 = graph()->NewNode(
        machine()->ChangeCompressedPointerToTaggedPointer(), load2);
    Node* load3 =
        graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]), object,
                         index, effect, control);
    Node* changeToTagged3 = graph()->NewNode(
        machine()->ChangeCompressedPointerToTaggedPointer(), load3);
    Node* typedStateValuesOneDecompress =
        graph()->NewNode(common()->TypedStateValues(types, dense),
                         changeToTagged1, changeToTagged2, changeToTagged3);

    // Reduce
    StrictMock<MockAdvancedReducerEditor> editor;
    DecompressionElimination decompression_elimination(&editor, graph(),
                                                       machine(), common());
    Reduction r =
        decompression_elimination.Reduce(typedStateValuesOneDecompress);
    ASSERT_TRUE(r.Changed());
  }
}

TEST_F(DecompressionEliminationTest, TypedStateValuesNoDecompresses) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

  // 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 numberOfInputs = 3;
  const ZoneVector<MachineType>* types =
      new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
          ZoneVector<MachineType>(numberOfInputs, graph()->zone());
  SparseInputMask dense = SparseInputMask::Dense();
  const ElementAccess ElementAccesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
       kNoWriteBarrier}};

  // For every access
  for (size_t i = 0; i < arraysize(ElementAccesses); ++i) {
    // Create the graph
    Node* load = graph()->NewNode(simplified()->LoadElement(ElementAccesses[i]),
                                  object, index, effect, control);
    Node* typedStateValuesOneDecompress = graph()->NewNode(
        common()->TypedStateValues(types, dense), load, load, load);

    // Reduce
    StrictMock<MockAdvancedReducerEditor> editor;
    DecompressionElimination decompression_elimination(&editor, graph(),
                                                       machine(), common());
    Reduction r =
        decompression_elimination.Reduce(typedStateValuesOneDecompress);
    ASSERT_FALSE(r.Changed());
  }
}

// -----------------------------------------------------------------------------
// Word64Equal comparison of two decompressions

TEST_F(DecompressionEliminationTest, TwoDecompressionWord64Equal) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

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

  const Operator* DecompressionOps[] = {
      machine()->ChangeCompressedToTagged(),
      machine()->ChangeCompressedSignedToTaggedSigned(),
      machine()->ChangeCompressedPointerToTaggedPointer()};

  const ElementAccess ElementAccesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
       kNoWriteBarrier}};

  ASSERT_EQ(arraysize(DecompressionOps), arraysize(ElementAccesses));

  // For every decompression (lhs)
  for (size_t j = 0; j < arraysize(DecompressionOps); ++j) {
    // For every decompression (rhs)
    for (size_t k = 0; k < arraysize(DecompressionOps); ++k) {
      // Create the graph
      Node* load1 =
          graph()->NewNode(simplified()->LoadElement(ElementAccesses[j]),
                           object, index, effect, control);
      Node* changeToTagged1 = graph()->NewNode(DecompressionOps[j], load1);
      Node* load2 =
          graph()->NewNode(simplified()->LoadElement(ElementAccesses[k]),
                           object, index, effect, control);
      Node* changeToTagged2 = graph()->NewNode(DecompressionOps[j], load2);
      Node* comparison = graph()->NewNode(machine()->Word64Equal(),
                                          changeToTagged1, changeToTagged2);
      // Reduce
      Reduction r = Reduce(comparison);
      ASSERT_TRUE(r.Changed());
      EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kWord32Equal);
    }
  }
}

// -----------------------------------------------------------------------------
// Word64Equal comparison of two decompressions, where lhs == rhs

TEST_F(DecompressionEliminationTest, TwoDecompressionWord64EqualSameInput) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

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

  const Operator* DecompressionOps[] = {
      machine()->ChangeCompressedToTagged(),
      machine()->ChangeCompressedSignedToTaggedSigned(),
      machine()->ChangeCompressedPointerToTaggedPointer()};

  const ElementAccess ElementAccesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
       kNoWriteBarrier}};

  ASSERT_EQ(arraysize(DecompressionOps), arraysize(ElementAccesses));

  // For every decompression (same for lhs and rhs)
  for (size_t j = 0; j < arraysize(DecompressionOps); ++j) {
    // Create the graph
    Node* load = graph()->NewNode(simplified()->LoadElement(ElementAccesses[j]),
                                  object, index, effect, control);
    Node* changeToTagged = graph()->NewNode(DecompressionOps[j], load);
    Node* comparison = graph()->NewNode(machine()->Word64Equal(),
                                        changeToTagged, changeToTagged);
    // Reduce
    Reduction r = Reduce(comparison);
    ASSERT_TRUE(r.Changed());
    EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kWord32Equal);
  }
}

// -----------------------------------------------------------------------------
// Word64Equal comparison of decompress and a constant

TEST_F(DecompressionEliminationTest, DecompressionConstantWord64Equal) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

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

  const Operator* DecompressionOps[] = {
      machine()->ChangeCompressedToTagged(),
      machine()->ChangeCompressedSignedToTaggedSigned(),
      machine()->ChangeCompressedPointerToTaggedPointer()};

  const ElementAccess ElementAccesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
       kNoWriteBarrier}};

  ASSERT_EQ(arraysize(DecompressionOps), arraysize(ElementAccesses));

  const int64_t constants[] = {static_cast<int64_t>(0x0000000000000000),
                               static_cast<int64_t>(0x0000000000000001),
                               static_cast<int64_t>(0x0000FFFFFFFF0000),
                               static_cast<int64_t>(0x7FFFFFFFFFFFFFFF),
                               static_cast<int64_t>(0x8000000000000000),
                               static_cast<int64_t>(0x8000000000000001),
                               static_cast<int64_t>(0x8000FFFFFFFF0000),
                               static_cast<int64_t>(0x8FFFFFFFFFFFFFFF),
                               static_cast<int64_t>(0xFFFFFFFFFFFFFFFF)};

  // For every decompression (lhs)
  for (size_t j = 0; j < arraysize(DecompressionOps); ++j) {
    // For every constant (rhs)
    for (size_t k = 0; k < arraysize(constants); ++k) {
      // Test with both (lhs, rhs) combinations
      for (bool lhsIsDecompression : {false, true}) {
        // Create the graph
        Node* load =
            graph()->NewNode(simplified()->LoadElement(ElementAccesses[j]),
                             object, index, effect, control);
        Node* changeToTagged = graph()->NewNode(DecompressionOps[j], load);
        Node* constant =
            graph()->NewNode(common()->Int64Constant(constants[k]));

        Node* lhs = lhsIsDecompression ? changeToTagged : constant;
        Node* rhs = lhsIsDecompression ? constant : changeToTagged;
        Node* comparison = graph()->NewNode(machine()->Word64Equal(), lhs, rhs);
        // Reduce
        Reduction r = Reduce(comparison);
        ASSERT_TRUE(r.Changed());
        EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kWord32Equal);
      }
    }
  }
}

TEST_F(DecompressionEliminationTest, DecompressionHeapConstantWord64Equal) {
  // Skip test if pointer compression is not enabled
  if (!COMPRESS_POINTERS_BOOL) {
    return;
  }

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

  const Operator* DecompressionOps[] = {
      machine()->ChangeCompressedToTagged(),
      machine()->ChangeCompressedSignedToTaggedSigned(),
      machine()->ChangeCompressedPointerToTaggedPointer()};

  const ElementAccess ElementAccesses[] = {
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::AnyTagged(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedSigned(),
       kNoWriteBarrier},
      {kTaggedBase, kTaggedSize, Type::Any(), MachineType::TaggedPointer(),
       kNoWriteBarrier}};

  ASSERT_EQ(arraysize(DecompressionOps), arraysize(ElementAccesses));

  const Handle<HeapNumber> heapConstants[] = {
      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)};

  // For every decompression (lhs)
  for (size_t j = 0; j < arraysize(DecompressionOps); ++j) {
    // For every constant (rhs)
    for (size_t k = 0; k < arraysize(heapConstants); ++k) {
      // Test with both (lhs, rhs) combinations
      for (bool lhsIsDecompression : {false, true}) {
        // Create the graph
        Node* load =
            graph()->NewNode(simplified()->LoadElement(ElementAccesses[j]),
                             object, index, effect, control);
        Node* changeToTagged = graph()->NewNode(DecompressionOps[j], load);
        Node* constant =
            graph()->NewNode(common()->HeapConstant(heapConstants[k]));

        Node* lhs = lhsIsDecompression ? changeToTagged : constant;
        Node* rhs = lhsIsDecompression ? constant : changeToTagged;
        Node* comparison = graph()->NewNode(machine()->Word64Equal(), lhs, rhs);
        // Reduce
        Reduction r = Reduce(comparison);
        ASSERT_TRUE(r.Changed());
        EXPECT_EQ(r.replacement()->opcode(), IrOpcode::kWord32Equal);
      }
    }
  }
}

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