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