1 /* 2 * Copyright (c) 2021 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 #ifndef ECMASCRIPT_COMPILER_CONSTANT_FOLDING_H 17 #define ECMASCRIPT_COMPILER_CONSTANT_FOLDING_H 18 19 #include "ecmascript/compiler/circuit.h" 20 #include "ecmascript/compiler/circuit_builder.h" 21 #include "ecmascript/compiler/gate.h" 22 #include "ecmascript/compiler/share_gate_meta_data.h" 23 #include "ecmascript/compiler/combined_pass_visitor.h" 24 #include "ecmascript/compiler/number_gate_info.h" 25 26 namespace panda::ecmascript::kungfu { 27 class ConstantFolding : public PassVisitor { 28 29 #define BINARY_OP_LIST(V) \ 30 V(ADD, VALID) \ 31 V(SUB, VALID) \ 32 V(MUL, VALID) \ 33 V(EXP, INVALID) \ 34 V(SDIV, INVALID) \ 35 V(SMOD, VALID) \ 36 V(UDIV, INVALID) \ 37 V(UMOD, VALID) \ 38 V(FDIV, INVALID) \ 39 V(FMOD, INVALID) \ 40 V(AND, VALID) \ 41 V(XOR, VALID) \ 42 V(OR, VALID) \ 43 V(LSL, INVALID) \ 44 V(LSR, INVALID) \ 45 V(ASR, INVALID) \ 46 V(MIN, VALID) \ 47 V(MAX, VALID) 48 49 #define UNARY_OP_LIST(V) \ 50 V(ZEXT, VALID) \ 51 V(SEXT, INVALID) \ 52 V(DOUBLE_TRUNC, INVALID) \ 53 V(TRUNC, INVALID) \ 54 V(FEXT, INVALID) \ 55 V(FTRUNC, INVALID) \ 56 V(REV, VALID) \ 57 V(TAGGED_TO_INT64, INVALID) \ 58 V(INT64_TO_TAGGED, INVALID) \ 59 V(SIGNED_INT_TO_FLOAT, INVALID) \ 60 V(UNSIGNED_INT_TO_FLOAT, INVALID) \ 61 V(FLOAT_TO_SIGNED_INT, INVALID) \ 62 V(UNSIGNED_FLOAT_TO_INT, INVALID) \ 63 V(TRUNC_FLOAT_TO_INT64, INVALID) \ 64 V(TRUNC_FLOAT_TO_INT32, INVALID) \ 65 V(BITCAST, INVALID) \ 66 V(ABS, VALID) \ 67 V(SQRT, VALID) \ 68 V(CLZ32, INVALID) \ 69 V(CEIL, VALID) \ 70 V(FLOOR, VALID) 71 72 #define GEN_SWITCH_CASE(op, flag) GEN_SWITCH_CASE_##flag(op) 73 #define GEN_SWITCH_CASE_VALID(op) \ 74 case OpCode::op: { \ 75 return Visit##op(gate); \ 76 } 77 #define GEN_SWITCH_CASE_INVALID(op) 78 79 public: ConstantFolding(Circuit * circuit,RPOVisitor * visitor,CompilationConfig * cmpCfg,bool enableLog,const std::string & name,Chunk * chunk)80 ConstantFolding(Circuit *circuit, RPOVisitor* visitor, CompilationConfig *cmpCfg, bool enableLog, 81 const std::string& name, Chunk* chunk) 82 : PassVisitor(circuit, chunk, visitor), circuit_(circuit), acc_(circuit), builder_(circuit, cmpCfg), 83 enableLog_(enableLog), methodName_(name) {} 84 ~ConstantFolding() = default; 85 void Print() const; 86 GateRef VisitGate(GateRef gate); 87 private: 88 89 #define DECLARE_VISIT_OP(name, valid) \ 90 GateRef Visit##name(GateRef gate); 91 92 BINARY_OP_LIST(DECLARE_VISIT_OP) 93 UNARY_OP_LIST(DECLARE_VISIT_OP) 94 #undef DECLARE_VISIT_BINARY_OP 95 96 GateRef UnaryInt32Calculate(GateRef gate, std::function<GateRef(int)> op); 97 GateRef UnaryF64Calculate(GateRef gate, std::function<GateRef(double)> op); 98 GateRef BinaryInt32Calculate(GateRef gate, std::function<GateRef(int, int)> op); 99 GateRef BinaryF64Calculate(GateRef gate, std::function<GateRef(double, double)> op); 100 BoolConstant(bool val)101 inline GateRef BoolConstant(bool val) 102 { 103 AddFoldingCount(); 104 GateRef result = builder_.Boolean(val); 105 return result; 106 } 107 Int32Constant(int32_t val)108 inline GateRef Int32Constant(int32_t val) 109 { 110 AddFoldingCount(); 111 GateRef result = builder_.Int32(val); 112 return result; 113 } 114 Int64Constant(size_t val)115 inline GateRef Int64Constant(size_t val) 116 { 117 AddFoldingCount(); 118 GateRef result = builder_.Int64(val); 119 return result; 120 } 121 DoubleConstant(double val)122 inline GateRef DoubleConstant(double val) 123 { 124 AddFoldingCount(); 125 GateRef result = builder_.Double(val); 126 return result; 127 } 128 IsBoolType(GateRef gate)129 inline bool IsBoolType(GateRef gate) const 130 { 131 return acc_.GetMachineType(gate) == MachineType::I1; 132 } 133 IsInt32Type(GateRef gate)134 inline bool IsInt32Type(GateRef gate) const 135 { 136 return acc_.GetMachineType(gate) == MachineType::I32; 137 } 138 IsInt64Type(GateRef gate)139 inline bool IsInt64Type(GateRef gate) const 140 { 141 return acc_.GetMachineType(gate) == MachineType::I64; 142 } 143 IsF64Type(GateRef gate)144 inline bool IsF64Type(GateRef gate) const 145 { 146 return acc_.GetMachineType(gate) == MachineType::F64; 147 } 148 IsLogEnabled()149 bool IsLogEnabled() const 150 { 151 return enableLog_; 152 } 153 GetMethodName()154 std::string GetMethodName() const 155 { 156 return methodName_; 157 } 158 AddFoldingCount()159 void AddFoldingCount() 160 { 161 ++foldingCount_; 162 } 163 GetFoldingCount()164 int32_t GetFoldingCount() const 165 { 166 return foldingCount_; 167 } 168 169 Circuit* circuit_; 170 GateAccessor acc_; 171 CircuitBuilder builder_; 172 bool enableLog_{false}; 173 std::string methodName_; 174 int32_t foldingCount_{0}; 175 }; 176 177 } // namespace panda::ecmascript::kungfu 178 #endif //ECMASCRIPT_COMPILER_CONSTANT_FOLDING_H