1 /* 2 * Copyright (c) 2024-2025 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 VisitLoadUniqueObject(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 VisitCallDynamic(GraphVisitor *visitor, Inst *inst); 295 296 static void VisitCallNative(GraphVisitor *visitor, Inst *inst); 297 static void VisitWrapObjectNative(GraphVisitor *visitor, Inst *inst); 298 299 static void VisitLoadConstantPool(GraphVisitor *visitor, Inst *inst); 300 static void VisitLoadLexicalEnv(GraphVisitor *visitor, Inst *inst); 301 302 static void VisitLoadFromConstantPool(GraphVisitor *visitor, Inst *inst); 303 304 static void VisitSafePoint(GraphVisitor *visitor, Inst *inst); 305 306 static void VisitSelect(GraphVisitor *visitor, Inst *inst); 307 308 static void VisitSelectImm(GraphVisitor *visitor, Inst *inst); 309 310 static void VisitLoadArrayPair(GraphVisitor *visitor, Inst *inst); 311 312 static void VisitLoadArrayPairI(GraphVisitor *visitor, Inst *inst); 313 314 static void VisitLoadPairPart(GraphVisitor *visitor, Inst *inst); 315 316 static void VisitLoadObjectPair(GraphVisitor *visitor, Inst *inst); 317 318 static void VisitStoreArrayPair(GraphVisitor *visitor, Inst *inst); 319 320 static void VisitStoreArrayPairI(GraphVisitor *visitor, Inst *inst); 321 322 static void VisitStoreObjectPair(GraphVisitor *visitor, Inst *inst); 323 324 static void VisitLoadExclusive(GraphVisitor *visitor, Inst *inst); 325 326 static void VisitStoreExclusive(GraphVisitor *visitor, Inst *inst); 327 328 static void VisitNOP(GraphVisitor *visitor, Inst *inst); 329 330 static void VisitThrow(GraphVisitor *visitor, Inst *inst); 331 332 static void VisitDeoptimizeIf(GraphVisitor *visitor, Inst *inst); 333 334 static void VisitDeoptimizeCompare(GraphVisitor *visitor, Inst *inst); 335 336 static void VisitDeoptimizeCompareImm(GraphVisitor *visitor, Inst *inst); 337 338 static void VisitDeoptimize(GraphVisitor *visitor, Inst *inst); 339 340 static void VisitIsMustDeoptimize(GraphVisitor *visitor, Inst *inst); 341 342 static void VisitMAdd(GraphVisitor *visitor, Inst *inst); 343 static void VisitMSub(GraphVisitor *visitor, Inst *inst); 344 static void VisitMNeg(GraphVisitor *visitor, Inst *inst); 345 static void VisitOrNot(GraphVisitor *visitor, Inst *inst); 346 static void VisitAndNot(GraphVisitor *visitor, Inst *inst); 347 static void VisitXorNot(GraphVisitor *visitor, Inst *inst); 348 static void VisitNegSR(GraphVisitor *visitor, Inst *inst); 349 350 static void VisitGetInstanceClass(GraphVisitor *visitor, Inst *inst); 351 static void VisitGetManagedClassObject(GraphVisitor *visito, Inst *inst); 352 static void VisitLoadImmediate(GraphVisitor *visitor, Inst *inst); 353 static void VisitFunctionImmediate(GraphVisitor *visitor, Inst *inst); 354 static void VisitLoadObjFromConst(GraphVisitor *visitor, Inst *inst); 355 static void VisitRegDef(GraphVisitor *visitor, Inst *inst); 356 static void VisitLiveIn(GraphVisitor *visitor, Inst *inst); 357 static void VisitLiveOut(GraphVisitor *visitor, Inst *inst); 358 static void VisitCallIndirect(GraphVisitor *visitor, Inst *inst); 359 static void VisitCall(GraphVisitor *visitor, Inst *inst); 360 361 static void VisitResolveByName(GraphVisitor *visitor, Inst *inst); 362 363 // Dyn inst. 364 static void VisitCompareAnyType(GraphVisitor *visitor, Inst *inst); 365 static void VisitGetAnyTypeName(GraphVisitor *visitor, Inst *inst); 366 static void VisitCastAnyTypeValue(GraphVisitor *visitor, Inst *inst); 367 static void VisitCastValueToAnyType(GraphVisitor *visitor, Inst *inst); 368 static void VisitAnyTypeCheck(GraphVisitor *visitor, Inst *inst); 369 static void VisitHclassCheck(GraphVisitor *visitor, Inst *inst); 370 static void VisitObjByIndexCheck(GraphVisitor *visitor, Inst *inst); 371 372 static void VisitLoadObjectDynamic(GraphVisitor *visitor, Inst *inst); 373 static void VisitStoreObjectDynamic(GraphVisitor *visitor, Inst *inst); 374 VisitDefault(Inst * inst)375 void VisitDefault([[maybe_unused]] Inst *inst) override 376 { 377 #ifndef NDEBUG 378 COMPILER_LOG(DEBUG, CODEGEN) << "Can't encode instruction " << GetOpcodeString(inst->GetOpcode()) 379 << " with type " << DataType::ToString(inst->GetType()); 380 #endif 381 success_ = false; 382 } 383 384 // Helper functions 385 static void FillUnresolvedClass(GraphVisitor *visitor, Inst *inst); 386 static void FillObjectClass(GraphVisitor *visitor, Reg tmpReg, LabelHolder::LabelId throwLabel); 387 static void FillOtherClass(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId throwLabel); 388 static void FillArrayObjectClass(GraphVisitor *visitor, Reg tmpReg, LabelHolder::LabelId throwLabel); 389 static void FillArrayClass(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId throwLabel); 390 static void FillInterfaceClass(GraphVisitor *visitor, Inst *inst); 391 392 static void FillLoadClassUnresolved(GraphVisitor *visitor, Inst *inst); 393 394 static void FillCheckCast(GraphVisitor *visitor, Inst *inst, Reg src, LabelHolder::LabelId endLabel, 395 compiler::ClassType klassType); 396 397 static void FillIsInstanceUnresolved(GraphVisitor *visitor, Inst *inst); 398 399 static void FillIsInstanceCaseObject(GraphVisitor *visitor, Inst *inst, Reg tmpReg); 400 401 static void FillIsInstanceCaseOther(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId endLabel); 402 403 static void FillIsInstanceCaseArrayObject(GraphVisitor *visitor, Inst *inst, Reg tmpReg, 404 LabelHolder::LabelId endLabel); 405 406 static void FillIsInstanceCaseArrayClass(GraphVisitor *visitor, Inst *inst, Reg tmpReg, 407 LabelHolder::LabelId endLabel); 408 409 static void FillIsInstanceCaseInterface(GraphVisitor *visitor, Inst *inst); 410 411 static void FillIsInstance(GraphVisitor *visitor, Inst *inst, Reg tmpReg, LabelHolder::LabelId endLabel); 412 static void EncodeLoadAndInitClassInAot(EncodeVisitor *enc, Encoder *encoder, Inst *inst, uint32_t classId, 413 Reg dst); 414 415 #include "optimizer/ir/visitor.inc" 416 417 private: 418 Codegen *cg_; 419 Arch arch_; 420 bool success_ {true}; 421 }; // EncodeVisitor 422 423 } // namespace ark::compiler 424 425 #endif // COMPILER_OPTIMIZER_CODEGEN_ENCODE_VISITOR_H 426