1 /* 2 * Copyright (c) 2021-2024 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 "macros.h" 20 #include "unit_test.h" 21 22 namespace ark::compiler { 23 class GraphCreator { 24 public: 25 GraphCreator() = delete; GraphCreator(ArenaAllocator & allocator,ArenaAllocator & localAllocator)26 explicit GraphCreator(ArenaAllocator &allocator, ArenaAllocator &localAllocator) 27 : allocator_(allocator), localAllocator_(localAllocator) 28 { 29 } 30 31 Graph *GenerateGraph(Inst *inst); 32 SetRuntimeTargetArch(Arch arch)33 void SetRuntimeTargetArch(Arch arch) 34 { 35 arch_ = arch; 36 } 37 GetRuntimeTargetArch()38 Arch GetRuntimeTargetArch() const 39 { 40 return arch_; 41 } 42 GetRuntime()43 RuntimeInterface *GetRuntime() 44 { 45 return &runtime_; 46 } 47 GetAllocator()48 ArenaAllocator *GetAllocator() const 49 { 50 return &allocator_; 51 } 52 GetLocalAllocator()53 ArenaAllocator *GetLocalAllocator() const 54 { 55 return &localAllocator_; 56 } 57 58 private: 59 Graph *CreateGraph(); 60 61 Inst *PopulateLoadArrayPair(Graph *graph, BasicBlock *block, Inst *inst, Opcode opc); 62 void PopulateStoreArrayPair(Graph *graph, Inst *inst, Opcode opc); 63 void PopulateReturnInlined(Graph *graph, BasicBlock *block, Inst *inst, int32_t n); 64 void PopulateCall(Graph *graph, BasicBlock *block, Inst *inst, DataType::Type type, int32_t n); 65 void PopulateLoadStoreArray(Graph *graph, Inst *inst, DataType::Type type, int32_t n); 66 void PopulateLoadStoreArrayI(Graph *graph, Inst *inst, DataType::Type type, int32_t n); 67 void PopulateSelect(Graph *graph, Inst *inst, DataType::Type type, int32_t n); 68 void PopulateSelectI(Graph *graph, Inst *inst, DataType::Type type, int32_t n); 69 void PopulateStoreStatic(Graph *graph, BasicBlock *block, Inst *inst, DataType::Type type); 70 void PopulateLoadStatic(Graph *graph, BasicBlock *block, Inst *inst); 71 void PopulateMonitor(Graph *graph, BasicBlock *block, Inst *inst); 72 void PopulateLoadType(Graph *graph, BasicBlock *block, Inst *inst); 73 void PopulateIsInstance(Graph *graph, BasicBlock *block, Inst *inst); 74 void PopulateNewArray(Graph *graph, BasicBlock *block, Inst *inst, int32_t n); 75 void PopulateNewObject(Graph *graph, BasicBlock *block, Inst *inst, int32_t n); 76 void PopulateDefault(Graph *graph, Inst *inst, DataType::Type type, int32_t n); 77 void PopulateGraph(Graph *graph, Inst *inst, int32_t n); 78 void Finalize(Graph *graph, BasicBlock *block, Inst *inst); 79 80 Graph *GenerateOperation(Inst *inst, int32_t n); 81 Graph *GenerateCheckOperation(Inst *inst); 82 Graph *GenerateSSOperation(Inst *inst); 83 Graph *GenerateBoundaryCheckOperation(Inst *inst); 84 Graph *GenerateThrowOperation(Inst *inst); 85 Graph *GenerateMultiArrayOperation(Inst *inst); 86 Graph *GeneratePhiOperation(Inst *inst); 87 88 #include "generate_operations_intrinsic_graph.inl" 89 90 Graph *CreateGraphWithOneBasicBlock(); 91 Graph *CreateGraphWithTwoBasicBlock(); 92 Graph *CreateGraphWithThreeBasicBlock(); 93 Graph *CreateGraphWithFourBasicBlock(); 94 ParameterInst *CreateParamInst(Graph *graph, DataType::Type type, uint8_t slot); 95 96 struct PackArgsForCkeckInst { 97 Opcode opcode; 98 DataType::Type type; 99 Inst *inst; 100 ParameterInst *param1; 101 ParameterInst *param2; 102 103 SaveStateInst *saveState; 104 BasicBlock *block; 105 Graph *graph; 106 }; 107 108 Inst *CreateCheckInstByPackArgs(const PackArgsForCkeckInst &pack); 109 110 private: 111 // need to create graphs 112 ArenaAllocator &allocator_; 113 ArenaAllocator &localAllocator_; 114 RuntimeInterfaceMock runtime_; 115 Arch arch_ {Arch::AARCH64}; 116 117 public: SetNumVRegsArgs(size_t regs,size_t args)118 void SetNumVRegsArgs(size_t regs, size_t args) 119 { 120 runtime_.vregsCount_ = regs; 121 runtime_.argsCount_ = args; 122 } 123 }; 124 125 class InstGenerator { 126 public: 127 InstGenerator() = delete; InstGenerator(ArenaAllocator & allocator)128 explicit InstGenerator(ArenaAllocator &allocator) : allocator_(allocator) {} 129 130 std::vector<Inst *> &Generate(Opcode opCode); 131 GetAllPossibleInstToGenerateNumber()132 int GetAllPossibleInstToGenerateNumber() 133 { 134 int result = 0; 135 for (auto &it : opcodeXPossibleTypes_) { 136 result += it.second.size(); 137 } 138 return result; 139 } 140 GetPossibleInstToGenerateNumber(Opcode opCode)141 int GetPossibleInstToGenerateNumber(Opcode opCode) 142 { 143 return opcodeXPossibleTypes_[opCode].size(); 144 } 145 GetMap()146 std::map<Opcode, std::vector<DataType::Type>> &GetMap() 147 { 148 return opcodeXPossibleTypes_; 149 } 150 GetAllocator()151 ArenaAllocator *GetAllocator() 152 { 153 return &allocator_; 154 } 155 156 private: 157 template <class T> 158 std::vector<Inst *> &GenerateOperations(Opcode opCode); 159 160 template <class T> 161 std::vector<Inst *> &GenerateOperationsImm(Opcode opCode); 162 163 template <class T> 164 std::vector<Inst *> &GenerateOperationsShiftedRegister(Opcode opCode); 165 GenerateIntrinsic(DataType::Type type,RuntimeInterface::IntrinsicId intrinsicId)166 void GenerateIntrinsic(DataType::Type type, RuntimeInterface::IntrinsicId intrinsicId) 167 { 168 auto inst = Inst::New<IntrinsicInst>(&allocator_, Opcode::Intrinsic); 169 inst->SetType(type); 170 inst->SetIntrinsicId(intrinsicId); 171 insts_.push_back(inst); 172 } 173 174 void SetFlagsNoCseNoHoistIfReference(Inst *inst, DataType::Type dstType); 175 176 std::vector<DataType::Type> integerTypes_ {DataType::UINT8, DataType::INT8, DataType::UINT16, DataType::INT16, 177 DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64}; 178 179 std::vector<DataType::Type> numericTypes_ {DataType::BOOL, DataType::UINT8, DataType::INT8, DataType::UINT16, 180 DataType::INT16, DataType::UINT32, DataType::INT32, DataType::UINT64, 181 DataType::INT64, DataType::FLOAT32, DataType::FLOAT64}; 182 183 std::vector<DataType::Type> refNumTypes_ { 184 DataType::REFERENCE, DataType::BOOL, DataType::UINT8, DataType::INT8, DataType::UINT16, DataType::INT16, 185 DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64}; 186 187 std::vector<DataType::Type> refIntTypes_ {DataType::REFERENCE, DataType::BOOL, DataType::UINT8, DataType::INT8, 188 DataType::UINT16, DataType::INT16, DataType::UINT32, DataType::INT32, 189 DataType::UINT64, DataType::INT64}; 190 191 std::vector<DataType::Type> allTypes_ {DataType::REFERENCE, DataType::BOOL, DataType::UINT8, DataType::INT8, 192 DataType::UINT16, DataType::INT16, DataType::UINT32, DataType::INT32, 193 DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 194 DataType::VOID}; 195 196 std::vector<DataType::Type> floatsTypes_ {DataType::FLOAT32, DataType::FLOAT64}; 197 198 std::map<Opcode, std::vector<DataType::Type>> opcodeXPossibleTypes_ = { 199 {Opcode::Neg, numericTypes_}, 200 {Opcode::Abs, numericTypes_}, 201 {Opcode::Not, integerTypes_}, 202 {Opcode::Add, numericTypes_}, 203 {Opcode::Sub, numericTypes_}, 204 {Opcode::Mul, numericTypes_}, 205 {Opcode::Div, numericTypes_}, 206 {Opcode::Min, numericTypes_}, 207 {Opcode::Max, numericTypes_}, 208 {Opcode::Shl, integerTypes_}, 209 {Opcode::Shr, integerTypes_}, 210 {Opcode::AShr, integerTypes_}, 211 {Opcode::Mod, numericTypes_}, 212 {Opcode::And, integerTypes_}, 213 {Opcode::Or, integerTypes_}, 214 {Opcode::Xor, integerTypes_}, 215 {Opcode::Compare, refNumTypes_}, 216 {Opcode::If, refIntTypes_}, 217 {Opcode::Cmp, {DataType::INT32}}, 218 {Opcode::Constant, {DataType::INT64, DataType::FLOAT32, DataType::FLOAT64}}, 219 {Opcode::Phi, refNumTypes_}, 220 {Opcode::IfImm, refIntTypes_}, 221 {Opcode::Cast, numericTypes_}, 222 {Opcode::Parameter, refNumTypes_}, 223 {Opcode::IsInstance, {DataType::BOOL}}, 224 {Opcode::LenArray, {DataType::INT32}}, 225 {Opcode::LoadArray, refNumTypes_}, 226 {Opcode::StoreArray, refNumTypes_}, 227 {Opcode::LoadArrayI, refNumTypes_}, 228 {Opcode::StoreArrayI, refNumTypes_}, 229 {Opcode::CheckCast, {DataType::NO_TYPE}}, 230 {Opcode::NullCheck, {DataType::NO_TYPE}}, 231 {Opcode::ZeroCheck, {DataType::NO_TYPE}}, 232 {Opcode::NegativeCheck, {DataType::NO_TYPE}}, 233 {Opcode::BoundsCheck, {DataType::NO_TYPE}}, 234 {Opcode::BoundsCheckI, {DataType::NO_TYPE}}, 235 {Opcode::SaveState, {DataType::NO_TYPE}}, 236 {Opcode::ReturnVoid, {DataType::NO_TYPE}}, 237 {Opcode::Throw, {DataType::NO_TYPE}}, 238 {Opcode::NewArray, {DataType::REFERENCE}}, 239 {Opcode::Return, refNumTypes_}, 240 {Opcode::ReturnI, numericTypes_}, 241 {Opcode::CallStatic, allTypes_}, 242 {Opcode::CallVirtual, allTypes_}, 243 {Opcode::AddI, integerTypes_}, 244 {Opcode::SubI, integerTypes_}, 245 {Opcode::AndI, integerTypes_}, 246 {Opcode::OrI, integerTypes_}, 247 {Opcode::XorI, integerTypes_}, 248 {Opcode::ShrI, integerTypes_}, 249 {Opcode::ShlI, integerTypes_}, 250 {Opcode::AShrI, integerTypes_}, 251 {Opcode::SpillFill, {DataType::NO_TYPE}}, 252 {Opcode::NewObject, {DataType::REFERENCE}}, 253 {Opcode::LoadObject, refNumTypes_}, 254 {Opcode::LoadStatic, refNumTypes_}, 255 {Opcode::StoreObject, refNumTypes_}, 256 {Opcode::StoreStatic, refNumTypes_}, 257 {Opcode::LoadString, {DataType::REFERENCE}}, 258 {Opcode::LoadType, {DataType::REFERENCE}}, 259 {Opcode::SafePoint, {DataType::NO_TYPE}}, 260 {Opcode::ReturnInlined, {DataType::NO_TYPE}}, 261 {Opcode::Monitor, {DataType::VOID}}, 262 {Opcode::Intrinsic, {}}, 263 {Opcode::Select, refIntTypes_}, 264 {Opcode::SelectImm, refIntTypes_}, 265 {Opcode::NullPtr, {DataType::REFERENCE}}, 266 {Opcode::LoadArrayPair, 267 {DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 268 DataType::REFERENCE}}, 269 {Opcode::LoadArrayPairI, 270 {DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 271 DataType::REFERENCE}}, 272 {Opcode::StoreArrayPair, 273 {DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 274 DataType::REFERENCE}}, 275 {Opcode::StoreArrayPairI, 276 {DataType::UINT32, DataType::INT32, DataType::UINT64, DataType::INT64, DataType::FLOAT32, DataType::FLOAT64, 277 DataType::REFERENCE}}, 278 {Opcode::AndNot, integerTypes_}, 279 {Opcode::OrNot, integerTypes_}, 280 {Opcode::XorNot, integerTypes_}, 281 {Opcode::MNeg, numericTypes_}, 282 {Opcode::MAdd, numericTypes_}, 283 {Opcode::MSub, numericTypes_}, 284 {Opcode::AddSR, integerTypes_}, 285 {Opcode::SubSR, integerTypes_}, 286 {Opcode::AndSR, integerTypes_}, 287 {Opcode::OrSR, integerTypes_}, 288 {Opcode::XorSR, integerTypes_}, 289 {Opcode::AndNotSR, integerTypes_}, 290 {Opcode::OrNotSR, integerTypes_}, 291 {Opcode::XorNotSR, integerTypes_}, 292 {Opcode::NegSR, integerTypes_}, 293 }; 294 295 std::vector<ShiftType> onlyShifts_ = {ShiftType::LSL, ShiftType::LSR, ShiftType::ASR}; 296 std::vector<ShiftType> shiftsAndRotation_ = {ShiftType::LSL, ShiftType::LSR, ShiftType::ASR, ShiftType::ROR}; 297 std::map<Opcode, std::vector<ShiftType>> opcodeXPossibleShiftTypes_ = { 298 {Opcode::AddSR, onlyShifts_}, {Opcode::SubSR, onlyShifts_}, 299 {Opcode::AndSR, shiftsAndRotation_}, {Opcode::OrSR, shiftsAndRotation_}, 300 {Opcode::XorSR, shiftsAndRotation_}, {Opcode::AndNotSR, shiftsAndRotation_}, 301 {Opcode::OrNotSR, shiftsAndRotation_}, {Opcode::XorNotSR, shiftsAndRotation_}, 302 {Opcode::NegSR, onlyShifts_}}; 303 std::vector<Inst *> insts_; 304 305 // need to create graphs 306 ArenaAllocator &allocator_; 307 }; 308 309 // NOLINTBEGIN(misc-non-private-member-variables-in-classes) 310 class StatisticGenerator { 311 public: StatisticGenerator(InstGenerator & instGenerator,GraphCreator & graphCreator)312 StatisticGenerator(InstGenerator &instGenerator, GraphCreator &graphCreator) 313 : instGenerator_(instGenerator), graphCreator_(graphCreator) 314 { 315 } 316 317 virtual ~StatisticGenerator() = default; 318 319 NO_COPY_SEMANTIC(StatisticGenerator); 320 NO_MOVE_SEMANTIC(StatisticGenerator); 321 322 using FullInstStat = std::map<DataType::Type, int8_t>; 323 using FullIntrinsicStat = std::map<RuntimeInterface::IntrinsicId, bool>; 324 using FullStat = std::pair<std::map<Opcode, FullInstStat>, FullIntrinsicStat>; 325 326 virtual void Generate() = 0; 327 GetStatistic()328 FullStat &GetStatistic() 329 { 330 return statistic_; 331 } 332 333 void GenerateHTMLPage(const std::string &fileName); 334 335 private: 336 void FillHTMLPageHeadPart(std::ofstream &htmlPage); 337 void FillHTMLPageOpcodeStatistic(std::ofstream &htmlPage, Opcode opc); 338 339 protected: 340 InstGenerator &instGenerator_; 341 GraphCreator &graphCreator_; 342 343 int allInstNumber_ = 0; 344 int positiveInstNumber_ = 0; 345 346 int allOpcodeNumber_ = 0; 347 int implementedOpcodeNumber_ = 0; 348 349 FullStat statistic_; 350 351 FullInstStat tmplt_ = { 352 {DataType::NO_TYPE, -1}, {DataType::REFERENCE, -1}, {DataType::BOOL, -1}, {DataType::UINT8, -1}, 353 {DataType::INT8, -1}, {DataType::UINT16, -1}, {DataType::INT16, -1}, {DataType::UINT32, -1}, 354 {DataType::INT32, -1}, {DataType::UINT64, -1}, {DataType::INT64, -1}, {DataType::FLOAT32, -1}, 355 {DataType::FLOAT64, -1}, {DataType::ANY, -1}, {DataType::VOID, -1}, 356 }; 357 }; 358 // NOLINTEND(misc-non-private-member-variables-in-classes) 359 360 } // namespace ark::compiler 361 362 #endif // COMPILER_TESTS_INST_GENERATOR_H 363