diff --git a/compiler/optimizer/ir/dyn_datatype.h b/compiler/optimizer/ir/dyn_datatype.h index 53a80e077d36f5cd81a1f06a4533409092547feb..7bcda1d4c363d6c6c60d94c9e870b2c65b544c1a 100644 --- a/compiler/optimizer/ir/dyn_datatype.h +++ b/compiler/optimizer/ir/dyn_datatype.h @@ -66,34 +66,41 @@ static inline uint8_t GetPossibleTypeMask(panda::compiler::AnyBaseType type, pro INTEGER = (1U << 0U), DOUBLE = (1U << 1U), BOOLEAN = (1U << 2U), - SPECIAL = (1U << 3U), + NULL_TYPE = (1U << 3U), + UNDEFINED = (1U << 4U), OTHER = (1U << 5U), - SPECIAL_INT = SPECIAL | INTEGER, - SPECIAL_DOUBLE = SPECIAL | DOUBLE, + // NOLINTNEXTLINE(hicpp-signed-bitwise) + SPECIAL_INT = BOOLEAN | NULL_TYPE | INTEGER, + SPECIAL_DOUBLE = UNDEFINED | DOUBLE, + NUMBER = INTEGER | DOUBLE, + SPECIAL_NUMBER = SPECIAL_INT | SPECIAL_DOUBLE }; - uint8_t result = 0; - if ((allowed_types & profiling::AnyInputType::SPECIAL) != 0) { - result = Type::SPECIAL; - } switch (type) { case panda::compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE: + return Type::BOOLEAN; case panda::compiler::AnyBaseType::ECMASCRIPT_NULL_TYPE: - return Type::SPECIAL_INT; + return Type::NULL_TYPE; case panda::compiler::AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE: - return Type::SPECIAL_DOUBLE; + return Type::UNDEFINED; case panda::compiler::AnyBaseType::ECMASCRIPT_INT_TYPE: - result |= Type::INTEGER; - break; + if ((allowed_types & profiling::AnyInputType::SPECIAL) != 0) { + return Type::SPECIAL_INT; + } + return Type::INTEGER; case panda::compiler::AnyBaseType::ECMASCRIPT_DOUBLE_TYPE: - result |= Type::DOUBLE; if ((allowed_types & profiling::AnyInputType::INTEGER) != 0) { - result |= Type::INTEGER; + if ((allowed_types & profiling::AnyInputType::SPECIAL) != 0) { + return Type::SPECIAL_NUMBER; + } + return Type::NUMBER; } - break; + if ((allowed_types & profiling::AnyInputType::SPECIAL) != 0) { + return Type::SPECIAL_DOUBLE; + } + return Type::DOUBLE; default: return Type::OTHER; } - return result; } static inline std::optional IsAnyTypeCanBeSubtypeOf(panda::compiler::AnyBaseType super_type, diff --git a/tests/compiler/peepholes_ecma_test.cpp b/tests/compiler/peepholes_ecma_test.cpp index c580e094ba74ff5c086325e24ac9968bcab75d6a..1c045bea3f96f5e6bf9feba98da4ad86bba24322 100644 --- a/tests/compiler/peepholes_ecma_test.cpp +++ b/tests/compiler/peepholes_ecma_test.cpp @@ -458,6 +458,205 @@ TEST_F(PeepholesTest, CompareCastToAnyAndConst) EXPECT_TRUE(GraphComparator().Compare(graph, graph_opt)); } + +TEST_F(PeepholesTest, CompareAnyTypeAfterCastValueToAny) +{ + auto graph = CreateGraphDynStubWithDefaultRuntime(); + GRAPH(graph) + { + CONSTANT(0, 0); + + BASIC_BLOCK(2, -1) + { + INST(2, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + + INST(3, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE).Inputs(2); + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(3); + + INST(5, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_NULL_TYPE).Inputs(2); + INST(6, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(5); + + INST(7, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); + INST(8, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(7); + + INST(9, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(2); + INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(9); + + INST(11, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(2); + INST(12, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(11); + + INST(13, Opcode::SaveState).Inputs(0, 3, 5, 7, 9, 11).SrcVregs({0, 1, 2, 3, 4, 5}); + INST(14, Opcode::CallDynamic).any().InputsAutoType(4, 6, 8, 10, 12, 13); + INST(15, Opcode::Return).any().Inputs(14); + } + } + + ASSERT_TRUE(graph->RunPass()); + ASSERT_TRUE(graph->RunPass()); + GraphChecker(graph).Check(); + + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); + GRAPH(graph_opt) + { + CONSTANT(0, 0); + CONSTANT(1, 1); + + BASIC_BLOCK(2, -1) + { + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(0); + INST(6, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(0); + INST(8, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(0); + INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(1); + INST(12, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(0); + + INST(13, Opcode::SaveState).Inputs(0, 0, 0, 0, 1, 0).SrcVregs({0, 1, 2, 3, 4, 5}); + INST(14, Opcode::CallDynamic).any().InputsAutoType(4, 6, 8, 10, 12, 13); + INST(15, Opcode::Return).any().Inputs(14); + } + } + + EXPECT_TRUE(GraphComparator().Compare(graph, graph_opt)); +} + +TEST_F(PeepholesTest, CompareAnyTypeAfterAnyTypeCheck) +{ + auto graph = CreateGraphDynStubWithDefaultRuntime(); + GRAPH(graph) + { + PARAMETER(0, 0).any(); + + BASIC_BLOCK(2, -1) + { + INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0}); + INST(2, Opcode::AnyTypeCheck).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(0, 1); + + INST(3, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE).Inputs(0); + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(3); + + INST(5, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_NULL_TYPE).Inputs(0); + INST(6, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(5); + + INST(7, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(0); + INST(8, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(7); + + INST(9, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(9); + + INST(11, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(0); + INST(12, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(11); + + INST(13, Opcode::SaveState).Inputs(0, 3, 5, 7, 9, 11).SrcVregs({0, 1, 2, 3, 4, 5}); + INST(14, Opcode::CallDynamic).any().InputsAutoType(4, 6, 8, 10, 12, 13); + INST(15, Opcode::Return).any().Inputs(14); + } + } + + ASSERT_TRUE(graph->RunPass()); + ASSERT_TRUE(graph->RunPass()); + GraphChecker(graph).Check(); + + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); + GRAPH(graph_opt) + { + PARAMETER(0, 0).any(); + CONSTANT(16, 0); + CONSTANT(17, 1); + + BASIC_BLOCK(2, -1) + { + INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0}); + INST(2, Opcode::AnyTypeCheck).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(0, 1); + + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(16); + INST(6, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(16); + INST(8, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(16); + INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(16); + INST(12, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(17); + + INST(13, Opcode::SaveState).Inputs(0, 16, 16, 16, 16, 17).SrcVregs({0, 1, 2, 3, 4, 5}); + INST(14, Opcode::CallDynamic).any().InputsAutoType(4, 6, 8, 10, 12, 13); + INST(15, Opcode::Return).any().Inputs(14); + } + } + + EXPECT_TRUE(GraphComparator().Compare(graph, graph_opt)); +} + +TEST_F(PeepholesTest, CompareAnyTypeAfterAnyTypeCheckSpecial) +{ + auto graph = CreateGraphDynStubWithDefaultRuntime(); + GRAPH(graph) + { + PARAMETER(0, 0).any(); + + BASIC_BLOCK(2, -1) + { + INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0}); + INST(2, Opcode::AnyTypeCheck) + .any() + .AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE) + .AllowedInputType(profiling::AnyInputType::SPECIAL) + .Inputs(0, 1); + + INST(3, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE).Inputs(0); + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(3); + + INST(5, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_NULL_TYPE).Inputs(0); + INST(6, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(5); + + INST(7, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(0); + INST(8, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(7); + + INST(9, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(9); + + INST(11, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(0); + INST(12, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(11); + + INST(13, Opcode::SaveState).Inputs(0, 3, 5, 7, 9, 11).SrcVregs({0, 1, 2, 3, 4, 5}); + INST(14, Opcode::CallDynamic).any().InputsAutoType(4, 6, 8, 10, 12, 13); + INST(15, Opcode::Return).any().Inputs(14); + } + } + + ASSERT_TRUE(graph->RunPass()); + ASSERT_TRUE(graph->RunPass()); + GraphChecker(graph).Check(); + + auto graph_opt = CreateGraphDynStubWithDefaultRuntime(); + GRAPH(graph_opt) + { + PARAMETER(0, 0).any(); + CONSTANT(16, 0); + + BASIC_BLOCK(2, -1) + { + INST(1, Opcode::SaveState).Inputs(0).SrcVregs({0}); + INST(2, Opcode::AnyTypeCheck) + .any() + .AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE) + .AllowedInputType(profiling::AnyInputType::SPECIAL) + .Inputs(0, 1); + + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(16); + + INST(5, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_NULL_TYPE).Inputs(0); + INST(6, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(5); + + INST(7, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(0); + INST(8, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(7); + + INST(9, Opcode::CompareAnyType).b().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(9); + + INST(12, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(16); + + INST(13, Opcode::SaveState).Inputs(0, 16, 5, 7, 9, 16).SrcVregs({0, 1, 2, 3, 4, 5}); + INST(14, Opcode::CallDynamic).any().InputsAutoType(4, 6, 8, 10, 12, 13); + INST(15, Opcode::Return).any().Inputs(14); + } + } +} // NOLINTEND(readability-magic-numbers) } // namespace panda::compiler