chromium/v8/test/unittests/compiler/x64/turboshaft-instruction-selector-x64-unittest.cc

// Copyright 2024 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 <limits>

#include "src/codegen/assembler.h"
#include "src/common/globals.h"
#include "src/compiler/backend/instruction-codes.h"
#include "src/objects/objects-inl.h"
#include "test/unittests/compiler/backend/turboshaft-instruction-selector-unittest.h"

#if V8_ENABLE_WEBASSEMBLY
#include "src/wasm/simd-shuffle.h"
#endif  // V8_ENABLE_WEBASSEMBLY

namespace v8::internal::compiler::turboshaft {

// -----------------------------------------------------------------------------
// Conversions.

TEST_F(TurboshaftInstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) {}

TEST_F(TurboshaftInstructionSelectorTest, ChangeInt32ToInt64WithParameter) {}

TEST_F(TurboshaftInstructionSelectorTest, ChangeUint32ToFloat64WithParameter) {}

TEST_F(TurboshaftInstructionSelectorTest, ChangeUint32ToUint64WithParameter) {}

TEST_F(TurboshaftInstructionSelectorTest,
       TruncateFloat64ToFloat32WithParameter) {}

TEST_F(TurboshaftInstructionSelectorTest, TruncateInt64ToInt32WithParameter) {}

TEST_F(TurboshaftInstructionSelectorTest, SelectWord32) {}

TEST_F(TurboshaftInstructionSelectorTest, SelectWord64) {}

namespace {
struct LoadWithToInt64Extension {};

std::ostream& operator<<(std::ostream& os,
                         const LoadWithToInt64Extension& i32toi64) {}

static const LoadWithToInt64Extension kLoadWithToInt64Extensions[] =;

// The parameterized test that use the following type are intentionally part
// of the anonymous namespace. The issue here is that the type parameter is
// using a type that is in the anonymous namespace, but the class generated by
// TEST_P is not. This will cause GCC to generate a -Wsubobject-linkage warning.
//
// In this case there will only be single translation unit and the warning
// about subobject-linkage can be avoided by placing the class generated
// by TEST_P in the anoynmous namespace as well.
TurboshaftInstructionSelectorChangeInt32ToInt64Test;

TEST_P(TurboshaftInstructionSelectorChangeInt32ToInt64Test,
       ChangeInt32ToInt64WithLoad) {}

}  // namespace

INSTANTIATE_TEST_SUITE_P();

// -----------------------------------------------------------------------------
// Loads and stores

namespace {

struct MemoryAccess {};

std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) {}

static const MemoryAccess kMemoryAccesses[] =;

// The parameterized test that use the following type are intentionally part
// of the anonymous namespace. The issue here is that the type parameter is
// using a type that is in the anonymous namespace, but the class generated by
// TEST_P is not. This will cause GCC to generate a -Wsubobject-linkage warning.
//
// In this case there will only be single translation unit and the warning
// about subobject-linkage can be avoided by placing the class generated
// by TEST_P in the anoynmous namespace as well.
TurboshaftInstructionSelectorMemoryAccessTest;

TEST_P(TurboshaftInstructionSelectorMemoryAccessTest, LoadWithParameters) {}

TEST_P(TurboshaftInstructionSelectorMemoryAccessTest, StoreWithParameters) {}

}  // namespace

INSTANTIATE_TEST_SUITE_P();

// -----------------------------------------------------------------------------
// ChangeUint32ToUint64.

namespace {

struct BinaryOperation {};

std::ostream& operator<<(std::ostream& os, const BinaryOperation& bop) {}

const BinaryOperation kWord32BinaryOperations[] =;

// The parameterized test that use the following type are intentionally part
// of the anonymous namespace. The issue here is that the type parameter is
// using a type that is in the anonymous namespace, but the class generated by
// TEST_P is not. This will cause GCC to generate a -Wsubobject-linkage warning.
//
// In this case there will only be single translation unit and the warning
// about subobject-linkage can be avoided by placing the class generated
// by TEST_P in the anoynmous namespace as well.
TurboshaftInstructionSelectorChangeUint32ToUint64Test;

TEST_P(TurboshaftInstructionSelectorChangeUint32ToUint64Test,
       ChangeUint32ToUint64) {}

}  // namespace

