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 164514f5e3Sopenharmony_ci#include "ecmascript/compiler/dead_code_elimination.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 194514f5e3Sopenharmony_ci 204514f5e3Sopenharmony_ciGateRef DeadCodeElimination::VisitGate(GateRef gate) 214514f5e3Sopenharmony_ci{ 224514f5e3Sopenharmony_ci auto opcode = acc_.GetOpCode(gate); 234514f5e3Sopenharmony_ci switch (opcode) { 244514f5e3Sopenharmony_ci case OpCode::SWITCH_BRANCH: 254514f5e3Sopenharmony_ci case OpCode::IF_BRANCH: 264514f5e3Sopenharmony_ci return EliminateBranch(gate); 274514f5e3Sopenharmony_ci case OpCode::MERGE: 284514f5e3Sopenharmony_ci case OpCode::LOOP_BEGIN: 294514f5e3Sopenharmony_ci return EliminateMergeAndLoopBegin(gate); 304514f5e3Sopenharmony_ci case OpCode::DEPEND_SELECTOR: 314514f5e3Sopenharmony_ci return EliminateDependSelector(gate); 324514f5e3Sopenharmony_ci case OpCode::IF_EXCEPTION: 334514f5e3Sopenharmony_ci return EliminateIfException(gate); 344514f5e3Sopenharmony_ci case OpCode::LOOP_EXIT: 354514f5e3Sopenharmony_ci return EliminateLoopExit(gate); 364514f5e3Sopenharmony_ci default : 374514f5e3Sopenharmony_ci return EliminateGate(gate); 384514f5e3Sopenharmony_ci } 394514f5e3Sopenharmony_ci return Circuit::NullGate(); 404514f5e3Sopenharmony_ci} 414514f5e3Sopenharmony_ci 424514f5e3Sopenharmony_ciGateRef DeadCodeElimination::StateIsDead(GateRef gate) 434514f5e3Sopenharmony_ci{ 444514f5e3Sopenharmony_ci auto state = acc_.GetState(gate); 454514f5e3Sopenharmony_ci if (acc_.IsDead(state)) { 464514f5e3Sopenharmony_ci return state; 474514f5e3Sopenharmony_ci } 484514f5e3Sopenharmony_ci return Circuit::NullGate(); 494514f5e3Sopenharmony_ci} 504514f5e3Sopenharmony_ci 514514f5e3Sopenharmony_ciGateRef DeadCodeElimination::EliminateDependSelector(GateRef gate) 524514f5e3Sopenharmony_ci{ 534514f5e3Sopenharmony_ci GateRef state = StateIsDead(gate); 544514f5e3Sopenharmony_ci if (state != Circuit::NullGate() && acc_.IsDead(state)) { 554514f5e3Sopenharmony_ci return state; 564514f5e3Sopenharmony_ci } 574514f5e3Sopenharmony_ci auto stateInput = acc_.GetState(gate); 584514f5e3Sopenharmony_ci size_t dependCount = acc_.GetDependCount(gate); 594514f5e3Sopenharmony_ci GateRef result = Circuit::NullGate(); 604514f5e3Sopenharmony_ci for (size_t i = 0; i < dependCount; i++) { 614514f5e3Sopenharmony_ci auto depend = acc_.GetDep(gate, i); 624514f5e3Sopenharmony_ci if (acc_.IsDead(depend)) { 634514f5e3Sopenharmony_ci acc_.ReplaceStateIn(stateInput, deadGate_, i); 644514f5e3Sopenharmony_ci visitor_->ReVisitGate(stateInput); 654514f5e3Sopenharmony_ci result = gate; 664514f5e3Sopenharmony_ci } 674514f5e3Sopenharmony_ci } 684514f5e3Sopenharmony_ci return result; 694514f5e3Sopenharmony_ci} 704514f5e3Sopenharmony_ci 714514f5e3Sopenharmony_ciGateRef DeadCodeElimination::EliminateIfException(GateRef gate) 724514f5e3Sopenharmony_ci{ 734514f5e3Sopenharmony_ci GateRef state = StateIsDead(gate); 744514f5e3Sopenharmony_ci if (state != Circuit::NullGate() && acc_.IsDead(state)) { 754514f5e3Sopenharmony_ci return state; 764514f5e3Sopenharmony_ci } 774514f5e3Sopenharmony_ci GateRef depend = acc_.GetDep(gate); 784514f5e3Sopenharmony_ci if (acc_.IsDead(depend)) { 794514f5e3Sopenharmony_ci return deadGate_; 804514f5e3Sopenharmony_ci } 814514f5e3Sopenharmony_ci return Circuit::NullGate(); 824514f5e3Sopenharmony_ci} 834514f5e3Sopenharmony_ci 844514f5e3Sopenharmony_ciGateRef DeadCodeElimination::EliminateLoopExit(GateRef gate) 854514f5e3Sopenharmony_ci{ 864514f5e3Sopenharmony_ci GateRef state = StateIsDead(gate); 874514f5e3Sopenharmony_ci if (state != Circuit::NullGate() && acc_.IsDead(state)) { 884514f5e3Sopenharmony_ci return DeleteLoopExit(gate); 894514f5e3Sopenharmony_ci } 904514f5e3Sopenharmony_ci return Circuit::NullGate(); 914514f5e3Sopenharmony_ci} 924514f5e3Sopenharmony_ci 934514f5e3Sopenharmony_ciGateRef DeadCodeElimination::EliminateBranch(GateRef gate) 944514f5e3Sopenharmony_ci{ 954514f5e3Sopenharmony_ci GateRef state = StateIsDead(gate); 964514f5e3Sopenharmony_ci if (state != Circuit::NullGate() && acc_.IsDead(state)) { 974514f5e3Sopenharmony_ci return state; 984514f5e3Sopenharmony_ci } 994514f5e3Sopenharmony_ci GateRef value = acc_.GetValueIn(gate, 0); 1004514f5e3Sopenharmony_ci if (acc_.IsDead(value)) { 1014514f5e3Sopenharmony_ci auto uses = acc_.Uses(gate); 1024514f5e3Sopenharmony_ci for (auto it = uses.begin(); it != uses.end(); it++) { 1034514f5e3Sopenharmony_ci if (acc_.IsIfOrSwitchRelated(*it)) { 1044514f5e3Sopenharmony_ci ReplaceGate(*it, acc_.GetState(gate)); 1054514f5e3Sopenharmony_ci return deadGate_; 1064514f5e3Sopenharmony_ci } 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci UNREACHABLE(); 1094514f5e3Sopenharmony_ci } 1104514f5e3Sopenharmony_ci return gate; 1114514f5e3Sopenharmony_ci} 1124514f5e3Sopenharmony_ci 1134514f5e3Sopenharmony_civoid DeadCodeElimination::DecreaseAllSelectors(GateRef gate, size_t count) 1144514f5e3Sopenharmony_ci{ 1154514f5e3Sopenharmony_ci auto uses = acc_.Uses(gate); 1164514f5e3Sopenharmony_ci for (auto it = uses.begin(); it != uses.end(); it++) { 1174514f5e3Sopenharmony_ci if (acc_.IsSelector(*it)) { 1184514f5e3Sopenharmony_ci acc_.DecreaseIn(*it, count + 1); 1194514f5e3Sopenharmony_ci } 1204514f5e3Sopenharmony_ci } 1214514f5e3Sopenharmony_ci} 1224514f5e3Sopenharmony_ciGateRef DeadCodeElimination::EliminateMergeAndLoopBegin(GateRef gate) 1234514f5e3Sopenharmony_ci{ 1244514f5e3Sopenharmony_ci if (acc_.GetOpCode(gate) == OpCode::LOOP_BEGIN) { 1254514f5e3Sopenharmony_ci auto loopEntry = acc_.GetIn(gate, 0); 1264514f5e3Sopenharmony_ci if (acc_.IsDead(loopEntry)) { 1274514f5e3Sopenharmony_ci return deadGate_; 1284514f5e3Sopenharmony_ci } 1294514f5e3Sopenharmony_ci } 1304514f5e3Sopenharmony_ci size_t count = 0; 1314514f5e3Sopenharmony_ci size_t inputCount = acc_.GetNumIns(gate); 1324514f5e3Sopenharmony_ci for (size_t i = 0; i < inputCount; i++) { 1334514f5e3Sopenharmony_ci auto input = acc_.GetIn(gate, count); 1344514f5e3Sopenharmony_ci if (acc_.IsDead(input)) { 1354514f5e3Sopenharmony_ci acc_.DecreaseIn(gate, count); 1364514f5e3Sopenharmony_ci DecreaseAllSelectors(gate, count); 1374514f5e3Sopenharmony_ci } else { 1384514f5e3Sopenharmony_ci count++; 1394514f5e3Sopenharmony_ci } 1404514f5e3Sopenharmony_ci } 1414514f5e3Sopenharmony_ci if (count == 0) { 1424514f5e3Sopenharmony_ci return deadGate_; 1434514f5e3Sopenharmony_ci } else if (count == 1) { 1444514f5e3Sopenharmony_ci auto uses = acc_.Uses(gate); 1454514f5e3Sopenharmony_ci for (auto it = uses.begin(); it != uses.end(); it++) { 1464514f5e3Sopenharmony_ci if (acc_.IsSelector(*it)) { 1474514f5e3Sopenharmony_ci TryFindAndDeleteLoopExit(*it); 1484514f5e3Sopenharmony_ci auto selectorInput = acc_.GetIn(*it, 1); 1494514f5e3Sopenharmony_ci ReplaceGate(*it, selectorInput); 1504514f5e3Sopenharmony_ci } 1514514f5e3Sopenharmony_ci } 1524514f5e3Sopenharmony_ci return acc_.GetIn(gate, 0); 1534514f5e3Sopenharmony_ci } 1544514f5e3Sopenharmony_ci if (count < inputCount) { 1554514f5e3Sopenharmony_ci auto uses = acc_.Uses(gate); 1564514f5e3Sopenharmony_ci for (auto it = uses.begin(); it != uses.end(); it++) { 1574514f5e3Sopenharmony_ci if (acc_.IsSelector(*it)) { 1584514f5e3Sopenharmony_ci visitor_->ReVisitGate(*it); 1594514f5e3Sopenharmony_ci } 1604514f5e3Sopenharmony_ci } 1614514f5e3Sopenharmony_ci return gate; 1624514f5e3Sopenharmony_ci } 1634514f5e3Sopenharmony_ci return Circuit::NullGate(); 1644514f5e3Sopenharmony_ci} 1654514f5e3Sopenharmony_ci 1664514f5e3Sopenharmony_civoid DeadCodeElimination::TryFindAndDeleteLoopExit(GateRef gate) 1674514f5e3Sopenharmony_ci{ 1684514f5e3Sopenharmony_ci auto uses = acc_.Uses(gate); 1694514f5e3Sopenharmony_ci for (auto it = uses.begin(); it != uses.end(); it++) { 1704514f5e3Sopenharmony_ci if (acc_.GetOpCode(*it) == OpCode::LOOP_EXIT_VALUE || acc_.GetOpCode(*it) == OpCode::LOOP_EXIT_DEPEND) { 1714514f5e3Sopenharmony_ci GateRef loopExit = acc_.GetState(gate); 1724514f5e3Sopenharmony_ci DeleteLoopExit(loopExit); 1734514f5e3Sopenharmony_ci } 1744514f5e3Sopenharmony_ci } 1754514f5e3Sopenharmony_ci} 1764514f5e3Sopenharmony_ciGateRef DeadCodeElimination::DeleteLoopExit(GateRef gate) 1774514f5e3Sopenharmony_ci{ 1784514f5e3Sopenharmony_ci auto uses = acc_.Uses(gate); 1794514f5e3Sopenharmony_ci for (auto it = uses.begin(); it != uses.end(); it++) { 1804514f5e3Sopenharmony_ci if (acc_.GetOpCode(*it) == OpCode::LOOP_EXIT_VALUE) { 1814514f5e3Sopenharmony_ci ReplaceGate(*it, acc_.GetValueIn(*it)); 1824514f5e3Sopenharmony_ci } else if (acc_.GetOpCode(*it) == OpCode::LOOP_EXIT_DEPEND) { 1834514f5e3Sopenharmony_ci ReplaceGate(*it, acc_.GetDep(*it)); 1844514f5e3Sopenharmony_ci } 1854514f5e3Sopenharmony_ci } 1864514f5e3Sopenharmony_ci return acc_.GetState(gate); 1874514f5e3Sopenharmony_ci} 1884514f5e3Sopenharmony_ci 1894514f5e3Sopenharmony_ciGateRef DeadCodeElimination::EliminateGate(GateRef gate) 1904514f5e3Sopenharmony_ci{ 1914514f5e3Sopenharmony_ci if (acc_.GetStateCount(gate) == 1) { 1924514f5e3Sopenharmony_ci return StateIsDead(gate); 1934514f5e3Sopenharmony_ci } 1944514f5e3Sopenharmony_ci return Circuit::NullGate(); 1954514f5e3Sopenharmony_ci} 1964514f5e3Sopenharmony_ci 1974514f5e3Sopenharmony_ci}