1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include "ecmascript/compiler/gate_accessor.h" 16#include "ecmascript/compiler/pass.h" 17#include "ecmascript/compiler/share_gate_meta_data.h" 18#include "ecmascript/compiler/share_opcodes.h" 19#include "ecmascript/compiler/value_numbering.h" 20#include "ecmascript/compiler/verifier.h" 21#include "ecmascript/compiler/typed_bytecode_lowering.h" 22#include "ecmascript/compiler/typed_hcr_lowering.h" 23#include "ecmascript/elements.h" 24#include "ecmascript/mem/concurrent_marker.h" 25#include "ecmascript/mem/native_area_allocator.h" 26#include "ecmascript/tests/test_helper.h" 27#include "gtest/gtest.h" 28#include <cstddef> 29#include <vector> 30 31namespace panda::test { 32class GlobalValueNumberingTests : public testing::Test {}; 33 34using ecmascript::kungfu::Circuit; 35using ecmascript::kungfu::CircuitBuilder; 36using ecmascript::kungfu::CombinedPassVisitor; 37using ecmascript::kungfu::EcmaOpcode; 38using ecmascript::kungfu::Environment; 39using ecmascript::kungfu::GateAccessor; 40using ecmascript::kungfu::GateRef; 41using ecmascript::kungfu::PGOSampleType; 42using ecmascript::kungfu::ValueNumbering; 43using ecmascript::kungfu::Verifier; 44 45 46HWTEST_F_L0(GlobalValueNumberingTests, AllInputsCheckedTest) 47{ 48 // construct a circuit 49 ecmascript::NativeAreaAllocator allocator; 50 Circuit circuit(&allocator); 51 ecmascript::Chunk chunk(&allocator); 52 GateAccessor acc(&circuit); 53 CircuitBuilder builder(&circuit); 54 Environment env(0, &builder); 55 builder.SetEnvironment(&env); 56 auto x = builder.Arguments(1); 57 auto y = builder.Arguments(2); 58 auto z = builder.Arguments(3); 59 auto add1 = builder.Int64Add(x, y); 60 auto add2 = builder.Int64Add(x, y); 61 auto add3 = builder.Int64Add(x, z); 62 63 CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 64 ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 65 66 EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate()); 67 EXPECT_EQ(valuenumber.VisitGate(add2), add1); 68 EXPECT_EQ(valuenumber.VisitGate(add3), Circuit::NullGate()); 69} 70 71 72HWTEST_F_L0(GlobalValueNumberingTests, DeadNodesTest) 73{ 74 // construct a circuit 75 ecmascript::NativeAreaAllocator allocator; 76 Circuit circuit(&allocator); 77 ecmascript::Chunk chunk(&allocator); 78 GateAccessor acc(&circuit); 79 CircuitBuilder builder(&circuit); 80 Environment env(0, &builder); 81 builder.SetEnvironment(&env); 82 auto x = builder.Arguments(1); 83 auto y = builder.Arguments(2); 84 85 auto add1 = builder.Int64Add(x, y); 86 auto add2 = builder.Int64Add(x, y); 87 88 CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 89 ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 90 91 EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate()); 92 acc.DeleteGate(add1); 93 EXPECT_EQ(valuenumber.VisitGate(add2), Circuit::NullGate()); 94} 95 96HWTEST_F_L0(GlobalValueNumberingTests, WontReplaceNodeWithItself) 97{ 98 // construct a circuit 99 ecmascript::NativeAreaAllocator allocator; 100 Circuit circuit(&allocator); 101 ecmascript::Chunk chunk(&allocator); 102 GateAccessor acc(&circuit); 103 CircuitBuilder builder(&circuit); 104 Environment env(0, &builder); 105 builder.SetEnvironment(&env); 106 auto x = builder.Arguments(1); 107 auto y = builder.Arguments(2); 108 109 auto add1 = builder.Int64Add(x, y); 110 111 CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 112 ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 113 114 EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate()); 115 EXPECT_EQ(valuenumber.VisitGate(add1), Circuit::NullGate()); 116} 117 118 119HWTEST_F_L0(GlobalValueNumberingTests, E2ESimpleAddTest) 120{ 121 // construct a circuit 122 ecmascript::NativeAreaAllocator allocator; 123 Circuit circuit(&allocator); 124 ecmascript::Chunk chunk(&allocator); 125 GateAccessor acc(&circuit); 126 CircuitBuilder builder(&circuit); 127 Environment env(0, &builder); 128 builder.SetEnvironment(&env); 129 130 auto x = builder.Arguments(1); 131 auto y = builder.Arguments(2); 132 133 134 auto add1 = builder.Int64Add(x, y); 135 auto add2 = builder.Int64Add(x, y); 136 auto add3 = builder.Int64Add(add1, add2); 137 138 builder.Return(add3); 139 EXPECT_TRUE(Verifier::Run(&circuit)); 140 CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 141 ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 142 visitor.AddPass(&valuenumber); 143 visitor.VisitGraph(); 144 EXPECT_TRUE(Verifier::Run(&circuit)); 145 EXPECT_TRUE(acc.GetValueIn(add3, 0) == acc.GetValueIn(add3, 1)); 146 EXPECT_EQ(valuenumber.GetoptimizedGateCount(), 1); 147} 148 149HWTEST_F_L0(GlobalValueNumberingTests, GrowStressTest) 150{ 151 // construct a circuit 152 ecmascript::NativeAreaAllocator allocator; 153 Circuit circuit(&allocator); 154 ecmascript::Chunk chunk(&allocator); 155 GateAccessor acc(&circuit); 156 CircuitBuilder builder(&circuit); 157 Environment env(0, &builder); 158 builder.SetEnvironment(&env); 159 160 std::vector<GateRef> results; 161 auto x = builder.Arguments(1); 162 auto y = builder.Arguments(2); 163 164 for (int i = 0; i < 10000; i++) { 165 auto add1 = builder.Int64Add(x, y); 166 results.push_back(add1); 167 } 168 169 GateRef before = results[0]; 170 for (int i = 1; i < 10000; i++) { 171 before = builder.Int64Add(before, results[i]); 172 } 173 174 builder.Return(before); 175 EXPECT_TRUE(Verifier::Run(&circuit)); 176 CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 177 ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 178 visitor.AddPass(&valuenumber); 179 visitor.VisitGraph(); 180 EXPECT_TRUE(Verifier::Run(&circuit)); 181 EXPECT_EQ(valuenumber.GetoptimizedGateCount(), 9999); 182} 183 184 185HWTEST_F_L0(GlobalValueNumberingTests, ComplexAddTest) 186{ 187 // construct a circuit 188 ecmascript::NativeAreaAllocator allocator; 189 Circuit circuit(&allocator); 190 ecmascript::Chunk chunk(&allocator); 191 GateAccessor acc(&circuit); 192 CircuitBuilder builder(&circuit); 193 Environment env(0, &builder); 194 builder.SetEnvironment(&env); 195 196 auto x = builder.Arguments(1); 197 auto y = builder.Arguments(2); 198 199 auto add1 = builder.Int64Add(x, y); 200 auto add2 = builder.Int64Add(x, y); 201 auto add3 = builder.Int64Add(add1, add2); 202 203 auto add4 = builder.Int64Add(x, y); 204 auto add5 = builder.Int64Add(x, y); 205 auto add6 = builder.Int64Add(add4, add5); 206 207 auto add7 = builder.Int64Add(add3, add6); 208 builder.Return(add7); 209 EXPECT_TRUE(Verifier::Run(&circuit)); 210 CombinedPassVisitor visitor(&circuit, false, "ValueNumbering", &chunk); 211 ValueNumbering valuenumber(&circuit, &visitor, &chunk, true, false); 212 visitor.AddPass(&valuenumber); 213 visitor.VisitGraph(); 214 EXPECT_TRUE(Verifier::Run(&circuit)); 215 EXPECT_EQ(valuenumber.GetoptimizedGateCount(), 4); 216} 217 218} // namespace panda::test