INSTANTIATE_TEST_SUITE_P();

// -----------------------------------------------------------------------------
// CanElideChangeUint32ToUint64

namespace {

template <typename Op>
struct MachInst {};

MachInst2;

// X64 instructions that clear the top 32 bits of the destination.
const MachInst2 kCanElideChangeUint32ToUint64[] = {
    {TSBinop::kWord32BitwiseAnd, "Word32BitwiseAnd", kX64And32,
     MachineType::Uint32()},
    {TSBinop::kWord32BitwiseOr, "Word32BitwiseOr", kX64Or32,
     MachineType::Uint32()},
    {TSBinop::kWord32BitwiseXor, "Word32BitwiseXor", kX64Xor32,
     MachineType::Uint32()},
    {TSBinop::kWord32ShiftLeft, "Word32ShiftLeft", kX64Shl32,
     MachineType::Uint32()},
    {TSBinop::kWord32ShiftRightLogical, "Word32Shr", kX64Shr32,
     MachineType::Uint32()},
    {TSBinop::kWord32ShiftRightArithmetic, "Word32Sar", kX64Sar32,
     MachineType::Uint32()},
    {TSBinop::kWord32RotateRight, "Word32Ror", kX64Ror32,
     MachineType::Uint32()},
    {TSBinop::kWord32Equal, "Word32Equal", kX64Cmp32, MachineType::Uint32()},
    {TSBinop::kWord32Add, "Int32Add", kX64Lea32, MachineType::Int32()},
    {TSBinop::kWord32Sub, "Int32Sub", kX64Sub32, MachineType::Int32()},
    {TSBinop::kWord32Mul, "Int32Mul", kX64Imul32, MachineType::Int32()},
    {TSBinop::kInt32MulOverflownBits, "Int32MulOverflownBits", kX64ImulHigh32,
     MachineType::Int32()},
    {TSBinop::kInt32Div, "Int32Div", kX64Idiv32, MachineType::Int32()},
    {TSBinop::kInt32LessThan, "Int32LessThan", kX64Cmp32, MachineType::Int32()},
    {TSBinop::kInt32LessThanOrEqual, "Int32LessThanOrEqual", kX64Cmp32,
     MachineType::Int32()},
    {TSBinop::kInt32Mod, "Int32Mod", kX64Idiv32, MachineType::Int32()},
    {TSBinop::kUint32Div, "Uint32Div", kX64Udiv32, MachineType::Uint32()},
    {TSBinop::kUint32LessThan, "Uint32LessThan", kX64Cmp32,
     MachineType::Uint32()},
    {TSBinop::kUint32LessThanOrEqual, "Uint32LessThanOrEqual", kX64Cmp32,
     MachineType::Uint32()},
    {TSBinop::kUint32Mod, "Uint32Mod", kX64Udiv32, MachineType::Uint32()},
};

// The parameterized test that use the following type are intentionally part
// of the anonymous namespace. The issue here is that the type parameter is
// using a type that is in the anonymous namespace, but the class generated by
// TEST_P is not. This will cause GCC to generate a -Wsubobject-linkage warning.
//
// In this case there will only be single translation unit and the warning
// about subobject-linkage can be avoided by placing the class generated
// by TEST_P in the anoynmous namespace as well.
TurboshaftInstructionSelectorElidedChangeUint32ToUint64Test;

TEST_P(TurboshaftInstructionSelectorElidedChangeUint32ToUint64Test, Parameter) {}

}  // namespace

INSTANTIATE_TEST_SUITE_P();

// ChangeUint32ToUint64AfterLoad
TEST_F(TurboshaftInstructionSelectorTest, ChangeUint32ToUint64AfterLoad) {}

