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/bytecodes.h" 164514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit.h" 174514f5e3Sopenharmony_ci#include "ecmascript/compiler/gate_accessor.h" 184514f5e3Sopenharmony_ci#include "ecmascript/compiler/lcr_gate_meta_data.h" 194514f5e3Sopenharmony_ci#include "ecmascript/compiler/pass.h" 204514f5e3Sopenharmony_ci#include "ecmascript/compiler/share_gate_meta_data.h" 214514f5e3Sopenharmony_ci#include "ecmascript/compiler/share_opcodes.h" 224514f5e3Sopenharmony_ci#include "ecmascript/compiler/instruction_combine.h" 234514f5e3Sopenharmony_ci#include "ecmascript/compiler/verifier.h" 244514f5e3Sopenharmony_ci#include "ecmascript/compiler/gate_matchers.h" 254514f5e3Sopenharmony_ci#include "ecmascript/elements.h" 264514f5e3Sopenharmony_ci#include "ecmascript/mem/concurrent_marker.h" 274514f5e3Sopenharmony_ci#include "ecmascript/mem/machine_code.h" 284514f5e3Sopenharmony_ci#include "ecmascript/mem/native_area_allocator.h" 294514f5e3Sopenharmony_ci#include "ecmascript/tests/test_helper.h" 304514f5e3Sopenharmony_ci#include "gtest/gtest.h" 314514f5e3Sopenharmony_ci#include <cmath> 324514f5e3Sopenharmony_ci#include <cstddef> 334514f5e3Sopenharmony_ci#include <cstdint> 344514f5e3Sopenharmony_ci#include <vector> 354514f5e3Sopenharmony_ci 364514f5e3Sopenharmony_cinamespace panda::test { 374514f5e3Sopenharmony_ciclass InstructionCombineTests : public testing::Test {}; 384514f5e3Sopenharmony_ciusing ecmascript::kungfu::Circuit; 394514f5e3Sopenharmony_ciusing ecmascript::kungfu::CircuitBuilder; 404514f5e3Sopenharmony_ciusing ecmascript::kungfu::CombinedPassVisitor; 414514f5e3Sopenharmony_ciusing ecmascript::kungfu::EcmaOpcode; 424514f5e3Sopenharmony_ciusing ecmascript::kungfu::Environment; 434514f5e3Sopenharmony_ciusing ecmascript::kungfu::Float64BinopMatcher; 444514f5e3Sopenharmony_ciusing ecmascript::kungfu::Float64Matcher; 454514f5e3Sopenharmony_ciusing ecmascript::kungfu::GateAccessor; 464514f5e3Sopenharmony_ciusing ecmascript::kungfu::GateRef; 474514f5e3Sopenharmony_ciusing ecmascript::kungfu::InstructionCombine; 484514f5e3Sopenharmony_ciusing ecmascript::kungfu::Int32BinopMatcher; 494514f5e3Sopenharmony_ciusing ecmascript::kungfu::Int64BinopMatcher; 504514f5e3Sopenharmony_ciusing ecmascript::kungfu::OpCode; 514514f5e3Sopenharmony_ciusing ecmascript::kungfu::PGOSampleType; 524514f5e3Sopenharmony_ciusing ecmascript::kungfu::Verifier; 534514f5e3Sopenharmony_ci// std::numeric_limits<T>::quiet_NaN(). 544514f5e3Sopenharmony_citemplate <class T> T SilenceNaN(T x) 554514f5e3Sopenharmony_ci{ 564514f5e3Sopenharmony_ci assert(std::isnan(x)); 574514f5e3Sopenharmony_ci // Do some calculation to make a signalling NaN quiet. 584514f5e3Sopenharmony_ci return x - x; 594514f5e3Sopenharmony_ci} 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64AddTest) 624514f5e3Sopenharmony_ci{ 634514f5e3Sopenharmony_ci // construct a circuit 644514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 654514f5e3Sopenharmony_ci Circuit circuit(&allocator); 664514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 674514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 684514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 694514f5e3Sopenharmony_ci Environment env(0, &builder); 704514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 714514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 724514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 734514f5e3Sopenharmony_ci 744514f5e3Sopenharmony_ci // test x + 0 => x 754514f5e3Sopenharmony_ci { 764514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 774514f5e3Sopenharmony_ci auto const_i64_0 = builder.Int64(0); 784514f5e3Sopenharmony_ci auto test_x_add_0 = builder.Int64Add(x, const_i64_0); 794514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(test_x_add_0), x); 804514f5e3Sopenharmony_ci } 814514f5e3Sopenharmony_ci // test 1 + 2 => 3 824514f5e3Sopenharmony_ci { 834514f5e3Sopenharmony_ci auto const_i64_1 = builder.Int64(1); 844514f5e3Sopenharmony_ci auto const_i64_2 = builder.Int64(2); 854514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int64Add(const_i64_1, const_i64_2)); 864514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, 3), true); 874514f5e3Sopenharmony_ci } 884514f5e3Sopenharmony_ci // Test for 64-bit integer wraparound: 9223372036854775807 + 1 => -9223372036854775808 894514f5e3Sopenharmony_ci { 904514f5e3Sopenharmony_ci auto const_i64_max = builder.Int64(9223372036854775807); 914514f5e3Sopenharmony_ci auto const_i64_1 = builder.Int64(1); 924514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int64Add(const_i64_max, const_i64_1)); 934514f5e3Sopenharmony_ci 944514f5e3Sopenharmony_ci // Cast -9223372036854775808 to uint64_t for comparison 954514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, static_cast<uint64_t>(9223372036854775808ULL)), true); 964514f5e3Sopenharmony_ci } 974514f5e3Sopenharmony_ci 984514f5e3Sopenharmony_ci // test ((y+max)+1) 994514f5e3Sopenharmony_ci { 1004514f5e3Sopenharmony_ci auto y = builder.Arguments(2); 1014514f5e3Sopenharmony_ci auto const_i64_max = builder.Int64(9223372036854775807); 1024514f5e3Sopenharmony_ci auto const_i64_1 = builder.Int64(1); 1034514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int64Add(builder.Int64Add(y, const_i64_max), const_i64_1)); 1044514f5e3Sopenharmony_ci Int64BinopMatcher result_m(result, &circuit); 1054514f5e3Sopenharmony_ci EXPECT_EQ(result_m.Left().Gate(), y); 1064514f5e3Sopenharmony_ci EXPECT_EQ(result_m.Right().ResolvedValue(), static_cast<uint64_t>(9223372036854775808ULL)); 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci // test ((z+1)+2) => (z+3) [z+1] not Owns 1094514f5e3Sopenharmony_ci { 1104514f5e3Sopenharmony_ci auto z = builder.Arguments(3); 1114514f5e3Sopenharmony_ci auto const_i64_1 = builder.Int64(1); 1124514f5e3Sopenharmony_ci auto const_i64_2 = builder.Int64(2); 1134514f5e3Sopenharmony_ci auto z_add_1 = builder.Int64Add(z, const_i64_1); 1144514f5e3Sopenharmony_ci auto intfer = builder.Int64Add(z_add_1, z_add_1); 1154514f5e3Sopenharmony_ci (void)intfer; 1164514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int64Add(z_add_1, const_i64_2)); 1174514f5e3Sopenharmony_ci EXPECT_EQ(result, Circuit::NullGate()); 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci} 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ci 1224514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int32AddTest) 1234514f5e3Sopenharmony_ci{ 1244514f5e3Sopenharmony_ci // construct a circuit 1254514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 1264514f5e3Sopenharmony_ci Circuit circuit(&allocator); 1274514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 1284514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 1294514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 1304514f5e3Sopenharmony_ci Environment env(0, &builder); 1314514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 1324514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 1334514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 1344514f5e3Sopenharmony_ci // test x + 0 => x 1354514f5e3Sopenharmony_ci { 1364514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 1374514f5e3Sopenharmony_ci auto const_i32_0 = builder.Int32(0); 1384514f5e3Sopenharmony_ci auto test_x_add_0 = builder.Int32Add(x, const_i32_0); 1394514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(test_x_add_0), x); 1404514f5e3Sopenharmony_ci } 1414514f5e3Sopenharmony_ci 1424514f5e3Sopenharmony_ci // test 1 + 2 => 3 1434514f5e3Sopenharmony_ci { 1444514f5e3Sopenharmony_ci auto const_i32_1 = builder.Int32(1); 1454514f5e3Sopenharmony_ci auto const_i32_2 = builder.Int32(2); 1464514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Add(const_i32_1, const_i32_2)); 1474514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, 3), true); 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci 1504514f5e3Sopenharmony_ci // Test for 32-bit integer wraparound: 2147483647 + 1 => -2147483648 1514514f5e3Sopenharmony_ci { 1524514f5e3Sopenharmony_ci auto const_i32_max = builder.Int32(2147483647); 1534514f5e3Sopenharmony_ci auto const_i32_1 = builder.Int32(1); 1544514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Add(const_i32_max, const_i32_1)); 1554514f5e3Sopenharmony_ci 1564514f5e3Sopenharmony_ci // Check if the result is -2147483648, demonstrating wraparound behavior 1574514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, static_cast<uint64_t>(-2147483648)), true); 1584514f5e3Sopenharmony_ci } 1594514f5e3Sopenharmony_ci 1604514f5e3Sopenharmony_ci 1614514f5e3Sopenharmony_ci // test (0 - x) + y => y - x 1624514f5e3Sopenharmony_ci { 1634514f5e3Sopenharmony_ci auto x = builder.Arguments(2); 1644514f5e3Sopenharmony_ci auto y = builder.Arguments(3); 1654514f5e3Sopenharmony_ci auto zero = builder.Int32(0); 1664514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Add(builder.Int32Sub(zero, x), y)); 1674514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 1684514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), y); 1694514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), x); 1704514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::SUB); 1714514f5e3Sopenharmony_ci } 1724514f5e3Sopenharmony_ci // test y + (0 - x) => y - x 1734514f5e3Sopenharmony_ci { 1744514f5e3Sopenharmony_ci auto x = builder.Arguments(4); 1754514f5e3Sopenharmony_ci auto y = builder.Arguments(5); 1764514f5e3Sopenharmony_ci auto zero = builder.Int32(0); 1774514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Add(y, builder.Int32Sub(zero, x))); 1784514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 1794514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), y); 1804514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), x); 1814514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::SUB); 1824514f5e3Sopenharmony_ci } 1834514f5e3Sopenharmony_ci 1844514f5e3Sopenharmony_ci // test ((y+1)+2) => (y+3) [y+1] Owns 1854514f5e3Sopenharmony_ci { 1864514f5e3Sopenharmony_ci auto y = builder.Arguments(6); 1874514f5e3Sopenharmony_ci auto const_1 = builder.Int32(1); 1884514f5e3Sopenharmony_ci auto const_2 = builder.Int32(2); 1894514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Add(builder.Int32Add(y, const_1), const_2)); 1904514f5e3Sopenharmony_ci Int32BinopMatcher result_m(result, &circuit); 1914514f5e3Sopenharmony_ci EXPECT_EQ(result_m.Left().Gate(), y); 1924514f5e3Sopenharmony_ci EXPECT_EQ(result_m.Right().ResolvedValue(), 3); 1934514f5e3Sopenharmony_ci } 1944514f5e3Sopenharmony_ci 1954514f5e3Sopenharmony_ci // test ((y+max)+1) 1964514f5e3Sopenharmony_ci { 1974514f5e3Sopenharmony_ci auto y = builder.Arguments(6); 1984514f5e3Sopenharmony_ci auto const_1 = builder.Int32(2147483647); 1994514f5e3Sopenharmony_ci auto const_2 = builder.Int32(1); 2004514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Add(builder.Int32Add(y, const_1), const_2)); 2014514f5e3Sopenharmony_ci Int32BinopMatcher result_m(result, &circuit); 2024514f5e3Sopenharmony_ci EXPECT_EQ(result_m.Left().Gate(), y); 2034514f5e3Sopenharmony_ci EXPECT_EQ(result_m.Right().ResolvedValue(), static_cast<uint64_t>(-2147483648)); 2044514f5e3Sopenharmony_ci } 2054514f5e3Sopenharmony_ci} 2064514f5e3Sopenharmony_ci 2074514f5e3Sopenharmony_ci 2084514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64SubTest) 2094514f5e3Sopenharmony_ci{ 2104514f5e3Sopenharmony_ci // construct a circuit 2114514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 2124514f5e3Sopenharmony_ci Circuit circuit(&allocator); 2134514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 2144514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 2154514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 2164514f5e3Sopenharmony_ci Environment env(0, &builder); 2174514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 2184514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 2194514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 2204514f5e3Sopenharmony_ci 2214514f5e3Sopenharmony_ci // test x - 0 => x 2224514f5e3Sopenharmony_ci { 2234514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 2244514f5e3Sopenharmony_ci auto const_i64_0 = builder.Int64(0); 2254514f5e3Sopenharmony_ci auto test_x_add_0 = builder.Int64Sub(x, const_i64_0); 2264514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(test_x_add_0), x); 2274514f5e3Sopenharmony_ci } 2284514f5e3Sopenharmony_ci // test 1 - 2 => -1 2294514f5e3Sopenharmony_ci { 2304514f5e3Sopenharmony_ci auto const_i64_1 = builder.Int64(1); 2314514f5e3Sopenharmony_ci auto const_i64_2 = builder.Int64(2); 2324514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int64Sub(const_i64_1, const_i64_2)); 2334514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, (int64_t)-1), true); 2344514f5e3Sopenharmony_ci } 2354514f5e3Sopenharmony_ci 2364514f5e3Sopenharmony_ci // Test for 64-bit integer wraparound subtraction: -9223372036854775808 - 1 => 9223372036854775807 2374514f5e3Sopenharmony_ci { 2384514f5e3Sopenharmony_ci auto const_i64_min = builder.Int64(-9223372036854775807 - 1); // -9223372036854775808 2394514f5e3Sopenharmony_ci auto const_i64_1 = builder.Int64(1); 2404514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int64Sub(const_i64_min, const_i64_1)); 2414514f5e3Sopenharmony_ci 2424514f5e3Sopenharmony_ci // Expect the result to wrap around to 9223372036854775807 2434514f5e3Sopenharmony_ci // Casting to uint64_t for the comparison 2444514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, static_cast<uint64_t>(9223372036854775807)), true); 2454514f5e3Sopenharmony_ci } 2464514f5e3Sopenharmony_ci 2474514f5e3Sopenharmony_ci 2484514f5e3Sopenharmony_ci // test x -x => 0 2494514f5e3Sopenharmony_ci { 2504514f5e3Sopenharmony_ci auto x = builder.Arguments(2); 2514514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int64Sub(x, x)); 2524514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, 0), true); 2534514f5e3Sopenharmony_ci } 2544514f5e3Sopenharmony_ci 2554514f5e3Sopenharmony_ci // test x - k = x + (-k) 2564514f5e3Sopenharmony_ci { 2574514f5e3Sopenharmony_ci auto x = builder.Arguments(3); 2584514f5e3Sopenharmony_ci auto const_1 = builder.Int64(-1); 2594514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int64Sub(x, const_1)); 2604514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 2614514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 2624514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), 1); 2634514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::ADD); 2644514f5e3Sopenharmony_ci } 2654514f5e3Sopenharmony_ci // Test for x - k = x + (-k) when k is the minimum int64_t value 2664514f5e3Sopenharmony_ci { 2674514f5e3Sopenharmony_ci auto x = builder.Arguments(3); 2684514f5e3Sopenharmony_ci auto const_min = builder.Int64(INT64_MIN); // Minimum int64_t value 2694514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int64Sub(x, const_min)); 2704514f5e3Sopenharmony_ci 2714514f5e3Sopenharmony_ci // Due to overflow, -k should wrap around to INT64_MIN. 2724514f5e3Sopenharmony_ci // The opcode should be ADD if the subtraction is reinterpreted as addition with -k. 2734514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 2744514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 2754514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), INT64_MIN); // Here, we expect that -k has wrapped around to INT64_MIN 2764514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::ADD); 2774514f5e3Sopenharmony_ci } 2784514f5e3Sopenharmony_ci} 2794514f5e3Sopenharmony_ci 2804514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int32SubTest) 2814514f5e3Sopenharmony_ci{ 2824514f5e3Sopenharmony_ci // construct a circuit 2834514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 2844514f5e3Sopenharmony_ci Circuit circuit(&allocator); 2854514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 2864514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 2874514f5e3Sopenharmony_ci CircuitBuilder builder(&circuit); 2884514f5e3Sopenharmony_ci Environment env(0, &builder); 2894514f5e3Sopenharmony_ci builder.SetEnvironment(&env); 2904514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 2914514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 2924514f5e3Sopenharmony_ci 2934514f5e3Sopenharmony_ci // test x - 0 => x 2944514f5e3Sopenharmony_ci { 2954514f5e3Sopenharmony_ci auto x = builder.Arguments(1); 2964514f5e3Sopenharmony_ci auto const_i32_0 = builder.Int32(0); 2974514f5e3Sopenharmony_ci auto test_x_add_0 = builder.Int32Sub(x, const_i32_0); 2984514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(test_x_add_0), x); 2994514f5e3Sopenharmony_ci } 3004514f5e3Sopenharmony_ci // test 1 - 2 => -1 3014514f5e3Sopenharmony_ci { 3024514f5e3Sopenharmony_ci auto const_i32_1 = builder.Int32(1); 3034514f5e3Sopenharmony_ci auto const_i32_2 = builder.Int32(2); 3044514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Sub(const_i32_1, const_i32_2)); 3054514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, (int32_t)-1), true); 3064514f5e3Sopenharmony_ci } 3074514f5e3Sopenharmony_ci 3084514f5e3Sopenharmony_ci // Test for 32-bit integer wraparound subtraction: -2147483648 - 1 => 2147483647 3094514f5e3Sopenharmony_ci { 3104514f5e3Sopenharmony_ci auto const_i32_min = builder.Int32(-2147483647 - 1); // -2147483648 3114514f5e3Sopenharmony_ci auto const_i32_1 = builder.Int32(1); 3124514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Sub(const_i32_min, const_i32_1)); 3134514f5e3Sopenharmony_ci 3144514f5e3Sopenharmony_ci // Expect the result to wrap around to 2147483647 3154514f5e3Sopenharmony_ci // Casting to uint64_t for the comparison, assuming IsConstantValue accepts uint64_t 3164514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, static_cast<uint64_t>(2147483647)), true); 3174514f5e3Sopenharmony_ci } 3184514f5e3Sopenharmony_ci 3194514f5e3Sopenharmony_ci // test x -x => 0 3204514f5e3Sopenharmony_ci { 3214514f5e3Sopenharmony_ci auto x = builder.Arguments(2); 3224514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Sub(x, x)); 3234514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, 0), true); 3244514f5e3Sopenharmony_ci } 3254514f5e3Sopenharmony_ci 3264514f5e3Sopenharmony_ci // test x - k = x + (-k) 3274514f5e3Sopenharmony_ci { 3284514f5e3Sopenharmony_ci auto x = builder.Arguments(3); 3294514f5e3Sopenharmony_ci auto const_1 = builder.Int32(-1); 3304514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Sub(x, const_1)); 3314514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 3324514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 3334514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), 1); 3344514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::ADD); 3354514f5e3Sopenharmony_ci } 3364514f5e3Sopenharmony_ci 3374514f5e3Sopenharmony_ci // Test for x - k = x + (-k) when k is the minimum int32_t value 3384514f5e3Sopenharmony_ci { 3394514f5e3Sopenharmony_ci auto x = builder.Arguments(3); 3404514f5e3Sopenharmony_ci auto const_min = builder.Int32(INT32_MIN); // Minimum int32_t value 3414514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(builder.Int32Sub(x, const_min)); 3424514f5e3Sopenharmony_ci 3434514f5e3Sopenharmony_ci // Due to overflow, -k should wrap around to INT32_MIN. 3444514f5e3Sopenharmony_ci // The opcode should be ADD if the subtraction is reinterpreted as addition with -k. 3454514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 3464514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 3474514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), INT32_MIN); // Here, we expect that -k has wrapped around to INT32_MIN 3484514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::ADD); 3494514f5e3Sopenharmony_ci } 3504514f5e3Sopenharmony_ci} 3514514f5e3Sopenharmony_ci 3524514f5e3Sopenharmony_ci 3534514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64MulTest) 3544514f5e3Sopenharmony_ci{ 3554514f5e3Sopenharmony_ci // construct a circuit 3564514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 3574514f5e3Sopenharmony_ci Circuit circuit(&allocator); 3584514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 3594514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 3604514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 3614514f5e3Sopenharmony_ci Environment env(0, &b); 3624514f5e3Sopenharmony_ci b.SetEnvironment(&env); 3634514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 3644514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 3654514f5e3Sopenharmony_ci 3664514f5e3Sopenharmony_ci // test x * 0 => 0 3674514f5e3Sopenharmony_ci { 3684514f5e3Sopenharmony_ci auto x = b.Arguments(1); 3694514f5e3Sopenharmony_ci auto const_0 = b.Int64(0); 3704514f5e3Sopenharmony_ci auto result = b.Int64Mul(x, const_0); 3714514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), const_0); 3724514f5e3Sopenharmony_ci } 3734514f5e3Sopenharmony_ci // test x * 1 => x 3744514f5e3Sopenharmony_ci { 3754514f5e3Sopenharmony_ci auto x = b.Arguments(1); 3764514f5e3Sopenharmony_ci auto const_1 = b.Int64(1); 3774514f5e3Sopenharmony_ci auto result = b.Int64Mul(x, const_1); 3784514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), x); 3794514f5e3Sopenharmony_ci } 3804514f5e3Sopenharmony_ci 3814514f5e3Sopenharmony_ci // test 1 * 2 => 2 3824514f5e3Sopenharmony_ci { 3834514f5e3Sopenharmony_ci auto const_1 = b.Int64(1); 3844514f5e3Sopenharmony_ci auto const_2 = b.Int64(2); 3854514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64Mul(const_1, const_2)); 3864514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, (int64_t)2), true); 3874514f5e3Sopenharmony_ci } 3884514f5e3Sopenharmony_ci // Test for 64-bit integer wraparound multiplication: 9223372036854775807 * 2 => -2 3894514f5e3Sopenharmony_ci { 3904514f5e3Sopenharmony_ci auto const_i64_max = b.Int64(9223372036854775807); // Max int64_t value 3914514f5e3Sopenharmony_ci auto const_i64_2 = b.Int64(2); 3924514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64Mul(const_i64_max, const_i64_2)); 3934514f5e3Sopenharmony_ci 3944514f5e3Sopenharmony_ci // Expect the result to wrap around to -2 3954514f5e3Sopenharmony_ci // Casting to uint64_t for the comparison 3964514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, static_cast<uint64_t>(-2)), true); 3974514f5e3Sopenharmony_ci } 3984514f5e3Sopenharmony_ci 3994514f5e3Sopenharmony_ci // test x * -1 => 0 - X 4004514f5e3Sopenharmony_ci { 4014514f5e3Sopenharmony_ci auto x = b.Arguments(2); 4024514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64Mul(x, b.Int64(-1))); 4034514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 4044514f5e3Sopenharmony_ci 4054514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().ResolvedValue(), 0); 4064514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), x); 4074514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::SUB); 4084514f5e3Sopenharmony_ci } 4094514f5e3Sopenharmony_ci 4104514f5e3Sopenharmony_ci // test x * 2^n => x << n 4114514f5e3Sopenharmony_ci { 4124514f5e3Sopenharmony_ci auto x = b.Arguments(3); 4134514f5e3Sopenharmony_ci auto const_4 = b.Int64(4); 4144514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64Mul(x, const_4)); 4154514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 4164514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 4174514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), 2); 4184514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::LSL); 4194514f5e3Sopenharmony_ci } 4204514f5e3Sopenharmony_ci 4214514f5e3Sopenharmony_ci // (x * Int64Constant(a)) * Int64Constant(b)) => x * Int64Constant(a * b) 4224514f5e3Sopenharmony_ci { 4234514f5e3Sopenharmony_ci auto x = b.Arguments(4); 4244514f5e3Sopenharmony_ci auto const_4 = b.Int64(4); 4254514f5e3Sopenharmony_ci auto const_5 = b.Int64(5); 4264514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64Mul(b.Int64Mul(x, const_4), const_5)); 4274514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 4284514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 4294514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), 20); 4304514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::MUL); 4314514f5e3Sopenharmony_ci } 4324514f5e3Sopenharmony_ci // Test for (x * Int64Constant(a)) * Int64Constant(b)) => x * Int64Constant(a * b) with overflow 4334514f5e3Sopenharmony_ci { 4344514f5e3Sopenharmony_ci auto x = b.Arguments(4); 4354514f5e3Sopenharmony_ci auto const_almost_max = b.Int64(INT64_MAX - 1); // INT64_MAX - 1 4364514f5e3Sopenharmony_ci auto const_3 = b.Int64(3); 4374514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64Mul(b.Int64Mul(x, const_almost_max), const_3)); 4384514f5e3Sopenharmony_ci 4394514f5e3Sopenharmony_ci // Due to overflow, a * b should wrap around. 4404514f5e3Sopenharmony_ci // The opcode should still be MUL. 4414514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 4424514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 4434514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), 9223372036854775802); 4444514f5e3Sopenharmony_ci 4454514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::MUL); 4464514f5e3Sopenharmony_ci } 4474514f5e3Sopenharmony_ci} 4484514f5e3Sopenharmony_ci 4494514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int32MulTest) 4504514f5e3Sopenharmony_ci{ 4514514f5e3Sopenharmony_ci // construct a circuit 4524514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 4534514f5e3Sopenharmony_ci Circuit circuit(&allocator); 4544514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 4554514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 4564514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 4574514f5e3Sopenharmony_ci Environment env(0, &b); 4584514f5e3Sopenharmony_ci b.SetEnvironment(&env); 4594514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 4604514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 4614514f5e3Sopenharmony_ci 4624514f5e3Sopenharmony_ci // test x * 0 => 0 4634514f5e3Sopenharmony_ci { 4644514f5e3Sopenharmony_ci auto x = b.Arguments(1); 4654514f5e3Sopenharmony_ci auto const_0 = b.Int32(0); 4664514f5e3Sopenharmony_ci auto result = b.Int32Mul(x, const_0); 4674514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), const_0); 4684514f5e3Sopenharmony_ci } 4694514f5e3Sopenharmony_ci // test x * 1 => x 4704514f5e3Sopenharmony_ci { 4714514f5e3Sopenharmony_ci auto x = b.Arguments(1); 4724514f5e3Sopenharmony_ci auto const_1 = b.Int32(1); 4734514f5e3Sopenharmony_ci auto result = b.Int32Mul(x, const_1); 4744514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), x); 4754514f5e3Sopenharmony_ci } 4764514f5e3Sopenharmony_ci 4774514f5e3Sopenharmony_ci 4784514f5e3Sopenharmony_ci // test 1 * 2 => 2 4794514f5e3Sopenharmony_ci { 4804514f5e3Sopenharmony_ci auto const_1 = b.Int32(1); 4814514f5e3Sopenharmony_ci auto const_2 = b.Int32(2); 4824514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Mul(const_1, const_2)); 4834514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 4844514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, (int32_t)2), true); 4854514f5e3Sopenharmony_ci } 4864514f5e3Sopenharmony_ci 4874514f5e3Sopenharmony_ci // Test for 32-bit integer wraparound multiplication: 2147483647 * 2 => -2 4884514f5e3Sopenharmony_ci { 4894514f5e3Sopenharmony_ci auto const_i32_max = b.Int32(2147483647); // Max int32_t value 4904514f5e3Sopenharmony_ci auto const_i32_2 = b.Int32(2); 4914514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Mul(const_i32_max, const_i32_2)); 4924514f5e3Sopenharmony_ci 4934514f5e3Sopenharmony_ci // Expect the result to wrap around to -2 4944514f5e3Sopenharmony_ci // Casting to uint32_t for the comparison 4954514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 4964514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetInt32FromConstant(result), -2); 4974514f5e3Sopenharmony_ci } 4984514f5e3Sopenharmony_ci 4994514f5e3Sopenharmony_ci 5004514f5e3Sopenharmony_ci // test x * -1 => 0 - X 5014514f5e3Sopenharmony_ci { 5024514f5e3Sopenharmony_ci auto x = b.Arguments(2); 5034514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Mul(x, b.Int32(-1))); 5044514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 5054514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 5064514f5e3Sopenharmony_ci 5074514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().ResolvedValue(), 0); 5084514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), x); 5094514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::SUB); 5104514f5e3Sopenharmony_ci } 5114514f5e3Sopenharmony_ci 5124514f5e3Sopenharmony_ci // test x * 2^n => x << n 5134514f5e3Sopenharmony_ci { 5144514f5e3Sopenharmony_ci auto x = b.Arguments(3); 5154514f5e3Sopenharmony_ci auto const_4 = b.Int32(4); 5164514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Mul(x, const_4)); 5174514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 5184514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 5194514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 5204514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), 2); 5214514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::LSL); 5224514f5e3Sopenharmony_ci } 5234514f5e3Sopenharmony_ci 5244514f5e3Sopenharmony_ci // (x * Int32Constant(a)) * Int32Constant(b)) => x * Int32Constant(a * b) 5254514f5e3Sopenharmony_ci { 5264514f5e3Sopenharmony_ci auto x = b.Arguments(4); 5274514f5e3Sopenharmony_ci auto const_4 = b.Int32(4); 5284514f5e3Sopenharmony_ci auto const_5 = b.Int32(5); 5294514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Mul(b.Int32Mul(x, const_4), const_5)); 5304514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 5314514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 5324514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 5334514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), 20); 5344514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::MUL); 5354514f5e3Sopenharmony_ci } 5364514f5e3Sopenharmony_ci // Test for (x * Int32Constant(a)) * Int32Constant(b)) => x * Int32Constant(a * b) with overflow 5374514f5e3Sopenharmony_ci { 5384514f5e3Sopenharmony_ci auto x = b.Arguments(4); 5394514f5e3Sopenharmony_ci auto const_almost_max = b.Int32(INT32_MAX - 1); // INT32_MAX - 1 5404514f5e3Sopenharmony_ci auto const_3 = b.Int32(3); 5414514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Mul(b.Int32Mul(x, const_almost_max), const_3)); 5424514f5e3Sopenharmony_ci 5434514f5e3Sopenharmony_ci // Due to overflow, a * b should wrap around. 5444514f5e3Sopenharmony_ci // The opcode should still be MUL. 5454514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 5464514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 5474514f5e3Sopenharmony_ci 5484514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().ResolvedValue(), static_cast<uint32_t>(2147483642)); 5494514f5e3Sopenharmony_ci 5504514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::MUL); 5514514f5e3Sopenharmony_ci } 5524514f5e3Sopenharmony_ci} 5534514f5e3Sopenharmony_ci 5544514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64DivTest) 5554514f5e3Sopenharmony_ci{ 5564514f5e3Sopenharmony_ci // construct a circuit 5574514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 5584514f5e3Sopenharmony_ci Circuit circuit(&allocator); 5594514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 5604514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 5614514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 5624514f5e3Sopenharmony_ci Environment env(0, &b); 5634514f5e3Sopenharmony_ci b.SetEnvironment(&env); 5644514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 5654514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 5664514f5e3Sopenharmony_ci 5674514f5e3Sopenharmony_ci // test 0/x => 0 5684514f5e3Sopenharmony_ci { 5694514f5e3Sopenharmony_ci auto x = b.Arguments(1); 5704514f5e3Sopenharmony_ci auto const_0 = b.Int64(0); 5714514f5e3Sopenharmony_ci auto result = b.Int64Div(const_0, x); 5724514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), const_0); 5734514f5e3Sopenharmony_ci } 5744514f5e3Sopenharmony_ci 5754514f5e3Sopenharmony_ci 5764514f5e3Sopenharmony_ci // test x/0 => 0 5774514f5e3Sopenharmony_ci { 5784514f5e3Sopenharmony_ci auto x = b.Arguments(1); 5794514f5e3Sopenharmony_ci auto const_0 = b.Int64(0); 5804514f5e3Sopenharmony_ci auto result = b.Int64Div(x, const_0); 5814514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), const_0); 5824514f5e3Sopenharmony_ci } 5834514f5e3Sopenharmony_ci 5844514f5e3Sopenharmony_ci // test x / 1 => x 5854514f5e3Sopenharmony_ci { 5864514f5e3Sopenharmony_ci auto x = b.Arguments(1); 5874514f5e3Sopenharmony_ci auto const_1 = b.Int64(1); 5884514f5e3Sopenharmony_ci auto result = b.Int64Div(x, const_1); 5894514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), x); 5904514f5e3Sopenharmony_ci } 5914514f5e3Sopenharmony_ci 5924514f5e3Sopenharmony_ci // test 4 / 2 => 4 5934514f5e3Sopenharmony_ci { 5944514f5e3Sopenharmony_ci auto const_4 = b.Int64(4); 5954514f5e3Sopenharmony_ci auto const_2 = b.Int64(2); 5964514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64Div(const_4, const_2)); 5974514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 5984514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, (int64_t)2), true); 5994514f5e3Sopenharmony_ci } 6004514f5e3Sopenharmony_ci 6014514f5e3Sopenharmony_ci // test x / -1 => 0 - X 6024514f5e3Sopenharmony_ci { 6034514f5e3Sopenharmony_ci auto x = b.Arguments(2); 6044514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64Div(x, b.Int64(-1))); 6054514f5e3Sopenharmony_ci 6064514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 6074514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 6084514f5e3Sopenharmony_ci 6094514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().ResolvedValue(), 0); 6104514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), x); 6114514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::SUB); 6124514f5e3Sopenharmony_ci } 6134514f5e3Sopenharmony_ci 6144514f5e3Sopenharmony_ci // test x / -5 => 0 - x / 5 6154514f5e3Sopenharmony_ci { 6164514f5e3Sopenharmony_ci auto x = b.Arguments(2); 6174514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64Div(x, b.Int64(-5))); 6184514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 6194514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 6204514f5e3Sopenharmony_ci 6214514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().ResolvedValue(), 0); 6224514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::SUB); 6234514f5e3Sopenharmony_ci Int64BinopMatcher m_right(m.Right().Gate(), &circuit); 6244514f5e3Sopenharmony_ci 6254514f5e3Sopenharmony_ci EXPECT_EQ(m_right.Left().Gate(), x); 6264514f5e3Sopenharmony_ci EXPECT_EQ(m_right.Opcode(), OpCode::SDIV); 6274514f5e3Sopenharmony_ci EXPECT_EQ(m_right.Right().ResolvedValue(), 5); 6284514f5e3Sopenharmony_ci } 6294514f5e3Sopenharmony_ci} 6304514f5e3Sopenharmony_ci 6314514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int32DivTest) 6324514f5e3Sopenharmony_ci{ 6334514f5e3Sopenharmony_ci // construct a circuit 6344514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 6354514f5e3Sopenharmony_ci Circuit circuit(&allocator); 6364514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 6374514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 6384514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 6394514f5e3Sopenharmony_ci Environment env(0, &b); 6404514f5e3Sopenharmony_ci b.SetEnvironment(&env); 6414514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 6424514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 6434514f5e3Sopenharmony_ci 6444514f5e3Sopenharmony_ci // test 0/x => 0 6454514f5e3Sopenharmony_ci { 6464514f5e3Sopenharmony_ci auto x = b.Arguments(1); 6474514f5e3Sopenharmony_ci auto const_0 = b.Int32(0); 6484514f5e3Sopenharmony_ci auto result = b.Int32Div(const_0, x); 6494514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), const_0); 6504514f5e3Sopenharmony_ci } 6514514f5e3Sopenharmony_ci 6524514f5e3Sopenharmony_ci 6534514f5e3Sopenharmony_ci // test x/0 => 0 6544514f5e3Sopenharmony_ci { 6554514f5e3Sopenharmony_ci auto x = b.Arguments(1); 6564514f5e3Sopenharmony_ci auto const_0 = b.Int32(0); 6574514f5e3Sopenharmony_ci auto result = b.Int32Div(x, const_0); 6584514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), const_0); 6594514f5e3Sopenharmony_ci } 6604514f5e3Sopenharmony_ci 6614514f5e3Sopenharmony_ci // test x / 1 => x 6624514f5e3Sopenharmony_ci { 6634514f5e3Sopenharmony_ci auto x = b.Arguments(1); 6644514f5e3Sopenharmony_ci auto const_1 = b.Int32(1); 6654514f5e3Sopenharmony_ci auto result = b.Int32Div(x, const_1); 6664514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(result), x); 6674514f5e3Sopenharmony_ci } 6684514f5e3Sopenharmony_ci 6694514f5e3Sopenharmony_ci // test 4 / 2 => 4 6704514f5e3Sopenharmony_ci { 6714514f5e3Sopenharmony_ci auto const_4 = b.Int32(4); 6724514f5e3Sopenharmony_ci auto const_2 = b.Int32(2); 6734514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Div(const_4, const_2)); 6744514f5e3Sopenharmony_ci 6754514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 6764514f5e3Sopenharmony_ci EXPECT_EQ(acc.IsConstantValue(result, (int32_t)2), true); 6774514f5e3Sopenharmony_ci } 6784514f5e3Sopenharmony_ci 6794514f5e3Sopenharmony_ci // test x / -1 => 0 - X 6804514f5e3Sopenharmony_ci { 6814514f5e3Sopenharmony_ci auto x = b.Arguments(2); 6824514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Div(x, b.Int32(-1))); 6834514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 6844514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 6854514f5e3Sopenharmony_ci 6864514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().ResolvedValue(), 0); 6874514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), x); 6884514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::SUB); 6894514f5e3Sopenharmony_ci } 6904514f5e3Sopenharmony_ci 6914514f5e3Sopenharmony_ci // test x / -5 => 0 - x / 5 6924514f5e3Sopenharmony_ci { 6934514f5e3Sopenharmony_ci auto x = b.Arguments(2); 6944514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Div(x, b.Int32(-5))); 6954514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 6964514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 6974514f5e3Sopenharmony_ci 6984514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().ResolvedValue(), 0); 6994514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::SUB); 7004514f5e3Sopenharmony_ci Int32BinopMatcher m_right(m.Right().Gate(), &circuit); 7014514f5e3Sopenharmony_ci 7024514f5e3Sopenharmony_ci EXPECT_EQ(m_right.Left().Gate(), x); 7034514f5e3Sopenharmony_ci EXPECT_EQ(m_right.Opcode(), OpCode::SDIV); 7044514f5e3Sopenharmony_ci EXPECT_EQ(m_right.Right().ResolvedValue(), 5); 7054514f5e3Sopenharmony_ci } 7064514f5e3Sopenharmony_ci} 7074514f5e3Sopenharmony_ci 7084514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, DoubleBinOptest) 7094514f5e3Sopenharmony_ci{ 7104514f5e3Sopenharmony_ci // construct a circuit 7114514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 7124514f5e3Sopenharmony_ci Circuit circuit(&allocator); 7134514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 7144514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 7154514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 7164514f5e3Sopenharmony_ci Environment env(0, &b); 7174514f5e3Sopenharmony_ci b.SetEnvironment(&env); 7184514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 7194514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 7204514f5e3Sopenharmony_ci 7214514f5e3Sopenharmony_ci // test x op NaN => NaN 7224514f5e3Sopenharmony_ci { 7234514f5e3Sopenharmony_ci auto x = b.Arguments(1); 7244514f5e3Sopenharmony_ci auto nan = b.NanValue(); 7254514f5e3Sopenharmony_ci auto zero = b.Double(0); 7264514f5e3Sopenharmony_ci Float64Matcher nan_m(nan, &circuit); 7274514f5e3Sopenharmony_ci EXPECT_EQ(nan_m.HasResolvedValue(), true); 7284514f5e3Sopenharmony_ci 7294514f5e3Sopenharmony_ci 7304514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.DoubleAdd(x, nan)), nan); 7314514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.DoubleSub(x, nan)), nan); 7324514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.DoubleMul(x, nan)), nan); 7334514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.DoubleDiv(x, nan)), nan); 7344514f5e3Sopenharmony_ci // x % 0 => NaN 7354514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.DoubleMod(x, zero)), nan); 7364514f5e3Sopenharmony_ci } 7374514f5e3Sopenharmony_ci // test NaN op op => NaN 7384514f5e3Sopenharmony_ci { 7394514f5e3Sopenharmony_ci auto x = b.Arguments(1); 7404514f5e3Sopenharmony_ci auto nan = b.NanValue(); 7414514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.DoubleAdd(nan, x)), nan); 7424514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.DoubleSub(nan, x)), nan); 7434514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.DoubleDiv(nan, x)), nan); 7444514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.DoubleMod(nan, x)), nan); 7454514f5e3Sopenharmony_ci } 7464514f5e3Sopenharmony_ci 7474514f5e3Sopenharmony_ci // test 10.4 op 5.2 => ? 7484514f5e3Sopenharmony_ci { 7494514f5e3Sopenharmony_ci auto value1 = b.Double(10.1); 7504514f5e3Sopenharmony_ci auto value2 = b.Double(5.2); 7514514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.DoubleAdd(value1, value2)); 7524514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 7534514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetOpCode(result), OpCode::CONSTANT); 7544514f5e3Sopenharmony_ci 7554514f5e3Sopenharmony_ci result = instcombie.VisitGate(b.DoubleAdd(value1, value2)); 7564514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 7574514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetOpCode(result), OpCode::CONSTANT); 7584514f5e3Sopenharmony_ci 7594514f5e3Sopenharmony_ci result = instcombie.VisitGate(b.DoubleSub(value1, value2)); 7604514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 7614514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetOpCode(result), OpCode::CONSTANT); 7624514f5e3Sopenharmony_ci 7634514f5e3Sopenharmony_ci result = instcombie.VisitGate(b.DoubleDiv(value1, value2)); 7644514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 7654514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetOpCode(result), OpCode::CONSTANT); 7664514f5e3Sopenharmony_ci } 7674514f5e3Sopenharmony_ci 7684514f5e3Sopenharmony_ci // test x * -1.0 => -0.0 - x 7694514f5e3Sopenharmony_ci { 7704514f5e3Sopenharmony_ci auto x = b.Arguments(1); 7714514f5e3Sopenharmony_ci auto neg_one = b.Double(-1); 7724514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.DoubleMul(x, neg_one)); 7734514f5e3Sopenharmony_ci 7744514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 7754514f5e3Sopenharmony_ci Float64BinopMatcher m(result, &circuit); 7764514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::SUB); 7774514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().ResolvedValue(), -0.0); 7784514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), x); 7794514f5e3Sopenharmony_ci } 7804514f5e3Sopenharmony_ci 7814514f5e3Sopenharmony_ci // test x * -1.0 => -0.0 - x 7824514f5e3Sopenharmony_ci { 7834514f5e3Sopenharmony_ci auto x = b.Arguments(1); 7844514f5e3Sopenharmony_ci auto two = b.Double(2.0); 7854514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.DoubleMul(x, two)); 7864514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 7874514f5e3Sopenharmony_ci Float64BinopMatcher m(result, &circuit); 7884514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::ADD); 7894514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 7904514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), x); 7914514f5e3Sopenharmony_ci } 7924514f5e3Sopenharmony_ci} 7934514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int32Modtest) 7944514f5e3Sopenharmony_ci{ 7954514f5e3Sopenharmony_ci // construct a circuit 7964514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 7974514f5e3Sopenharmony_ci Circuit circuit(&allocator); 7984514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 7994514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 8004514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 8014514f5e3Sopenharmony_ci Environment env(0, &b); 8024514f5e3Sopenharmony_ci b.SetEnvironment(&env); 8034514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 8044514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 8054514f5e3Sopenharmony_ci { 8064514f5e3Sopenharmony_ci auto x = b.Arguments(1); 8074514f5e3Sopenharmony_ci auto zero = b.Int32(0); 8084514f5e3Sopenharmony_ci auto one = b.Int32(1); 8094514f5e3Sopenharmony_ci auto neg_one = b.Int32(-1); 8104514f5e3Sopenharmony_ci auto four = b.Int32(4); 8114514f5e3Sopenharmony_ci auto two = b.Int32(2); 8124514f5e3Sopenharmony_ci 8134514f5e3Sopenharmony_ci // 0 % x => 0 8144514f5e3Sopenharmony_ci // x % 0 => 0 8154514f5e3Sopenharmony_ci // x % 1 => 0 8164514f5e3Sopenharmony_ci // x % -1 => 0 8174514f5e3Sopenharmony_ci // x % x => 0 8184514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Mod(x, zero)), zero); 8194514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Mod(zero, x)), zero); 8204514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Mod(x, one)), zero); 8214514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Mod(x, neg_one)), zero); 8224514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Mod(x, x)), zero); 8234514f5e3Sopenharmony_ci // 2%4 =>2 8244514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Mod(two, four)), two); 8254514f5e3Sopenharmony_ci } 8264514f5e3Sopenharmony_ci} 8274514f5e3Sopenharmony_ci 8284514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int32AddOverFlowtest) 8294514f5e3Sopenharmony_ci{ 8304514f5e3Sopenharmony_ci // construct a circuit 8314514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 8324514f5e3Sopenharmony_ci Circuit circuit(&allocator); 8334514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 8344514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 8354514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 8364514f5e3Sopenharmony_ci Environment env(0, &b); 8374514f5e3Sopenharmony_ci b.SetEnvironment(&env); 8384514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 8394514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 8404514f5e3Sopenharmony_ci 8414514f5e3Sopenharmony_ci // IsFoldable overflow 8424514f5e3Sopenharmony_ci // 2147483647 + 1 =-2147483648 8434514f5e3Sopenharmony_ci { 8444514f5e3Sopenharmony_ci auto add_overflow = b.AddWithOverflow(b.Int32(2147483647), b.Int32(1)); 8454514f5e3Sopenharmony_ci auto add_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, add_overflow, b.Int32(0)); 8464514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, add_overflow, b.Int32(1)); 8474514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetInt32FromConstant(instcombie.VisitGate(add_result)), -2147483648); 8484514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(true)); 8494514f5e3Sopenharmony_ci } 8504514f5e3Sopenharmony_ci 8514514f5e3Sopenharmony_ci // IsFoldable no overflow 8524514f5e3Sopenharmony_ci { 8534514f5e3Sopenharmony_ci auto add_overflow = b.AddWithOverflow(b.Int32(2147483646), b.Int32(1)); 8544514f5e3Sopenharmony_ci auto add_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, add_overflow, b.Int32(0)); 8554514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, add_overflow, b.Int32(1)); 8564514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetInt32FromConstant(instcombie.VisitGate(add_result)), 2147483647); 8574514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(false)); 8584514f5e3Sopenharmony_ci } 8594514f5e3Sopenharmony_ci 8604514f5e3Sopenharmony_ci 8614514f5e3Sopenharmony_ci // x add 0 => 0 8624514f5e3Sopenharmony_ci // IsFoldable no overflow 8634514f5e3Sopenharmony_ci { 8644514f5e3Sopenharmony_ci auto x = b.Arguments(1); 8654514f5e3Sopenharmony_ci auto add_overflow = b.AddWithOverflow(x, b.Int32(0)); 8664514f5e3Sopenharmony_ci auto add_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, add_overflow, b.Int32(0)); 8674514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, add_overflow, b.Int32(1)); 8684514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(add_result), x); 8694514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(false)); 8704514f5e3Sopenharmony_ci } 8714514f5e3Sopenharmony_ci} 8724514f5e3Sopenharmony_ci 8734514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int32SubOverFlowTest) 8744514f5e3Sopenharmony_ci{ 8754514f5e3Sopenharmony_ci // construct a circuit 8764514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 8774514f5e3Sopenharmony_ci Circuit circuit(&allocator); 8784514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 8794514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 8804514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 8814514f5e3Sopenharmony_ci Environment env(0, &b); 8824514f5e3Sopenharmony_ci b.SetEnvironment(&env); 8834514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 8844514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 8854514f5e3Sopenharmony_ci 8864514f5e3Sopenharmony_ci // IsFoldable overflow 8874514f5e3Sopenharmony_ci // -2147483648 - 1 = 2147483647 8884514f5e3Sopenharmony_ci { 8894514f5e3Sopenharmony_ci auto sub_overflow = b.SubWithOverflow(b.Int32(-2147483648), b.Int32(1)); 8904514f5e3Sopenharmony_ci auto sub_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, sub_overflow, b.Int32(0)); 8914514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, sub_overflow, b.Int32(1)); 8924514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetInt32FromConstant(instcombie.VisitGate(sub_result)), 2147483647); 8934514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(true)); 8944514f5e3Sopenharmony_ci } 8954514f5e3Sopenharmony_ci 8964514f5e3Sopenharmony_ci // IsFoldable no overflow 8974514f5e3Sopenharmony_ci { 8984514f5e3Sopenharmony_ci auto sub_overflow = b.SubWithOverflow(b.Int32(2147483647), b.Int32(1)); 8994514f5e3Sopenharmony_ci auto sub_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, sub_overflow, b.Int32(0)); 9004514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, sub_overflow, b.Int32(1)); 9014514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetInt32FromConstant(instcombie.VisitGate(sub_result)), 2147483646); 9024514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(false)); 9034514f5e3Sopenharmony_ci } 9044514f5e3Sopenharmony_ci 9054514f5e3Sopenharmony_ci // x sub 0 => x 9064514f5e3Sopenharmony_ci // IsFoldable no overflow 9074514f5e3Sopenharmony_ci { 9084514f5e3Sopenharmony_ci auto x = b.Arguments(1); 9094514f5e3Sopenharmony_ci auto sub_overflow = b.SubWithOverflow(x, b.Int32(0)); 9104514f5e3Sopenharmony_ci auto sub_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, sub_overflow, b.Int32(0)); 9114514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, sub_overflow, b.Int32(1)); 9124514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(sub_result), x); 9134514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(false)); 9144514f5e3Sopenharmony_ci } 9154514f5e3Sopenharmony_ci} 9164514f5e3Sopenharmony_ci 9174514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int32MulOverFlowTest) 9184514f5e3Sopenharmony_ci{ 9194514f5e3Sopenharmony_ci // construct a circuit 9204514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 9214514f5e3Sopenharmony_ci Circuit circuit(&allocator); 9224514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 9234514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 9244514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 9254514f5e3Sopenharmony_ci Environment env(0, &b); 9264514f5e3Sopenharmony_ci b.SetEnvironment(&env); 9274514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 9284514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 9294514f5e3Sopenharmony_ci 9304514f5e3Sopenharmony_ci // IsFoldable overflow 9314514f5e3Sopenharmony_ci // 2147483647 * 2 = -2 9324514f5e3Sopenharmony_ci { 9334514f5e3Sopenharmony_ci auto mul_overflow = b.MulWithOverflow(b.Int32(2147483647), b.Int32(2)); 9344514f5e3Sopenharmony_ci auto mul_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, mul_overflow, b.Int32(0)); 9354514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, mul_overflow, b.Int32(1)); 9364514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetInt32FromConstant(instcombie.VisitGate(mul_result)), -2); 9374514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(true)); 9384514f5e3Sopenharmony_ci } 9394514f5e3Sopenharmony_ci 9404514f5e3Sopenharmony_ci // IsFoldable no overflow 9414514f5e3Sopenharmony_ci // 1000 * 2 = 2000 9424514f5e3Sopenharmony_ci { 9434514f5e3Sopenharmony_ci auto mul_overflow = b.MulWithOverflow(b.Int32(1000), b.Int32(2)); 9444514f5e3Sopenharmony_ci auto mul_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, mul_overflow, b.Int32(0)); 9454514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, mul_overflow, b.Int32(1)); 9464514f5e3Sopenharmony_ci EXPECT_EQ(acc.GetInt32FromConstant(instcombie.VisitGate(mul_result)), 2000); 9474514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(false)); 9484514f5e3Sopenharmony_ci } 9494514f5e3Sopenharmony_ci 9504514f5e3Sopenharmony_ci // x * 1 => x 9514514f5e3Sopenharmony_ci // IsFoldable no overflow 9524514f5e3Sopenharmony_ci { 9534514f5e3Sopenharmony_ci auto x = b.Arguments(1); 9544514f5e3Sopenharmony_ci auto mul_overflow = b.MulWithOverflow(x, b.Int32(1)); 9554514f5e3Sopenharmony_ci auto mul_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, mul_overflow, b.Int32(0)); 9564514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, mul_overflow, b.Int32(1)); 9574514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(mul_result), x); 9584514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(false)); 9594514f5e3Sopenharmony_ci } 9604514f5e3Sopenharmony_ci 9614514f5e3Sopenharmony_ci // x * 0 => 0 9624514f5e3Sopenharmony_ci // IsFoldable no overflow 9634514f5e3Sopenharmony_ci { 9644514f5e3Sopenharmony_ci auto x = b.Arguments(1); 9654514f5e3Sopenharmony_ci auto mul_overflow = b.MulWithOverflow(x, b.Int32(0)); 9664514f5e3Sopenharmony_ci auto mul_result = b.ExtractValue(ecmascript::kungfu::MachineType::I32, mul_overflow, b.Int32(0)); 9674514f5e3Sopenharmony_ci auto is_over = b.ExtractValue(ecmascript::kungfu::MachineType::I1, mul_overflow, b.Int32(1)); 9684514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(mul_result), b.Int32(0)); 9694514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(is_over), b.Boolean(false)); 9704514f5e3Sopenharmony_ci } 9714514f5e3Sopenharmony_ci} 9724514f5e3Sopenharmony_ci 9734514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64_32AndTest) 9744514f5e3Sopenharmony_ci{ 9754514f5e3Sopenharmony_ci // construct a circuit 9764514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 9774514f5e3Sopenharmony_ci Circuit circuit(&allocator); 9784514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 9794514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 9804514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 9814514f5e3Sopenharmony_ci Environment env(0, &b); 9824514f5e3Sopenharmony_ci b.SetEnvironment(&env); 9834514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 9844514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 9854514f5e3Sopenharmony_ci { 9864514f5e3Sopenharmony_ci auto x = b.Arguments(1); 9874514f5e3Sopenharmony_ci auto zero = b.Int64(0); 9884514f5e3Sopenharmony_ci auto neg_one = b.Int64(-1); 9894514f5e3Sopenharmony_ci auto Icmp = b.Equal(x, zero); 9904514f5e3Sopenharmony_ci auto one = b.Int64(1); 9914514f5e3Sopenharmony_ci auto two = b.Int64(2); 9924514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64And(x, zero)), zero); // x & 0 => 0 9934514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64And(x, neg_one)), x); // x & -1 => x 9944514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64And(Icmp, one)), Icmp); // CMP & 1 => CMP 9954514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64And(two, one)), zero); // K & K => K 9964514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64And(x, x)), x); // x & x => x 9974514f5e3Sopenharmony_ci // (x & 1) & 2 => x & 0 9984514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int64And(b.Int64And(x, one), two)); 9994514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 10004514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 10014514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 10024514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::AND); 10034514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), zero); 10044514f5e3Sopenharmony_ci } 10054514f5e3Sopenharmony_ci 10064514f5e3Sopenharmony_ci { 10074514f5e3Sopenharmony_ci auto x = b.Arguments(2); 10084514f5e3Sopenharmony_ci auto zero = b.Int32(0); 10094514f5e3Sopenharmony_ci auto neg_one = b.Int32(-1); 10104514f5e3Sopenharmony_ci auto Icmp = b.Equal(x, zero); 10114514f5e3Sopenharmony_ci auto one = b.Int32(1); 10124514f5e3Sopenharmony_ci auto two = b.Int32(2); 10134514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32And(x, zero)), zero); // x & 0 => 0 10144514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32And(x, neg_one)), x); // x & -1 => x 10154514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32And(Icmp, one)), Icmp); // CMP & 1 => CMP 10164514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32And(two, one)), zero); // K & K => K 10174514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32And(x, x)), x); // x & x => x 10184514f5e3Sopenharmony_ci // (x & 1) & 2 => x & 0 10194514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32And(b.Int32And(x, one), two)); 10204514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 10214514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 10224514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 10234514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::AND); 10244514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), zero); 10254514f5e3Sopenharmony_ci } 10264514f5e3Sopenharmony_ci} 10274514f5e3Sopenharmony_ci 10284514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64_32OrTest) 10294514f5e3Sopenharmony_ci{ 10304514f5e3Sopenharmony_ci // construct a circuit 10314514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 10324514f5e3Sopenharmony_ci Circuit circuit(&allocator); 10334514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 10344514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 10354514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 10364514f5e3Sopenharmony_ci Environment env(0, &b); 10374514f5e3Sopenharmony_ci b.SetEnvironment(&env); 10384514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 10394514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 10404514f5e3Sopenharmony_ci { 10414514f5e3Sopenharmony_ci auto x = b.Arguments(1); 10424514f5e3Sopenharmony_ci auto zero = b.Int64(0); 10434514f5e3Sopenharmony_ci auto neg_one = b.Int64(-1); 10444514f5e3Sopenharmony_ci auto one = b.Int64(1); 10454514f5e3Sopenharmony_ci auto two = b.Int64(2); 10464514f5e3Sopenharmony_ci auto three = b.Int64(3); 10474514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64Or(x, zero)), x); // x | 0 => x 10484514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64Or(x, neg_one)), neg_one); // x | -1 => -1 10494514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64Or(two, one)), three); // 2 | 1 => 3 10504514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64Or(x, x)), x); // x | x => x 10514514f5e3Sopenharmony_ci // (x & K1) | K2 => x | K2 if K2 has ones for every zero bit in K1. 10524514f5e3Sopenharmony_ci auto result = instcombie.VisitGate( 10534514f5e3Sopenharmony_ci b.Int64Or(b.Int64And(x, b.Int64(-6148914691236517205L)), b.Int64(6148914691236517205L))); 10544514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 10554514f5e3Sopenharmony_ci Int64BinopMatcher m(result, &circuit); 10564514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 10574514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::OR); 10584514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), b.Int64(6148914691236517205L)); 10594514f5e3Sopenharmony_ci } 10604514f5e3Sopenharmony_ci 10614514f5e3Sopenharmony_ci { 10624514f5e3Sopenharmony_ci auto x = b.Arguments(1); 10634514f5e3Sopenharmony_ci auto zero = b.Int32(0); 10644514f5e3Sopenharmony_ci auto neg_one = b.Int32(-1); 10654514f5e3Sopenharmony_ci auto one = b.Int32(1); 10664514f5e3Sopenharmony_ci auto two = b.Int32(2); 10674514f5e3Sopenharmony_ci auto three = b.Int32(3); 10684514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Or(x, zero)), x); // x | 0 => x 10694514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Or(x, neg_one)), neg_one); // x | -1 => -1 10704514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Or(two, one)), three); // 2 | 1 => 3 10714514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Or(x, x)), x); // x | x => x 10724514f5e3Sopenharmony_ci // (x & K1) | K2 => x | K2 if K2 has ones for every zero bit in K1. 10734514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Int32Or(b.Int32And(x, b.Int32(-1431655765)), b.Int32(1431655765))); 10744514f5e3Sopenharmony_ci EXPECT_NE(result, Circuit::NullGate()); 10754514f5e3Sopenharmony_ci Int32BinopMatcher m(result, &circuit); 10764514f5e3Sopenharmony_ci EXPECT_EQ(m.Left().Gate(), x); 10774514f5e3Sopenharmony_ci EXPECT_EQ(m.Opcode(), OpCode::OR); 10784514f5e3Sopenharmony_ci EXPECT_EQ(m.Right().Gate(), b.Int32(1431655765)); 10794514f5e3Sopenharmony_ci } 10804514f5e3Sopenharmony_ci} 10814514f5e3Sopenharmony_ci 10824514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64_32XOrTest) 10834514f5e3Sopenharmony_ci{ 10844514f5e3Sopenharmony_ci // construct a circuit 10854514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 10864514f5e3Sopenharmony_ci Circuit circuit(&allocator); 10874514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 10884514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 10894514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 10904514f5e3Sopenharmony_ci Environment env(0, &b); 10914514f5e3Sopenharmony_ci b.SetEnvironment(&env); 10924514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 10934514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 10944514f5e3Sopenharmony_ci { 10954514f5e3Sopenharmony_ci auto x = b.Arguments(1); 10964514f5e3Sopenharmony_ci auto zero = b.Int64(0); 10974514f5e3Sopenharmony_ci auto neg_one = b.Int64(-1); 10984514f5e3Sopenharmony_ci auto one = b.Int64(1); 10994514f5e3Sopenharmony_ci auto two = b.Int64(2); 11004514f5e3Sopenharmony_ci auto three = b.Int64(3); 11014514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64Xor(x, zero)), x); // x ^ 0 => x 11024514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64Xor(two, one)), three); // 2 | 1 => 3 11034514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64Xor(x, x)), zero); // x ^ x => 0 11044514f5e3Sopenharmony_ci // (x ^ -1) ^ -1 => x 11054514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64Xor(b.Int64Xor(x, neg_one), neg_one)), x); 11064514f5e3Sopenharmony_ci } 11074514f5e3Sopenharmony_ci 11084514f5e3Sopenharmony_ci { 11094514f5e3Sopenharmony_ci auto x = b.Arguments(1); 11104514f5e3Sopenharmony_ci auto zero = b.Int32(0); 11114514f5e3Sopenharmony_ci auto neg_one = b.Int32(-1); 11124514f5e3Sopenharmony_ci auto one = b.Int32(1); 11134514f5e3Sopenharmony_ci auto two = b.Int32(2); 11144514f5e3Sopenharmony_ci auto three = b.Int32(3); 11154514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Xor(x, zero)), x); // x ^ 0 => x 11164514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Xor(two, one)), three); // 2 | 1 => 3 11174514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Xor(x, x)), zero); // x ^ x => 0 11184514f5e3Sopenharmony_ci // (x ^ -1) ^ -1 => x 11194514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32Xor(b.Int32Xor(x, neg_one), neg_one)), x); 11204514f5e3Sopenharmony_ci } 11214514f5e3Sopenharmony_ci} 11224514f5e3Sopenharmony_ci 11234514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64_32LsrTest) 11244514f5e3Sopenharmony_ci{ 11254514f5e3Sopenharmony_ci // construct a circuit 11264514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 11274514f5e3Sopenharmony_ci Circuit circuit(&allocator); 11284514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 11294514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 11304514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 11314514f5e3Sopenharmony_ci Environment env(0, &b); 11324514f5e3Sopenharmony_ci b.SetEnvironment(&env); 11334514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 11344514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 11354514f5e3Sopenharmony_ci 11364514f5e3Sopenharmony_ci { 11374514f5e3Sopenharmony_ci auto x = b.Arguments(1); 11384514f5e3Sopenharmony_ci auto zero = b.Int64(0); 11394514f5e3Sopenharmony_ci auto two = b.Int64(2); 11404514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64LSR(x, zero)), x); // x >>> 0 => x 11414514f5e3Sopenharmony_ci // (u)-8 >> 2 => 4611686018427387902u 11424514f5e3Sopenharmony_ci // 8 >> 2 => 2 11434514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64LSR(b.Int64(-8), two)), b.Int64(4611686018427387902u)); 11444514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64LSR(b.Int64(8), two)), b.Int64(2)); 11454514f5e3Sopenharmony_ci } 11464514f5e3Sopenharmony_ci 11474514f5e3Sopenharmony_ci { 11484514f5e3Sopenharmony_ci auto x = b.Arguments(1); 11494514f5e3Sopenharmony_ci auto zero = b.Int32(0); 11504514f5e3Sopenharmony_ci auto two = b.Int32(2); 11514514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32LSR(x, zero)), x); // x >>> 0 => x 11524514f5e3Sopenharmony_ci // (u)-8 >> 2 => 1073741822u 11534514f5e3Sopenharmony_ci // 8 >> 2 => 2 11544514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32LSR(b.Int32(-8), two)), b.Int32(1073741822u)); 11554514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32LSR(b.Int32(8), two)), b.Int32(2)); 11564514f5e3Sopenharmony_ci // (x & 1023) >>> 10 => 0 11574514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32LSR(b.Int32And(x, b.Int32(1023)), b.Int32(10))), zero); 11584514f5e3Sopenharmony_ci } 11594514f5e3Sopenharmony_ci} 11604514f5e3Sopenharmony_ci 11614514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64_32AsrTest) 11624514f5e3Sopenharmony_ci{ 11634514f5e3Sopenharmony_ci // construct a circuit 11644514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 11654514f5e3Sopenharmony_ci Circuit circuit(&allocator); 11664514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 11674514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 11684514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 11694514f5e3Sopenharmony_ci Environment env(0, &b); 11704514f5e3Sopenharmony_ci b.SetEnvironment(&env); 11714514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 11724514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 11734514f5e3Sopenharmony_ci { 11744514f5e3Sopenharmony_ci auto x = b.Arguments(1); 11754514f5e3Sopenharmony_ci auto zero = b.Int64(0); 11764514f5e3Sopenharmony_ci auto two = b.Int64(2); 11774514f5e3Sopenharmony_ci // x >> 0 => x 11784514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64ASR(x, zero)), x); 11794514f5e3Sopenharmony_ci // -8 >> 2 => -2 11804514f5e3Sopenharmony_ci // 8 >> 2 => 2 11814514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64ASR(b.Int64(-8), two)), b.Int64(-2)); 11824514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64ASR(b.Int64(8), two)), b.Int64(2)); 11834514f5e3Sopenharmony_ci } 11844514f5e3Sopenharmony_ci { 11854514f5e3Sopenharmony_ci auto x = b.Arguments(1); 11864514f5e3Sopenharmony_ci auto zero = b.Int32(0); 11874514f5e3Sopenharmony_ci auto two = b.Int32(2); 11884514f5e3Sopenharmony_ci // x >> 0 => x 11894514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32ASR(x, zero)), x); 11904514f5e3Sopenharmony_ci // -8 >> 2 => -2 11914514f5e3Sopenharmony_ci // 8 >> 2 => 2 11924514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32ASR(b.Int32(-8), two)), b.Int32(-2)); 11934514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32ASR(b.Int32(8), two)), b.Int32(2)); 11944514f5e3Sopenharmony_ci } 11954514f5e3Sopenharmony_ci} 11964514f5e3Sopenharmony_ci 11974514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64_32LslTest) 11984514f5e3Sopenharmony_ci{ 11994514f5e3Sopenharmony_ci // construct a circuit 12004514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 12014514f5e3Sopenharmony_ci Circuit circuit(&allocator); 12024514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 12034514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 12044514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 12054514f5e3Sopenharmony_ci Environment env(0, &b); 12064514f5e3Sopenharmony_ci b.SetEnvironment(&env); 12074514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 12084514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 12094514f5e3Sopenharmony_ci { 12104514f5e3Sopenharmony_ci auto x = b.Arguments(1); 12114514f5e3Sopenharmony_ci auto zero = b.Int64(0); 12124514f5e3Sopenharmony_ci auto two = b.Int64(2); 12134514f5e3Sopenharmony_ci // x << 0 => x 12144514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64LSL(x, zero)), x); 12154514f5e3Sopenharmony_ci // 1 << 2 => 4 12164514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int64LSL(b.Int64(1), two)), b.Int64(4)); 12174514f5e3Sopenharmony_ci } 12184514f5e3Sopenharmony_ci { 12194514f5e3Sopenharmony_ci auto x = b.Arguments(1); 12204514f5e3Sopenharmony_ci auto zero = b.Int32(0); 12214514f5e3Sopenharmony_ci auto two = b.Int32(2); 12224514f5e3Sopenharmony_ci // x << 0 => x 12234514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32LSL(x, zero)), x); 12244514f5e3Sopenharmony_ci // 1 << 2 => 4 12254514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.Int32LSL(b.Int32(1), two)), b.Int32(4)); 12264514f5e3Sopenharmony_ci } 12274514f5e3Sopenharmony_ci} 12284514f5e3Sopenharmony_ci 12294514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, Int64EqualTest) 12304514f5e3Sopenharmony_ci{ 12314514f5e3Sopenharmony_ci // construct a circuit 12324514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 12334514f5e3Sopenharmony_ci Circuit circuit(&allocator); 12344514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 12354514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 12364514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 12374514f5e3Sopenharmony_ci Environment env(0, &b); 12384514f5e3Sopenharmony_ci b.SetEnvironment(&env); 12394514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 12404514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 12414514f5e3Sopenharmony_ci 12424514f5e3Sopenharmony_ci // Match {EQ ((x or constant1) , constant2)} {((constant1 || constant2) != constant2)} => false 12434514f5e3Sopenharmony_ci { 12444514f5e3Sopenharmony_ci auto x = b.Arguments(1); 12454514f5e3Sopenharmony_ci auto constant1 = b.Int64(5); 12464514f5e3Sopenharmony_ci auto constant2 = b.Int64(10); 12474514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Equal(b.Int64Or(x, constant1), constant2)); 12484514f5e3Sopenharmony_ci EXPECT_EQ(result, b.False()); 12494514f5e3Sopenharmony_ci } 12504514f5e3Sopenharmony_ci 12514514f5e3Sopenharmony_ci // Taggedalue 12524514f5e3Sopenharmony_ci { 12534514f5e3Sopenharmony_ci auto x = b.Arguments(1); 12544514f5e3Sopenharmony_ci auto constant1 = b.Int64(5); 12554514f5e3Sopenharmony_ci auto constant2 = b.Int64(10); 12564514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Equal(b.Int64ToTaggedPtr(b.Int64Or(x, constant1)), constant2)); 12574514f5e3Sopenharmony_ci EXPECT_EQ(result, b.False()); 12584514f5e3Sopenharmony_ci } 12594514f5e3Sopenharmony_ci // Match {EQ((X or constant1) & constant2, 0)} { (constan2 !=0 && constant1 & constant2 !=0) }=> false 12604514f5e3Sopenharmony_ci { 12614514f5e3Sopenharmony_ci auto x = b.Arguments(1); 12624514f5e3Sopenharmony_ci auto constant1 = b.Int64(15); 12634514f5e3Sopenharmony_ci auto constant2 = b.Int64(7); 12644514f5e3Sopenharmony_ci auto zero = b.Int64(0); 12654514f5e3Sopenharmony_ci auto result = instcombie.VisitGate(b.Equal(b.Int64And(b.Int64Or(x, constant1), constant2), zero)); 12664514f5e3Sopenharmony_ci EXPECT_EQ(result, b.False()); 12674514f5e3Sopenharmony_ci } 12684514f5e3Sopenharmony_ci} 12694514f5e3Sopenharmony_ci 12704514f5e3Sopenharmony_ciHWTEST_F_L0(InstructionCombineTests, ConvertTest) 12714514f5e3Sopenharmony_ci{ 12724514f5e3Sopenharmony_ci // construct a circuit 12734514f5e3Sopenharmony_ci ecmascript::NativeAreaAllocator allocator; 12744514f5e3Sopenharmony_ci Circuit circuit(&allocator); 12754514f5e3Sopenharmony_ci ecmascript::Chunk chunk(&allocator); 12764514f5e3Sopenharmony_ci GateAccessor acc(&circuit); 12774514f5e3Sopenharmony_ci CircuitBuilder b(&circuit); 12784514f5e3Sopenharmony_ci Environment env(0, &b); 12794514f5e3Sopenharmony_ci b.SetEnvironment(&env); 12804514f5e3Sopenharmony_ci CombinedPassVisitor visitor(&circuit, false, "InstCombie", &chunk); 12814514f5e3Sopenharmony_ci InstructionCombine instcombie(&circuit, &visitor, &chunk); 12824514f5e3Sopenharmony_ci { 12834514f5e3Sopenharmony_ci auto x = b.Arguments(1); 12844514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.ChangeFloat64ToInt32(b.ChangeInt32ToFloat64(x))), x); 12854514f5e3Sopenharmony_ci } 12864514f5e3Sopenharmony_ci 12874514f5e3Sopenharmony_ci { 12884514f5e3Sopenharmony_ci auto x = b.Arguments(2); 12894514f5e3Sopenharmony_ci EXPECT_EQ(instcombie.VisitGate(b.ChangeInt32ToFloat64(b.ChangeFloat64ToInt32(x))), x); 12904514f5e3Sopenharmony_ci } 12914514f5e3Sopenharmony_ci} 12924514f5e3Sopenharmony_ci} // namespace panda::test