* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ecmascript/compiler/circuit_builder_helper.h"
#include "ecmascript/compiler/combined_pass_visitor.h"
#include "ecmascript/compiler/dead_code_elimination.h"
#include "ecmascript/compiler/verifier.h"
#include "ecmascript/tests/test_helper.h"
namespace panda::test {
class DeadCodeEliminationTests : public testing::Test {
};
using ecmascript::kungfu::Chunk;
using ecmascript::kungfu::CombinedPassVisitor;
using ecmascript::kungfu::Circuit;
using ecmascript::kungfu::CircuitBuilder;
using ecmascript::kungfu::DeadCodeElimination;
using ecmascript::kungfu::Environment;
using ecmascript::kungfu::OpCode;
using ecmascript::kungfu::GateType;
using ecmascript::kungfu::MachineType;
using ecmascript::kungfu::GateAccessor;
using ecmascript::kungfu::GateRef;
using ecmascript::kungfu::Verifier;
using ecmascript::NativeAreaAllocator;
HWTEST_F_L0(DeadCodeEliminationTests, CommonEliminationFramework)
{
ecmascript::NativeAreaAllocator allocator;
Circuit circuit(&allocator);
CircuitBuilder builder(&circuit);
GateAccessor acc(&circuit);
auto depend = acc.GetDependRoot();
auto arg0 = builder.Arguments(0);
auto dead = circuit.DeadGate();
auto ifBranch = circuit.NewGate(circuit.IfBranch(0), {dead, arg0});
auto ifTrue = circuit.NewGate(circuit.IfTrue(), {ifBranch});
auto ifFalse = circuit.NewGate(circuit.IfFalse(), {ifBranch});
auto trueReturn = circuit.NewGate(circuit.Return(), {ifTrue, depend, arg0, circuit.GetReturnRoot()});
auto falseReturn = circuit.NewGate(circuit.Return(), {ifFalse, depend, arg0, circuit.GetReturnRoot()});
Chunk chunk(&allocator);
CombinedPassVisitor visitor(&circuit, false, "dead code elimination", &chunk);
DeadCodeElimination elimination(&circuit, &visitor, &chunk);
visitor.AddPass(&elimination);
visitor.VisitGraph();
EXPECT_TRUE(acc.IsNop(ifBranch));
EXPECT_TRUE(acc.IsNop(ifTrue));
EXPECT_TRUE(acc.IsNop(ifFalse));
EXPECT_TRUE(acc.IsNop(trueReturn));
EXPECT_TRUE(acc.IsNop(falseReturn));
}
HWTEST_F_L0(DeadCodeEliminationTests, MergeEliminationFramework)
{
ecmascript::NativeAreaAllocator allocator;
Circuit circuit(&allocator);
CircuitBuilder builder(&circuit);
Environment env(0, &builder);
builder.SetEnvironment(&env);
GateAccessor acc(&circuit);
auto entry = acc.GetStateRoot();
auto depend = acc.GetDependRoot();
auto arg0 = builder.Arguments(0);
auto arg1 = builder.Arguments(1);
auto arg2 = builder.Arguments(2);
auto dead = circuit.DeadGate();
auto icmp = circuit.NewGate(circuit.Icmp(1), MachineType::I1, {arg0, arg1}, GateType::NJSValue());
auto ifBranch = circuit.NewGate(circuit.IfBranch(0), {entry, icmp});
circuit.NewGate(circuit.IfTrue(), {ifBranch});
auto ifFalse = circuit.NewGate(circuit.IfFalse(), {ifBranch});
auto merge = circuit.NewGate(circuit.Merge(2), {dead, ifFalse});
auto valueSelector = circuit.NewGate(circuit.ValueSelector(2), {merge, arg1, arg2});
auto circuitReturn = circuit.NewGate(circuit.Return(), {merge, depend, valueSelector, circuit.GetReturnRoot()});
Chunk chunk(&allocator);
CombinedPassVisitor visitor(&circuit, false, "dead code elimination", &chunk);
DeadCodeElimination elimination(&circuit, &visitor, &chunk);
visitor.AddPass(&elimination);
visitor.VisitGraph();
EXPECT_TRUE(acc.IsNop(merge));
EXPECT_TRUE(acc.IsNop(valueSelector));
EXPECT_TRUE(acc.GetValueIn(circuitReturn) == arg2);
}
HWTEST_F_L0(DeadCodeEliminationTests, MergeInputEliminationFramework)
{
ecmascript::NativeAreaAllocator allocator;
Circuit circuit(&allocator);
CircuitBuilder builder(&circuit);
Environment env(0, &builder);
builder.SetEnvironment(&env);
GateAccessor acc(&circuit);
auto entry = acc.GetStateRoot();
auto depend = acc.GetDependRoot();
auto arg0 = builder.Arguments(0);
auto arg1 = builder.Arguments(1);
auto arg2 = builder.Arguments(2);
auto dead = circuit.DeadGate();
auto icmp = circuit.NewGate(circuit.Icmp(1), MachineType::I1, {arg0, arg1}, GateType::NJSValue());
auto ifBranch = circuit.NewGate(circuit.IfBranch(0), {entry, icmp});
auto ifTrue = circuit.NewGate(circuit.IfTrue(), {ifBranch});
auto ifFalse = circuit.NewGate(circuit.IfFalse(), {ifBranch});
auto ifBranch2 = circuit.NewGate(circuit.IfBranch(0), {ifTrue, icmp});
auto ifTrue2 = circuit.NewGate(circuit.IfTrue(), {ifBranch2});
circuit.NewGate(circuit.IfFalse(), {ifBranch2});
auto merge = circuit.NewGate(circuit.Merge(3), {ifTrue2, dead, ifFalse});
auto valueSelector = circuit.NewGate(circuit.ValueSelector(3), {merge, arg0, arg1, arg2});
auto circuitReturn = circuit.NewGate(circuit.Return(), {merge, depend, valueSelector, circuit.GetReturnRoot()});
Chunk chunk(&allocator);
CombinedPassVisitor visitor(&circuit, false, "dead code elimination", &chunk);
DeadCodeElimination elimination(&circuit, &visitor, &chunk);
visitor.AddPass(&elimination);
visitor.VisitGraph();
EXPECT_TRUE(acc.GetOpCode(merge) == OpCode::MERGE);
EXPECT_TRUE(acc.GetOpCode(valueSelector) == OpCode::VALUE_SELECTOR);
EXPECT_TRUE(acc.GetValueIn(circuitReturn) == valueSelector);
EXPECT_TRUE(acc.GetNumIns(merge) == 2);
EXPECT_TRUE(acc.GetNumIns(valueSelector) == 3);
EXPECT_TRUE(acc.GetIn(merge, 0) == ifTrue2);
EXPECT_TRUE(acc.GetIn(merge, 1) == ifFalse);
EXPECT_TRUE(acc.GetIn(valueSelector, 1) == arg0);
EXPECT_TRUE(acc.GetIn(valueSelector, 2) == arg2);
}
}