// -----------------------------------------------------------------------------
// TruncateInt64ToInt32.

TEST_F(TurboshaftInstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {}

TEST_F(TurboshaftInstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {}

// -----------------------------------------------------------------------------
// Addition.

TEST_F(TurboshaftInstructionSelectorTest, Int32AddWithInt32ParametersLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddConstantAsLeaSingle) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddConstantAsAdd) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddConstantAsLeaDouble) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddSimpleAsAdd) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddSimpleAsLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled2Mul) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddCommutedScaled2Mul) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled2Shl) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddCommutedScaled2Shl) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled4Mul) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled4Shl) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled8Mul) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled8Shl) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled2MulWithConstant) {}

TEST_F(TurboshaftInstructionSelectorTest,
       Int32AddScaled2MulWithConstantShuffle1) {}

TEST_F(TurboshaftInstructionSelectorTest,
       Int32AddScaled2MulWithConstantShuffle2) {}

TEST_F(TurboshaftInstructionSelectorTest,
       Int32AddScaled2MulWithConstantShuffle3) {}

TEST_F(TurboshaftInstructionSelectorTest,
       Int32AddScaled2MulWithConstantShuffle4) {}

TEST_F(TurboshaftInstructionSelectorTest,
       Int32AddScaled2MulWithConstantShuffle5) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled2ShlWithConstant) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled4MulWithConstant) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled4ShlWithConstant) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled8MulWithConstant) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled8ShlWithConstant) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32SubConstantAsSub) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32SubConstantAsLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddScaled2Other) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32AddMinNegativeDisplacement) {}

// -----------------------------------------------------------------------------
// Multiplication.

TEST_F(TurboshaftInstructionSelectorTest, Int32MulWithInt32MulWithParameters) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32MulOverflownBits) {}

TEST_F(TurboshaftInstructionSelectorTest, Uint32MulOverflownBits) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32Mul2BecomesLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32Mul3BecomesLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32Mul4BecomesLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32Mul5BecomesLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32Mul8BecomesLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32Mul9BecomesLea) {}

// -----------------------------------------------------------------------------
// Word32ShiftLeft.

TEST_F(TurboshaftInstructionSelectorTest, Int32Shl1BecomesLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32Shl2BecomesLea) {}

TEST_F(TurboshaftInstructionSelectorTest, Int32Shl4BecomesLea) {}

// -----------------------------------------------------------------------------
// Binops with a memory operand.

TEST_F(TurboshaftInstructionSelectorTest, LoadCmp32) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadAnd32) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadOr32) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadXor32) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadAdd32) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadSub32) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadAnd64) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadOr64) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadXor64) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadAdd64) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadSub64) {}

// -----------------------------------------------------------------------------
// Floating point operations.

TEST_F(TurboshaftInstructionSelectorTest, Float32Abs) {}

TEST_F(TurboshaftInstructionSelectorTest, Float64Abs) {}

TEST_F(TurboshaftInstructionSelectorTest, Float64BinopArithmetic) {}

TEST_F(TurboshaftInstructionSelectorTest, Float32BinopArithmeticWithLoad) {}

TEST_F(TurboshaftInstructionSelectorTest, Float64BinopArithmeticWithLoad) {}

// -----------------------------------------------------------------------------
// Miscellaneous.

TEST_F(TurboshaftInstructionSelectorTest,
       Word64ShiftLeftWithChangeInt32ToInt64) {}

TEST_F(TurboshaftInstructionSelectorTest,
       Word64ShiftLeftWithChangeUint32ToUint64) {}

TEST_F(TurboshaftInstructionSelectorTest, Word32BitwiseAndWith0xFF) {}

TEST_F(TurboshaftInstructionSelectorTest, Word64BitwiseAndWith0xFFFFFFFF) {}

TEST_F(TurboshaftInstructionSelectorTest, Word64BitwiseAndWith0xFFFF) {}

