1 /* 2 * Copyright (c) 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_OPTIMIZER_CODEGEN_ENCODE_VISITOR_H 17 #define COMPILER_OPTIMIZER_CODEGEN_ENCODE_VISITOR_H 18 19 #include "codegen.h" 20 21 namespace ark::compiler { 22 23 class Encoder; 24 class CodeBuilder; 25 class OsrEntryStub; 26 27 class EncodeVisitor : public GraphVisitor { 28 using EntrypointId = RuntimeInterface::EntrypointId; 29 30 public: EncodeVisitor(Codegen * cg)31 explicit EncodeVisitor(Codegen *cg) : cg_(cg), arch_(cg->GetArch()) {} 32 33 EncodeVisitor() = delete; 34 GetBlocksToVisit()35 const ArenaVector<BasicBlock *> &GetBlocksToVisit() const override 36 { 37 return cg_->GetGraph()->GetBlocksRPO(); 38 } GetCodegen()39 Codegen *GetCodegen() const 40 { 41 return cg_; 42 } GetEncoder()43 Encoder *GetEncoder() 44 { 45 return cg_->GetEncoder(); 46 } GetArch()47 Arch GetArch() const 48 { 49 return arch_; 50 } GetCallingConvention()51 CallingConvention *GetCallingConvention() 52 { 53 return cg_->GetCallingConvention(); 54 } 55 GetRegfile()56 RegistersDescription *GetRegfile() 57 { 58 return cg_->GetRegfile(); 59 } 60 GetResult()61 bool GetResult() 62 { 63 return success_ && cg_->GetEncoder()->GetResult(); 64 } 65 66 // For each group of SpillFillData representing spill or fill operations and 67 // sharing the same source and destination types order by stack slot number in descending order. 68 static void SortSpillFillData(ArenaVector<SpillFillData> *spillFills); 69 // Checks if two spill-fill operations could be coalesced into single operation over pair of arguments. 70 static bool CanCombineSpillFills(SpillFillData pred, SpillFillData succ, const CFrameLayout &fl, 71 const Graph *graph); 72 73 protected: 74 // UnaryOperation 75 static void VisitMov(GraphVisitor *visitor, Inst *inst); 76 static void VisitNeg(GraphVisitor *visitor, Inst *inst); 77 static void VisitAbs(GraphVisitor *visitor, Inst *inst); 78 static void VisitNot(GraphVisitor *visitor, Inst *inst); 79 static void VisitSqrt(GraphVisitor *visitor, Inst *inst); 80 81 // BinaryOperation 82 static void VisitAdd(GraphVisitor *visitor, Inst *inst); 83 static void VisitSub(GraphVisitor *visitor, Inst *inst); 84 static void VisitMul(GraphVisitor *visitor, Inst *inst); 85 static void VisitShl(GraphVisitor *visitor, Inst *inst); 86 static void VisitAShr(GraphVisitor *visitor, Inst *inst); 87 static void VisitAnd(GraphVisitor *visitor, Inst *inst); 88 static void VisitOr(GraphVisitor *visitor, Inst *inst); 89 static void VisitXor(GraphVisitor *visitor, Inst *inst); 90 91 // Binary Overflow Operation 92 static void VisitAddOverflow(GraphVisitor *visitor, Inst *inst); 93 static void VisitAddOverflowCheck(GraphVisitor *visitor, Inst *inst); 94 static void VisitSubOverflow(GraphVisitor *visitor, Inst *inst); 95 static void VisitSubOverflowCheck(GraphVisitor *visitor, Inst *inst); 96 static void VisitNegOverflowAndZeroCheck(GraphVisitor *visitor, Inst *inst); 97 98 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 99 #define BINARY_IMM_OPERATION(opc) static void Visit##opc##I(GraphVisitor *visitor, Inst *inst) 100 101 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 102 #define BINARY_IMM_OPS(DEF) \ 103 DEF(Add); \ 104 DEF(Sub); \ 105 DEF(Shl); \ 106 DEF(AShr); \ 107 DEF(And); \ 108 DEF(Or); \ 109 DEF(Xor); \ 110 DEF(Div); \ 111 DEF(Mod) 112 113 BINARY_IMM_OPS(BINARY_IMM_OPERATION); 114 115 #undef BINARY_IMM_OPS 116 #undef BINARY_IMM_OPERATION 117 118 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 119 #define BINARY_SIGN_UNSIGN_OPERATION(opc) static void Visit##opc(GraphVisitor *visitor, Inst *inst) 120 121 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 122 #define SIGN_UNSIGN_OPS(DEF) \ 123 DEF(Div); \ 124 DEF(Mod); \ 125 DEF(Min); \ 126 DEF(Max); \ 127 DEF(Shr) 128 129 SIGN_UNSIGN_OPS(BINARY_SIGN_UNSIGN_OPERATION); 130 131 #undef SIGN_UNSIGN_OPS 132 #undef BINARY_SIGN_UNSIGN_OPERATION 133 134 // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) 135 #define BINARY_SHIFTED_REGISTER_OPERATION_DEF(opc, ignored) \ 136 /* CC-OFFNXT(G.PRE.09) code generation */ \ 137 static void Visit##opc##SR(GraphVisitor *visitor, Inst *inst); 138 139 ENCODE_INST_WITH_SHIFTED_OPERAND(BINARY_SHIFTED_REGISTER_OPERATION_DEF) 140 141 #undef BINARY_SHIFTED_REGISTER_OPERATION_DEF 142 143 static void VisitShrI(GraphVisitor *visitor, Inst *inst); 144 145 static void VisitCast(GraphVisitor *visitor, Inst *inst); 146 147 static void VisitBitcast(GraphVisitor *visitor, Inst *inst); 148 149 static void VisitPhi([[maybe_unused]] GraphVisitor *visitor, [[maybe_unused]] Inst *inst); 150 151 static void VisitConstant(GraphVisitor *visitor, Inst *inst); 152 153 static void VisitNullPtr(GraphVisitor *visitor, Inst *inst); 154 155 static void VisitLoadUndefined(GraphVisitor *visitor, Inst *inst); 156 157 static void VisitIf(GraphVisitor *visitor, Inst *inst); 158 159 static void VisitIfImm(GraphVisitor *visitor, Inst *inst); 160 161 static void VisitCompare(GraphVisitor *visitor, Inst *inst); 162 163 static void VisitCmp(GraphVisitor *visitor, Inst *inst); 164 165 // All next visitors use execution model for implementation 166 static void VisitReturnVoid(GraphVisitor *visitor, Inst * /* unused */); 167 168 static void VisitReturn(GraphVisitor *visitor, Inst *inst); 169 170 static void VisitReturnI(GraphVisitor *visitor, Inst *inst); 171 172 static void VisitReturnInlined(GraphVisitor *visitor, Inst * /* unused */); 173 174 static void VisitNewArray(GraphVisitor *visitor, Inst *inst); 175 176 static void VisitLoadConstArray(GraphVisitor *visitor, Inst *inst); 177 178 static void VisitFillConstArray(GraphVisitor *visitor, Inst *inst); 179 180 static void VisitParameter(GraphVisitor *visitor, Inst *inst); 181 182 static void VisitStoreArray(GraphVisitor *visitor, Inst *inst); 183 184 static void VisitSpillFill(GraphVisitor *visitor, Inst *inst); 185 186 static void VisitSaveState(GraphVisitor *visitor, Inst *inst); 187 188 static void VisitSaveStateDeoptimize(GraphVisitor *visitor, Inst *inst); 189 190 static void VisitSaveStateOsr(GraphVisitor *visitor, Inst *inst); 191 192 static void VisitLoadArray(GraphVisitor *visitor, Inst *inst); 193 194 static void VisitLoadCompressedStringChar(GraphVisitor *visitor, Inst *inst); 195 196 static void VisitLenArray(GraphVisitor *visitor, Inst *inst); 197 198 static void VisitNullCheck(GraphVisitor *visitor, Inst *inst); 199 200 static void VisitBoundsCheck(GraphVisitor *visitor, Inst *inst); 201 202 static void VisitZeroCheck(GraphVisitor *visitor, Inst *inst); 203 204 static void VisitRefTypeCheck(GraphVisitor *visitor, Inst *inst); 205 206 static void VisitNegativeCheck(GraphVisitor *visitor, Inst *inst); 207 208 static void VisitNotPositiveCheck(GraphVisitor *visitor, Inst *inst); 209 210 static void VisitLoadString(GraphVisitor *visitor, Inst *inst); 211 212 static void VisitResolveObjectField(GraphVisitor *visitor, Inst *inst); 213 214 static void VisitLoadResolvedObjectField(GraphVisitor *visitor, Inst *inst); 215 216 static void VisitLoadObject(GraphVisitor *visitor, Inst *inst); 217 218 static void VisitLoad(GraphVisitor *visitor, Inst *inst); 219 220 static void VisitStoreObject(GraphVisitor *visitor, Inst *inst); 221 222 static void VisitStoreResolvedObjectField(GraphVisitor *visitor, Inst *inst); 223 224 static void VisitStore(GraphVisitor *visitor, Inst *inst); 225 226 static void VisitLoadStatic(GraphVisitor *visitor, Inst *inst); 227 228 static void VisitResolveObjectFieldStatic(GraphVisitor *visitor, Inst *inst); 229 230 static void VisitLoadResolvedObjectFieldStatic(GraphVisitor *visitor, Inst *inst); 231 232 static void VisitStoreStatic(GraphVisitor *visitor, Inst *inst); 233 234 static void VisitUnresolvedStoreStatic(GraphVisitor *visitor, Inst *inst); 235 236 static void VisitStoreResolvedObjectFieldStatic(GraphVisitor *visitor, Inst *inst); 237 238 static void VisitNewObject(GraphVisitor *visitor, Inst *inst); 239 240 static void VisitLoadRuntimeClass(GraphVisitor *visitor, Inst *inst); 241 242 static void VisitLoadClass(GraphVisitor *visitor, Inst *inst); 243 244 static void VisitLoadAndInitClass(GraphVisitor *visitor, Inst *inst); 245 246 static void VisitGetGlobalVarAddress(GraphVisitor *visitor, Inst *inst); 247 248 static void VisitUnresolvedLoadAndInitClass(GraphVisitor *visitor, Inst *inst); 249 250 static void VisitInitClass(GraphVisitor *visitor, Inst *inst); 251 252 static void VisitUnresolvedInitClass(GraphVisitor *visitor, Inst *inst); 253 254 static void VisitLoadType(GraphVisitor *visitor, Inst *inst); 255 256 static void VisitUnresolvedLoadType(GraphVisitor *visitor, Inst *inst); 257 258 static void VisitCheckCast(GraphVisitor *visitor, Inst *inst); 259 260 static void VisitIsInstance(GraphVisitor *visitor, Inst *inst); 261 262 static void VisitMonitor(GraphVisitor *visitor, Inst *inst); 263 264 static void VisitIntrinsic(GraphVisitor *visitor, Inst *inst); 265 266 static void VisitBuiltin(GraphVisitor *visitor, Inst *inst); 267 268 static void VisitBoundsCheckI(GraphVisitor *visitor, Inst *inst); 269 270 static void VisitStoreArrayI(GraphVisitor *visitor, Inst *inst); 271 272 static void VisitLoadArrayI(GraphVisitor *visitor, Inst *inst); 273 274 static void VisitLoadCompressedStringCharI(GraphVisitor *visitor, Inst *inst); 275 276 static void VisitLoadI(GraphVisitor *visitor, Inst *inst); 277 278 static void VisitStoreI(GraphVisitor *visitor, Inst *inst); 279 280 static void VisitMultiArray(GraphVisitor *visitor, Inst *inst); 281 static void VisitInitEmptyString(GraphVisitor *visitor, Inst *inst); 282 static void VisitInitString(GraphVisitor *visitor, Inst *inst); 283 284 static void VisitCallStatic(GraphVisitor *visitor, Inst *inst); 285 286 static void VisitResolveStatic(GraphVisitor *visitor, Inst *inst); 287 static void VisitCallResolvedStatic(GraphVisitor *visitor, Inst *inst); 288 289 static void VisitCallVirtual(GraphVisitor *visitor, Inst *inst); 290 291 static void VisitResolveVirtual(GraphVisitor *visitor, Inst *inst); 292 static void VisitCallResolvedVirtual(GraphVisitor *visitor, Inst *inst); 293 294 static void VisitCallLaunchStatic(GraphVisitor *visitor, Inst *inst); 295 static void VisitCallResolvedLaunchStatic(GraphVisitor *visitor, Inst *inst); 296 297 static void VisitCallLaunchVirtual(GraphVisitor *visitor, Inst *inst); 298 static void VisitCallResolvedLaunchVirtual(GraphVisitor *visitor, Inst *inst); 299 300 static void VisitCallDynamic(GraphVisitor *visitor, Inst *inst); 301 302 static void VisitLoadConstantPool(GraphVisitor *visitor, Inst *inst); 303 static void VisitLoadLexicalEnv(GraphVisitor *visitor, Inst *inst); 304 305 static void VisitLoadFromConstantPool(GraphVisitor *visitor, Inst *inst); 306 307 static void VisitSafePoint(GraphVisitor *visitor, Inst *inst); 308 309 static void VisitSelect(GraphVisitor *visitor, Inst *inst); 310 311 static void VisitSelectImm(GraphVisitor *visitor, Inst *inst); 312 313 static void VisitLoadArrayPair(GraphVisitor *visitor, Inst *inst); 314 315 static void VisitLoadArrayPairI(GraphVisitor *visitor, Inst *inst); 316 317 static void VisitLoadPairPart(GraphVisitor *visitor, Inst *inst); 318 319 static void VisitLoadObjectPair(GraphVisitor *visitor, Inst *inst); 320 321 static void VisitStoreArrayPair(GraphVisitor *visitor, Inst *inst); 322 323 static void VisitStoreArrayPairI(GraphVisitor *visitor, Inst *inst); 324 325 static void VisitStoreObjectPair(GraphVisitor *visitor, Inst *inst); 326 327 static void VisitLoadExclusive(GraphVisitor *visitor, Inst *inst); 328 329 static void VisitStoreExclusive(GraphVisitor *visitor, Inst *inst); 330 331 static void VisitNOP(GraphVisitor *visitor, Inst *inst); 332 333 static void VisitThrow(GraphVisitor *visitor, Inst *inst); 334 335 static void VisitDeoptimizeIf(GraphVisitor *visitor, Inst *inst); 336 337 static void VisitDeoptimizeCompare(GraphVisitor *visitor, Inst *inst); 338 339 static void VisitDeoptimizeCompareImm(GraphVisitor *visitor, Inst *inst); 340 341 static void VisitDeoptimize(GraphVisitor *visitor, Inst *inst); 342 343 static void VisitIsMustDeoptimize(GraphVisitor *visitor, Inst *inst); 344 345 static void VisitMAdd(GraphVisitor *visitor, Inst *inst); 346 static void VisitMSub(GraphVisitor *visitor, Inst *inst); 347 static void VisitMNeg(GraphVisitor *visitor, Inst *inst); 348 static void VisitOrNot(GraphVisitor *visitor, Inst *inst); 349 static void VisitAndNot(GraphVisitor *visitor, Inst *inst); 350 static void VisitXorNot(GraphVisitor *visitor, Inst *inst); 351 static void VisitNegSR(GraphVisitor *visitor, Inst *inst); 352 353 static void VisitGetInstanceClass(GraphVisitor *visitor, Inst *inst); 354 static void VisitGetManagedClassObject(GraphVisitor *visito, Inst *inst); 355 static void VisitLoadImmediate(GraphVisitor *visitor, Inst *inst); 356 static void VisitFunctionImmediate(GraphVisitor *visitor, Inst *inst); 357 static void VisitLoadObjFromConst(GraphVisitor *visitor, Inst *inst); 358 static void VisitRegDef(GraphVisitor *visitor, Inst *inst); 359 static void VisitLiveIn(GraphVisitor *visitor, Inst *inst); 360 static void VisitLiveOut(GraphVisitor *visitor, Inst *inst); 361 static void VisitCallIndirect(GraphVisitor *visitor, Inst *inst); 362 static void VisitCall(GraphVisitor *visitor, Inst *inst); 363 364 // Dyn inst. 365 static void VisitCompareAnyType(GraphVisitor *visitor, Inst *inst); 366 static void VisitGetAnyTypeName(GraphVisitor *visitor, Inst *inst); 367 static void VisitCastAnyTypeValue(GraphVisitor *visitor, Inst *inst); 368 static void VisitCastValueToAnyType(GraphVisitor *visitor, Inst *inst); 369 static void VisitAnyTypeCheck(GraphVisitor *visitor, Inst *inst); 370 static void VisitHclassCheck(GraphVisitor *visitor, Inst *inst); 371 static void VisitObjByIndexCheck(GraphVisitor *visitor, Inst *inst); 372 373 static void VisitLoadObjectDynamic(GraphVisitor *visitor, Inst *inst); 374 static void VisitStoreObjectDynamic(GraphVisitor *visitor, Inst *inst); 375 VisitDefault(Inst * inst)376 void VisitDefault([[maybe_unused]] Inst *inst) override 377 { 378 #ifndef NDEBUG 379 COMPILER_LOG(DEBUG, CODEGEN) << "Can't encode instruction " << GetOpcodeString(inst->GetOpcode()) 380 << " with type " << DataType::ToString(inst->GetType()); 381 #endif 382 success_ = false; 383 } 384 385 // Helper functions 386 static void FillUnresolvedClass(GraphVisitor *visitor, Inst *inst); 387 static void FillObjectClass(GraphVisitor *visitor, Reg tmpReg, LabelHolder::LabelId throwLabel); 388 static void FillOtherClass(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId throwLabel); 389 static void FillArrayObjectClass(GraphVisitor *visitor, Reg tmpReg, LabelHolder::LabelId throwLabel); 390 static void FillArrayClass(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId throwLabel); 391 static void FillInterfaceClass(GraphVisitor *visitor, Inst *inst); 392 393 static void FillLoadClassUnresolved(GraphVisitor *visitor, Inst *inst); 394 395 static void FillCheckCast(GraphVisitor *visitor, Inst *inst, Reg src, LabelHolder::LabelId endLabel, 396 compiler::ClassType klassType); 397 398 static void FillIsInstanceUnresolved(GraphVisitor *visitor, Inst *inst); 399 400 static void FillIsInstanceCaseObject(GraphVisitor *visitor, Inst *inst, Reg tmpReg); 401 402 static void FillIsInstanceCaseOther(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId endLabel); 403 404 static void FillIsInstanceCaseArrayObject(GraphVisitor *visitor, Inst *inst, Reg tmpReg, 405 LabelHolder::LabelId endLabel); 406 407 static void FillIsInstanceCaseArrayClass(GraphVisitor *visitor, Inst *inst, Reg tmpReg, 408 LabelHolder::LabelId endLabel); 409 410 static void FillIsInstanceCaseInterface(GraphVisitor *visitor, Inst *inst); 411 412 static void FillIsInstance(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId endLabel); 413 static void EncodeLoadAndInitClassInAot(EncodeVisitor *enc, Encoder *encoder, Inst *inst, uint32_t classId, 414 Reg dst); 415 416 #include "optimizer/ir/visitor.inc" 417 418 private: 419 Codegen *cg_; 420 Arch arch_; 421 bool success_ {true}; 422 }; // EncodeVisitor 423 424 } // namespace ark::compiler 425 426 #endif // COMPILER_OPTIMIZER_CODEGEN_ENCODE_VISITOR_H 427