// 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 "src/compiler/turboshaft/operations.h" #define TURBOSHAFT_OPMASK_EXPORT_FIELD_MACRO_FOR_UNITTESTS #include "src/compiler/turboshaft/opmasks.h" #include "testing/gtest-support.h" namespace v8::internal::compiler::turboshaft { struct MyFakeOp; // We reuse `Opcode::kConstant` because extending the opcode enum is hard from // within the test. template <> struct operation_to_opcode : std::integral_constant {}; struct MyFakeOp : FixedArityOperationT<0, MyFakeOp> { enum class Kind : uint16_t { kA = 0x0000, kB = 0x0001, kC = 0x0100, kD = 0x11F8, kE = 0xFFFF, }; Kind kind; uint16_t value; MyFakeOp(Kind kind, uint16_t value) : Base(), kind(kind), value(value) {} }; using namespace Opmask; using MyFakeMask = Opmask::MaskBuilder; using kA0 = MyFakeMask::For; using kB0 = MyFakeMask::For; using kC0 = MyFakeMask::For; using kD0 = MyFakeMask::For; using kA1 = MyFakeMask::For; using kC1 = MyFakeMask::For; using kB0100 = MyFakeMask::For; using kD0100 = MyFakeMask::For; using kA11F8 = MyFakeMask::For; using kB11F8 = MyFakeMask::For; using MyFakeKindMask = Opmask::MaskBuilder; using kA = MyFakeKindMask::For; using kC = MyFakeKindMask::For; class OpmaskTest : public ::testing::Test {}; template struct MaskList; template struct MaskList { template static void Check(const MyFakeOp& op) { ASSERT_EQ(op.template Is(), (std::is_same_v)); MaskList::template Check(op); } }; template <> struct MaskList<> { template static void Check(const MyFakeOp&) {} }; template void Check(const MyFakeOp& op) { MaskList::Check(op); } TEST_F(OpmaskTest, FullMask) { MyFakeOp op_A0(MyFakeOp::Kind::kA, 0); Check(op_A0); MyFakeOp op_B0(MyFakeOp::Kind::kB, 0); Check(op_B0); MyFakeOp op_C1(MyFakeOp::Kind::kC, 1); Check(op_C1); MyFakeOp op_B0100(MyFakeOp::Kind::kB, 0x0100); Check(op_B0100); MyFakeOp op_D0100(MyFakeOp::Kind::kD, 0x0100); Check(op_D0100); MyFakeOp op_A11F8(MyFakeOp::Kind::kA, 0x11F8); Check(op_A11F8); // Ops that should not match any mask. MyFakeOp op_other1(MyFakeOp::Kind::kE, 0); Check(op_other1); MyFakeOp op_other2(MyFakeOp::Kind::kE, 0x11F8); Check(op_other2); MyFakeOp op_other3(MyFakeOp::Kind::kA, 2); Check(op_other3); MyFakeOp op_other4(MyFakeOp::Kind::kD, 0xF811); Check(op_other4); MyFakeOp op_other5(MyFakeOp::Kind::kA, 0x0100); Check(op_other5); } TEST_F(OpmaskTest, PartialMask) { for (uint16_t v : {0, 1, 2, 0x0100, 0x0101, 0x11F8}) { MyFakeOp op(MyFakeOp::Kind::kA, v); ASSERT_TRUE(op.Is()); ASSERT_FALSE(op.Is()); } for (uint16_t v : {0, 1, 2, 0x0100, 0x0101, 0x11F8}) { MyFakeOp op(MyFakeOp::Kind::kC, v); ASSERT_FALSE(op.Is()); ASSERT_TRUE(op.Is()); } } } // namespace v8::internal::compiler::turboshaft