1 /** 2 * Copyright (c) 2021-2022 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 COMPILER_TESTS_INST_GENERATOR_H 17 #define COMPILER_TESTS_INST_GENERATOR_H 18 19 #include "unit_test.h" 20 21 namespace panda::compiler { 22 class GraphCreator { 23 public: 24 GraphCreator() = delete; GraphCreator(ArenaAllocator & allocator,ArenaAllocator & local_allocator)25 explicit GraphCreator(ArenaAllocator &allocator, ArenaAllocator &local_allocator) 26 : allocator_(allocator), local_allocator_(local_allocator) 27 { 28 } 29 30 Graph *GenerateGraph(Inst *inst); 31 SetRuntimeTargetArch(Arch arch)32 void SetRuntimeTargetArch(Arch arch) 33 { 34 arch_ = arch; 35 } 36 GetRuntime()37 RuntimeInterface *GetRuntime() 38 { 39 return &runtime_; 40 } 41 GetAllocator()42 ArenaAllocator *GetAllocator() const 43 { 44 return &allocator_; 45 } 46 GetLocalAllocator()47 ArenaAllocator *GetLocalAllocator() const 48 { 49 return &local_allocator_; 50 } 51 SetNumVRegsArgs(size_t regs,size_t args)52 void SetNumVRegsArgs(size_t regs, size_t args) 53 { 54 runtime_.vregs_count = regs; 55 runtime_.args_count = args; 56 } 57 58 private: 59 Graph *CreateGraph(); 60 Graph *GenerateOperation(Inst *inst, int32_t n); 61 Graph *GenerateCheckOperation(Inst *inst); 62 Graph *GenerateSSOperation(Inst *inst); 63 Graph *GenerateBoundaryCheckOperation(Inst *inst); 64 Graph *GenerateThrowOperation(Inst *inst); 65 Graph *GenerateMultiArrayOperation(Inst *inst); 66 Graph *GeneratePhiOperation(Inst *inst); 67 68 Graph *CreateGraphWithOneBasicBlock(); 69 Graph *CreateGraphWithTwoBasicBlock(); 70 Graph *CreateGraphWithThreeBasicBlock(); 71 Graph *CreateGraphWithFourBasicBlock(); 72 ParameterInst *CreateParamInst(Graph *graph, DataType::Type type, uint8_t slot); 73 74 // need to create graphs 75 ArenaAllocator &allocator_; 76 ArenaAllocator &local_allocator_; 77 RuntimeInterfaceMock runtime_; 78 Arch arch_ {Arch::AARCH64}; 79 #include "generate_operations_intrinsic_graph.inl" 80 }; 81 82 class InstGenerator { 83 public: 84 InstGenerator() = delete; InstGenerator(ArenaAllocator & allocator)85 explicit InstGenerator(ArenaAllocator &allocator) : allocator_(allocator) {} 86 87 std::vector<Inst *> &Generate(Opcode OpCode); 88 GetAllPossibleInstToGenerateNumber()89 int GetAllPossibleInstToGenerateNumber() 90 { 91 int result = 0; 92 for (auto &it : opcode_x_possible_types_) { 93 result += it.second.size(); 94 } 95 return result; 96 } 97 GetPossibleInstToGenerateNumber(Opcode OpCode)98 int GetPossibleInstToGenerateNumber(Opcode OpCode) 99 { 100 return opcode_x_possible_types_[OpCode].size(); 101 } 102 GetMap()103 std::map<Opcode, std::vector<DataType::Type>> &GetMap() 104 { 105 return opcode_x_possible_types_; 106 } 107 GetAllocator()108 ArenaAllocator *GetAllocator() 109 { 110 return &allocator_; 111 } 112 113 private: 114 template <class T> 115 std::vector<Inst *> &GenerateOperations(Opcode OpCode); 116 117 template <class T> 118 std::vector<Inst *> &GenerateOperationsImm(Opcode OpCode); 119 120 template <class T> 121 std::vector<Inst *> &GenerateOperationsShiftedRegister(Opcode OpCode); 122 GenerateIntrinsic(DataType::Type Type,RuntimeInterface::IntrinsicId intrinsic_id)123 void GenerateIntrinsic(DataType::Type Type, RuntimeInterface::IntrinsicId intrinsic_id) 124 { 125 auto inst = Inst::New<IntrinsicInst>(&allocator_, Opcode::Intrinsic); 126 inst->SetType(Type); 127 inst->SetIntrinsicId(intrinsic_id); 128 insts_.push_back(inst); 129 } 130 131 std::vector<DataType::Type> integer_types_ {DataType::UINT8, DataType::INT8, DataType::UINT16, DataType::INT16, 132 DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64}; 133 134 std::vector<DataType::Type> numeric_types_ {DataType::BOOL, DataType::UINT8, DataType::INT8, DataType::UINT16, 135 DataType::INT16, DataType::UINT32, DataType::INT32, DataType::UINT64, 136 DataType::INT64, DataType::FLOAT32, DataType::FLOAT64}; 137 138 std::vector<DataType::Type> ref_num_types_ { 139 DataType::REFERENCE, DataType::BOOL, DataType::UINT8, DataType::INT8, DataType::UINT16, DataType::INT16, 140 DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64}; 141 142 std::vector<DataType::Type> ref_int_types_ {DataType::REFERENCE, DataType::BOOL, DataType::UINT8, DataType::INT8, 143 DataType::UINT16, DataType::INT16, DataType::UINT32, DataType::INT32, 144 DataType::UINT64, DataType::INT64}; 145 146 std::vector<DataType::Type> all_types_ {DataType::REFERENCE, DataType::BOOL, DataType::UINT8, DataType::INT8, 147 DataType::UINT16, DataType::INT16, DataType::UINT32, DataType::INT32, 148 DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 149 DataType::VOID}; 150 151 std::vector<DataType::Type> floats_types_ {DataType::FLOAT32, DataType::FLOAT64}; 152 153 std::map<Opcode, std::vector<DataType::Type>> opcode_x_possible_types_ = { 154 {Opcode::Neg, numeric_types_}, 155 {Opcode::Abs, numeric_types_}, 156 {Opcode::Not, integer_types_}, 157 {Opcode::Add, numeric_types_}, 158 {Opcode::Sub, numeric_types_}, 159 {Opcode::Mul, numeric_types_}, 160 {Opcode::Div, numeric_types_}, 161 {Opcode::Min, numeric_types_}, 162 {Opcode::Max, numeric_types_}, 163 {Opcode::Shl, integer_types_}, 164 {Opcode::Shr, integer_types_}, 165 {Opcode::AShr, integer_types_}, 166 {Opcode::Mod, numeric_types_}, 167 {Opcode::And, integer_types_}, 168 {Opcode::Or, integer_types_}, 169 {Opcode::Xor, integer_types_}, 170 {Opcode::Compare, ref_num_types_}, 171 {Opcode::If, ref_int_types_}, 172 {Opcode::Cmp, {DataType::INT32}}, 173 {Opcode::Constant, {DataType::INT64, DataType::FLOAT32, DataType::FLOAT64}}, 174 {Opcode::Phi, ref_num_types_}, 175 {Opcode::IfImm, ref_int_types_}, 176 {Opcode::Cast, numeric_types_}, 177 {Opcode::Parameter, ref_num_types_}, 178 {Opcode::IsInstance, {DataType::BOOL}}, 179 {Opcode::LenArray, {DataType::INT32}}, 180 {Opcode::LoadArray, ref_num_types_}, 181 {Opcode::StoreArray, ref_num_types_}, 182 {Opcode::LoadArrayI, ref_num_types_}, 183 {Opcode::StoreArrayI, ref_num_types_}, 184 {Opcode::CheckCast, {DataType::NO_TYPE}}, 185 {Opcode::NullCheck, {DataType::NO_TYPE}}, 186 {Opcode::ZeroCheck, {DataType::NO_TYPE}}, 187 {Opcode::NegativeCheck, {DataType::NO_TYPE}}, 188 {Opcode::BoundsCheck, {DataType::NO_TYPE}}, 189 {Opcode::BoundsCheckI, {DataType::NO_TYPE}}, 190 {Opcode::SaveState, {DataType::NO_TYPE}}, 191 {Opcode::ReturnVoid, {DataType::NO_TYPE}}, 192 {Opcode::Throw, {DataType::NO_TYPE}}, 193 {Opcode::NewArray, {DataType::REFERENCE}}, 194 {Opcode::Return, ref_num_types_}, 195 {Opcode::ReturnI, numeric_types_}, 196 {Opcode::CallStatic, all_types_}, 197 {Opcode::CallVirtual, all_types_}, 198 {Opcode::AddI, integer_types_}, 199 {Opcode::SubI, integer_types_}, 200 {Opcode::AndI, integer_types_}, 201 {Opcode::OrI, integer_types_}, 202 {Opcode::XorI, integer_types_}, 203 {Opcode::ShrI, integer_types_}, 204 {Opcode::ShlI, integer_types_}, 205 {Opcode::AShrI, integer_types_}, 206 {Opcode::SpillFill, {DataType::NO_TYPE}}, 207 {Opcode::NewObject, {DataType::REFERENCE}}, 208 {Opcode::LoadObject, ref_num_types_}, 209 {Opcode::LoadStatic, ref_num_types_}, 210 {Opcode::StoreObject, ref_num_types_}, 211 {Opcode::StoreStatic, ref_num_types_}, 212 {Opcode::LoadString, {DataType::REFERENCE}}, 213 {Opcode::LoadType, {DataType::REFERENCE}}, 214 {Opcode::SafePoint, {DataType::NO_TYPE}}, 215 {Opcode::ReturnInlined, {DataType::NO_TYPE}}, 216 {Opcode::Monitor, {DataType::VOID}}, 217 {Opcode::Intrinsic, {}}, 218 {Opcode::Select, ref_int_types_}, 219 {Opcode::SelectImm, ref_int_types_}, 220 {Opcode::NullPtr, {DataType::REFERENCE}}, 221 {Opcode::LoadArrayPair, 222 {DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 223 DataType::REFERENCE}}, 224 {Opcode::LoadArrayPairI, 225 {DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 226 DataType::REFERENCE}}, 227 {Opcode::StoreArrayPair, 228 {DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 229 DataType::REFERENCE}}, 230 {Opcode::StoreArrayPairI, 231 {DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 232 DataType::REFERENCE}}, 233 {Opcode::AndNot, integer_types_}, 234 {Opcode::OrNot, integer_types_}, 235 {Opcode::XorNot, integer_types_}, 236 {Opcode::MNeg, numeric_types_}, 237 {Opcode::MAdd, numeric_types_}, 238 {Opcode::MSub, numeric_types_}, 239 {Opcode::AddSR, integer_types_}, 240 {Opcode::SubSR, integer_types_}, 241 {Opcode::AndSR, integer_types_}, 242 {Opcode::OrSR, integer_types_}, 243 {Opcode::XorSR, integer_types_}, 244 {Opcode::AndNotSR, integer_types_}, 245 {Opcode::OrNotSR, integer_types_}, 246 {Opcode::XorNotSR, integer_types_}, 247 {Opcode::NegSR, integer_types_}, 248 }; 249 250 std::vector<ShiftType> only_shifts_ = {ShiftType::LSL, ShiftType::LSR, ShiftType::ASR}; 251 std::vector<ShiftType> shifts_and_rotation_ = {ShiftType::LSL, ShiftType::LSR, ShiftType::ASR, ShiftType::ROR}; 252 std::map<Opcode, std::vector<ShiftType>> opcode_x_possible_shift_types_ = {{Opcode::AddSR, only_shifts_}, 253 {Opcode::SubSR, only_shifts_}, 254 {Opcode::AndSR, shifts_and_rotation_}, 255 {Opcode::OrSR, shifts_and_rotation_}, 256 {Opcode::XorSR, shifts_and_rotation_}, 257 {Opcode::AndNotSR, shifts_and_rotation_}, 258 {Opcode::OrNotSR, shifts_and_rotation_}, 259 {Opcode::XorNotSR, shifts_and_rotation_}, 260 {Opcode::NegSR, only_shifts_}}; 261 std::vector<Inst *> insts_; 262 263 // need to create graphs 264 ArenaAllocator &allocator_; 265 }; 266 267 class StatisticGenerator { 268 public: StatisticGenerator(InstGenerator & inst_generator,GraphCreator & graph_creator)269 StatisticGenerator(InstGenerator &inst_generator, GraphCreator &graph_creator) 270 : inst_generator_(inst_generator), graph_creator_(graph_creator) 271 { 272 } 273 274 virtual ~StatisticGenerator() = default; 275 276 typedef std::map<DataType::Type, int8_t> FULL_INST_STAT; 277 typedef std::map<RuntimeInterface::IntrinsicId, bool> FULL_INTRINSIC_STAT; 278 typedef std::pair<std::map<Opcode, FULL_INST_STAT>, FULL_INTRINSIC_STAT> FULL_STAT; 279 280 virtual void Generate() = 0; 281 GetStatistic()282 FULL_STAT &GetStatistic() 283 { 284 return statistic_; 285 } 286 287 void GenerateHTMLPage(std::string file_name); 288 289 protected: 290 InstGenerator &inst_generator_; 291 GraphCreator &graph_creator_; 292 293 int all_inst_number_ = 0; 294 int positive_inst_number = 0; 295 296 int all_opcode_number_ = 0; 297 int implemented_opcode_number_ = 0; 298 299 FULL_STAT statistic_; 300 301 FULL_INST_STAT tmplt_ = { 302 {DataType::NO_TYPE, -1}, {DataType::REFERENCE, -1}, {DataType::BOOL, -1}, {DataType::UINT8, -1}, 303 {DataType::INT8, -1}, {DataType::UINT16, -1}, {DataType::INT16, -1}, {DataType::UINT32, -1}, 304 {DataType::INT32, -1}, {DataType::UINT64, -1}, {DataType::INT64, -1}, {DataType::FLOAT32, -1}, 305 {DataType::FLOAT64, -1}, {DataType::ANY, -1}, {DataType::VOID, -1}, 306 }; 307 }; 308 } // namespace panda::compiler 309 310 #endif // COMPILER_TESTS_INST_GENERATOR_H 311