14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci#include "ecmascript/compiler/gate_accessor.h" 164514f5e3Sopenharmony_ci#include "ecmascript/compiler/pass.h" 174514f5e3Sopenharmony_ci#include "ecmascript/compiler/share_gate_meta_data.h" 184514f5e3Sopenharmony_ci#include "ecmascript/compiler/share_opcodes.h" 194514f5e3Sopenharmony_ci#include "ecmascript/compiler/value_numbering.h" 204514f5e3Sopenharmony_ci#include "ecmascript/compiler/verifier.h" 214514f5e3Sopenharmony_ci#include "ecmascript/compiler/typed_bytecode_lowering.h" 224514f5e3Sopenharmony_ci#include "ecmascript/compiler/typed_hcr_lowering.h" 234514f5e3Sopenharmony_ci#include "ecmascript/elements.h" 244514f5e3Sopenharmony_ci#include "ecmascript/mem/concurrent_marker.h" 254514f5e3Sopenharmony_ci#include "ecmascript/mem/native_area_allocator.h" 264514f5e3Sopenharmony_ci#include "ecmascript/tests/test_helper.h" 274514f5e3Sopenharmony_ci#include "gtest/gtest.h" 284514f5e3Sopenharmony_ci#include <cstddef> 294514f5e3Sopenharmony_ci#include <vector> 304514f5e3Sopenharmony_ci 314514f5e3Sopenharmony_cinamespace panda::test { 324514f5e3Sopenharmony_ciclass GlobalValueNumberingTests : public testing::Test {}; 334514f5e3Sopenharmony_ci 344514f5e3Sopenharmony_ciusing ecmascript::kungfu::Circuit; 354514f5e3Sopenharmony_ciusing ecmascript::kungfu::CircuitBuilder; 364514f5e3Sopenharmony_ciusing ecmascript::kungfu::CombinedPassVisitor; 374514f5e3Sopenharmony_ciusing ecmascript::kungfu::EcmaOpcode; 384514f5e3Sopenharmony_ciusing ecmascript::kungfu::Environment; 394514f5e3Sopenharmony_ciusing ecmascript::kungfu::GateAccessor; 404514f5e3Sopenharmony_ciusing ecmascript::kungfu::GateRef; 414514f5e3Sopenharmony_ciusing ecmascript::kungfu::PGOSampleType; 424514f5e3Sopenharmony_ciusing ecmascript::kungfu::ValueNumbering; 434514f5e3Sopenharmony_ciusing ecmascript::kungfu::Verifier; 444514f5e3Sopenharmony_ci 454514f5e3Sopenharmony_ci 464514f5e3Sopenharmony_ciHWTEST_F_L0(GlobalValueNumberingTests, AllInputsCheckedTest) 474514f5e3Sopenharmony_ci{ 484514f5e3Sopenharmony_ci // construct a circuit 494514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 504514f5e3Sopenharmony_ci Circuit circuit(&allocator); 514514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 524514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 534514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 544514f5e3Sopenharmony_ci Environment env(0, &builder); 554514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 564514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 574514f5e3Sopenharmony_ci auto y = builder.Arguments(2); 584514f5e3Sopenharmony_ci auto z = builder.Arguments(3); 594514f5e3Sopenharmony_ci auto add1 = builder.Int64Add(x, y); 604514f5e3Sopenharmony_ci auto add2 = builder.Int64Add(x, y); 614514f5e3Sopenharmony_ci auto add3 = builder.Int64Add(x, z); 624514f5e3Sopenharmony_ci 634514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 644514f5e3Sopenharmony_ci ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 654514f5e3Sopenharmony_ci 664514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate()); 674514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.VisitGate(add2), add1); 684514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.VisitGate(add3), Circuit::NullGate()); 694514f5e3Sopenharmony_ci} 704514f5e3Sopenharmony_ci 714514f5e3Sopenharmony_ci 724514f5e3Sopenharmony_ciHWTEST_F_L0(GlobalValueNumberingTests, DeadNodesTest) 734514f5e3Sopenharmony_ci{ 744514f5e3Sopenharmony_ci // construct a circuit 754514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 764514f5e3Sopenharmony_ci Circuit circuit(&allocator); 774514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 784514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 794514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 804514f5e3Sopenharmony_ci Environment env(0, &builder); 814514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 824514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 834514f5e3Sopenharmony_ci auto y = builder.Arguments(2); 844514f5e3Sopenharmony_ci 854514f5e3Sopenharmony_ci auto add1 = builder.Int64Add(x, y); 864514f5e3Sopenharmony_ci auto add2 = builder.Int64Add(x, y); 874514f5e3Sopenharmony_ci 884514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 894514f5e3Sopenharmony_ci ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 904514f5e3Sopenharmony_ci 914514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate()); 924514f5e3Sopenharmony_ci acc.DeleteGate(add1); 934514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.VisitGate(add2), Circuit::NullGate()); 944514f5e3Sopenharmony_ci} 954514f5e3Sopenharmony_ci 964514f5e3Sopenharmony_ciHWTEST_F_L0(GlobalValueNumberingTests, WontReplaceNodeWithItself) 974514f5e3Sopenharmony_ci{ 984514f5e3Sopenharmony_ci // construct a circuit 994514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 1004514f5e3Sopenharmony_ci Circuit circuit(&allocator); 1014514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 1024514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 1034514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 1044514f5e3Sopenharmony_ci Environment env(0, &builder); 1054514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 1064514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 1074514f5e3Sopenharmony_ci auto y = builder.Arguments(2); 1084514f5e3Sopenharmony_ci 1094514f5e3Sopenharmony_ci auto add1 = builder.Int64Add(x, y); 1104514f5e3Sopenharmony_ci 1114514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 1124514f5e3Sopenharmony_ci ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 1134514f5e3Sopenharmony_ci 1144514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate()); 1154514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate()); 1164514f5e3Sopenharmony_ci} 1174514f5e3Sopenharmony_ci 1184514f5e3Sopenharmony_ci 1194514f5e3Sopenharmony_ciHWTEST_F_L0(GlobalValueNumberingTests, E2ESimpleAddTest) 1204514f5e3Sopenharmony_ci{ 1214514f5e3Sopenharmony_ci // construct a circuit 1224514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 1234514f5e3Sopenharmony_ci Circuit circuit(&allocator); 1244514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 1254514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 1264514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 1274514f5e3Sopenharmony_ci Environment env(0, &builder); 1284514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 1294514f5e3Sopenharmony_ci 1304514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 1314514f5e3Sopenharmony_ci auto y = builder.Arguments(2); 1324514f5e3Sopenharmony_ci 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_ci auto add1 = builder.Int64Add(x, y); 1354514f5e3Sopenharmony_ci auto add2 = builder.Int64Add(x, y); 1364514f5e3Sopenharmony_ci auto add3 = builder.Int64Add(add1, add2); 1374514f5e3Sopenharmony_ci 1384514f5e3Sopenharmony_ci builder.Return(add3); 1394514f5e3Sopenharmony_ci EXPECT_TRUE(Verifier::Run(&circuit)); 1404514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 1414514f5e3Sopenharmony_ci ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 1424514f5e3Sopenharmony_ci visitor.AddPass(&valuenumber); 1434514f5e3Sopenharmony_ci visitor.VisitGraph(); 1444514f5e3Sopenharmony_ci EXPECT_TRUE(Verifier::Run(&circuit)); 1454514f5e3Sopenharmony_ci EXPECT_TRUE(acc.GetValueIn(add3, 0) == acc.GetValueIn(add3, 1)); 1464514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.GetoptimizedGateCount(), 1); 1474514f5e3Sopenharmony_ci} 1484514f5e3Sopenharmony_ci 1494514f5e3Sopenharmony_ciHWTEST_F_L0(GlobalValueNumberingTests, GrowStressTest) 1504514f5e3Sopenharmony_ci{ 1514514f5e3Sopenharmony_ci // construct a circuit 1524514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 1534514f5e3Sopenharmony_ci Circuit circuit(&allocator); 1544514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 1554514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 1564514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 1574514f5e3Sopenharmony_ci Environment env(0, &builder); 1584514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_ci std::vector<GateRef> results; 1614514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 1624514f5e3Sopenharmony_ci auto y = builder.Arguments(2); 1634514f5e3Sopenharmony_ci 1644514f5e3Sopenharmony_ci for (int i = 0; i < 10000; i++) { 1654514f5e3Sopenharmony_ci auto add1 = builder.Int64Add(x, y); 1664514f5e3Sopenharmony_ci results.push_back(add1); 1674514f5e3Sopenharmony_ci } 1684514f5e3Sopenharmony_ci 1694514f5e3Sopenharmony_ci GateRef before = results[0]; 1704514f5e3Sopenharmony_ci for (int i = 1; i < 10000; i++) { 1714514f5e3Sopenharmony_ci before = builder.Int64Add(before, results[i]); 1724514f5e3Sopenharmony_ci } 1734514f5e3Sopenharmony_ci 1744514f5e3Sopenharmony_ci builder.Return(before); 1754514f5e3Sopenharmony_ci EXPECT_TRUE(Verifier::Run(&circuit)); 1764514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 1774514f5e3Sopenharmony_ci ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 1784514f5e3Sopenharmony_ci visitor.AddPass(&valuenumber); 1794514f5e3Sopenharmony_ci visitor.VisitGraph(); 1804514f5e3Sopenharmony_ci EXPECT_TRUE(Verifier::Run(&circuit)); 1814514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.GetoptimizedGateCount(), 9999); 1824514f5e3Sopenharmony_ci} 1834514f5e3Sopenharmony_ci 1844514f5e3Sopenharmony_ci 1854514f5e3Sopenharmony_ciHWTEST_F_L0(GlobalValueNumberingTests, ComplexAddTest) 1864514f5e3Sopenharmony_ci{ 1874514f5e3Sopenharmony_ci // construct a circuit 1884514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 1894514f5e3Sopenharmony_ci Circuit circuit(&allocator); 1904514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 1914514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 1924514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 1934514f5e3Sopenharmony_ci Environment env(0, &builder); 1944514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 1954514f5e3Sopenharmony_ci 1964514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 1974514f5e3Sopenharmony_ci auto y = builder.Arguments(2); 1984514f5e3Sopenharmony_ci 1994514f5e3Sopenharmony_ci auto add1 = builder.Int64Add(x, y); 2004514f5e3Sopenharmony_ci auto add2 = builder.Int64Add(x, y); 2014514f5e3Sopenharmony_ci auto add3 = builder.Int64Add(add1, add2); 2024514f5e3Sopenharmony_ci 2034514f5e3Sopenharmony_ci auto add4 = builder.Int64Add(x, y); 2044514f5e3Sopenharmony_ci auto add5 = builder.Int64Add(x, y); 2054514f5e3Sopenharmony_ci auto add6 = builder.Int64Add(add4, add5); 2064514f5e3Sopenharmony_ci 2074514f5e3Sopenharmony_ci auto add7 = builder.Int64Add(add3, add6); 2084514f5e3Sopenharmony_ci builder.Return(add7); 2094514f5e3Sopenharmony_ci EXPECT_TRUE(Verifier::Run(&circuit)); 2104514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 2114514f5e3Sopenharmony_ci ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 2124514f5e3Sopenharmony_ci visitor.AddPass(&valuenumber); 2134514f5e3Sopenharmony_ci visitor.VisitGraph(); 2144514f5e3Sopenharmony_ci EXPECT_TRUE(Verifier::Run(&circuit)); 2154514f5e3Sopenharmony_ci EXPECT_EQ(valuenumber.GetoptimizedGateCount(), 4); 2164514f5e3Sopenharmony_ci} 2174514f5e3Sopenharmony_ci 2184514f5e3Sopenharmony_ci} // namespace panda::test