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
16 #include "ecmascript/compiler/constant_folding.h"
17
18 namespace panda::ecmascript::kungfu {
19
VisitGate(GateRef gate)20 GateRef ConstantFolding::VisitGate(GateRef gate)
21 {
22 auto op = acc_.GetOpCode(gate);
23 switch (op) {
24 case OpCode::ADD:
25 return VisitADD(gate);
26 case OpCode::SUB:
27 return VisitSUB(gate);
28 case OpCode::MUL:
29 return VisitMUL(gate);
30 case OpCode::SMOD:
31 return VisitSMOD(gate);
32 case OpCode::UMOD:
33 return VisitUMOD(gate);
34 case OpCode::ZEXT:
35 return VisitZEXT(gate);
36 default:
37 return Circuit::NullGate();
38 }
39 }
40
VisitZEXT(GateRef gate)41 GateRef ConstantFolding::VisitZEXT(GateRef gate)
42 {
43 auto input = acc_.GetValueIn(gate, 0);
44 if (acc_.GetMachineType(gate) == acc_.GetMachineType(input)) {
45 AddFoldingCount();
46 return input;
47 }
48
49 GateRef result = Circuit::NullGate();
50 if (IsConstant(input) && IsInt32Type(input)) {
51 int value = acc_.GetInt32FromConstant(input);
52 auto machineType = acc_.GetMachineType(gate);
53 switch (machineType) {
54 case MachineType::I32:
55 result = Int32Constant(value);
56 break;
57 case MachineType::ARCH:
58 case MachineType::I64:
59 result = Int64Constant(value);
60 break;
61 default:
62 break;
63 }
64 }
65 return result;
66 }
67
VisitSMOD(GateRef gate)68 GateRef ConstantFolding::VisitSMOD(GateRef gate)
69 {
70 auto left = acc_.GetValueIn(gate, 0);
71 auto right = acc_.GetValueIn(gate, 1);
72 if (!IsInt32Type(gate) || !IsInt32Type(left) || !IsInt32Type(right)) {
73 return Circuit::NullGate();
74 }
75
76 GateRef result = Circuit::NullGate();
77 if (IsConstant(left) && IsConstant(right)) {
78 int lvalue = acc_.GetInt32FromConstant(left);
79 int rvalue = acc_.GetInt32FromConstant(right);
80 if (rvalue != 0) {
81 result = Int32Constant(lvalue % rvalue);
82 }
83 }
84 return result;
85 }
86
VisitUMOD(GateRef gate)87 GateRef ConstantFolding::VisitUMOD(GateRef gate)
88 {
89 auto left = acc_.GetValueIn(gate, 0);
90 auto right = acc_.GetValueIn(gate, 1);
91 if (!IsInt32Type(gate) || !IsInt32Type(left) || !IsInt32Type(right)) {
92 return Circuit::NullGate();
93 }
94
95 GateRef result = Circuit::NullGate();
96 if (IsConstant(left) && IsConstant(right)) {
97 int lvalue = acc_.GetInt32FromConstant(left);
98 int rvalue = acc_.GetInt32FromConstant(right);
99 if (rvalue != 0) {
100 result = Int32Constant(bit_cast<uint32_t>(lvalue) % bit_cast<uint32_t>(rvalue));
101 }
102 }
103 return result;
104 }
105
VisitADD(GateRef gate)106 GateRef ConstantFolding::VisitADD(GateRef gate)
107 {
108 auto left = acc_.GetValueIn(gate, 0);
109 auto right = acc_.GetValueIn(gate, 1);
110 if (!IsInt32Type(gate) || !IsInt32Type(left) || !IsInt32Type(right)) {
111 return Circuit::NullGate();
112 }
113
114 GateRef result = Circuit::NullGate();
115 if (IsConstant(left) && IsConstant(right)) {
116 int lvalue = acc_.GetInt32FromConstant(left);
117 int rvalue = acc_.GetInt32FromConstant(right);
118 result = Int32Constant(lvalue + rvalue);
119 }
120 return result;
121 }
122
VisitSUB(GateRef gate)123 GateRef ConstantFolding::VisitSUB(GateRef gate)
124 {
125 auto left = acc_.GetValueIn(gate, 0);
126 auto right = acc_.GetValueIn(gate, 1);
127 if (!IsInt32Type(gate) || !IsInt32Type(left) || !IsInt32Type(right)) {
128 return Circuit::NullGate();
129 }
130
131 GateRef result = Circuit::NullGate();
132 if (IsConstant(left) && IsConstant(right)) {
133 int lvalue = acc_.GetInt32FromConstant(left);
134 int rvalue = acc_.GetInt32FromConstant(right);
135 result = Int32Constant(lvalue - rvalue);
136 }
137 return result;
138 }
139
VisitMUL(GateRef gate)140 GateRef ConstantFolding::VisitMUL(GateRef gate)
141 {
142 auto left = acc_.GetValueIn(gate, 0);
143 auto right = acc_.GetValueIn(gate, 1);
144 if (!IsInt32Type(gate) || !IsInt32Type(left) || !IsInt32Type(right)) {
145 return Circuit::NullGate();
146 }
147
148 GateRef result = Circuit::NullGate();
149 if (IsConstant(left) && IsConstant(right)) {
150 int lvalue = acc_.GetInt32FromConstant(left);
151 int rvalue = acc_.GetInt32FromConstant(right);
152 result = Int32Constant(lvalue * rvalue);
153 }
154 return result;
155 }
156
Int32Constant(int32_t val)157 GateRef ConstantFolding::Int32Constant(int32_t val)
158 {
159 AddFoldingCount();
160 GateRef result = builder_.Int32(val);
161 return result;
162 }
163
Int64Constant(size_t val)164 GateRef ConstantFolding::Int64Constant(size_t val)
165 {
166 AddFoldingCount();
167 GateRef result = builder_.Int64(val);
168 return result;
169 }
170
IsInt32Type(GateRef gate) const171 bool ConstantFolding::IsInt32Type(GateRef gate) const
172 {
173 return acc_.GetMachineType(gate) == MachineType::I32;
174 }
175
Print() const176 void ConstantFolding::Print() const
177 {
178 if (IsLogEnabled()) {
179 LOG_COMPILER(INFO) << "";
180 LOG_COMPILER(INFO) << "\033[34m"
181 << "===================="
182 << " After constant folding "
183 << "[" << GetMethodName() << "]"
184 << "===================="
185 << "\033[0m";
186 circuit_->PrintAllGatesWithBytecode();
187 LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
188
189 LOG_COMPILER(INFO) << "Folding Count : " << GetFoldingCount();
190 }
191 }
192 } // namespace panda::ecmascript::kungfu