• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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