TEST_F(TurboshaftInstructionSelectorTest, Word64BitwiseAndWith0xFF) {}

TEST_F(TurboshaftInstructionSelectorTest, Word64BitwiseAndWithInt64FitsUint32) {}

TEST_F(TurboshaftInstructionSelectorTest,
       Word64BitwiseAndWithInt64DontFitsUint32) {}

TEST_F(TurboshaftInstructionSelectorTest, Word32BitwiseAndWith0xFFFF) {}

TEST_F(TurboshaftInstructionSelectorTest, Word32Clz) {}

TEST_F(TurboshaftInstructionSelectorTest, LoadAndWord64ShiftRight32) {}

#if V8_ENABLE_WEBASSEMBLY
// -----------------------------------------------------------------------------
// SIMD.

TEST_F(TurboshaftInstructionSelectorTest, SIMDSplatZero) {}

struct ArchShuffle {};

static constexpr ArchShuffle kArchShuffles[] =;

TurboshaftInstructionSelectorSIMDArchShuffleTest;

TEST_P(TurboshaftInstructionSelectorSIMDArchShuffleTest, SIMDArchShuffle) {}

INSTANTIATE_TEST_SUITE_P();

// TODO(dmercadier): port to Turboshaft once Turboshaft supports Simd256
// shuffles.
#if 0

struct ArchShuffle256 {
  uint8_t shuffle[kSimd256Size];
  ArchOpcode arch_opcode;
  size_t input_count;
};

static constexpr ArchShuffle256 kArchShuffles256[] = {
    {{4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 0,  1,  2,  3,
      20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19},
     kX64Vpshufd,
     2}};

using TurboshaftInstructionSelectorSIMDArchShuffle256Test =
    TurboshaftInstructionSelectorTestWithParam<ArchShuffle256>;

TEST_P(TurboshaftInstructionSelectorSIMDArchShuffle256Test,
       SIMDArchShuffle256) {
  MachineType type = MachineType::Simd128();
  {
    // Tests various shuffle optimizations
    StreamBuilder m(this, type, type, type);
    auto param = GetParam();
    auto shuffle = param.shuffle;
    const Operator* op = m.machine()->I8x32Shuffle(shuffle);
    OpIndex n = m.AddNode(op, m.Parameter(0), m.Parameter(1));
    m.Return(n);
    Stream s = m.Build();
    ASSERT_EQ(1U, s.size());
    EXPECT_EQ(param.arch_opcode, s[0]->arch_opcode());
    ASSERT_EQ(param.input_count, s[0]->InputCount());
    EXPECT_EQ(1U, s[0]->OutputCount());
  }
}

INSTANTIATE_TEST_SUITE_P(TurboshaftInstructionSelectorTest,
                         TurboshaftInstructionSelectorSIMDArchShuffle256Test,
                         ::testing::ValuesIn(kArchShuffles256));

#endif

struct ShuffleWithZeroInput {};

static constexpr ShuffleWithZeroInput kShuffleWithZeroInput[] =;

TurboshaftInstructionSelectorSIMDShuffleWithZeroInputTest;

TEST_P(TurboshaftInstructionSelectorSIMDShuffleWithZeroInputTest,
       SIMDShuffleWithZeroInputTest) {}

INSTANTIATE_TEST_SUITE_P();

struct SwizzleConstants {};

static constexpr SwizzleConstants kSwizzleConstants[] =;

TurboshaftInstructionSelectorSIMDSwizzleConstantTest;

TEST_P(TurboshaftInstructionSelectorSIMDSwizzleConstantTest,
       SimdSwizzleConstant) {}

INSTANTIATE_TEST_SUITE_P();

TEST_F(TurboshaftInstructionSelectorTest,
       F64x2PromoteLowF32x4WithS128Load64Zero) {}

#endif  // V8_ENABLE_WEBASSEMBLY

}  // namespace v8::internal::compiler::turboshaft