diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index 11407c9cabb1da..e82b5f01cbebc0 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -180,30 +180,40 @@ unsigned emitter::emitTotalIGExtend; unsigned emitter::emitTotalIDescSmallCnt; unsigned emitter::emitTotalIDescCnt; -unsigned emitter::emitTotalIDescJmpCnt; -#if !defined(TARGET_ARM64) -unsigned emitter::emitTotalIDescLblCnt; -#endif // !defined(TARGET_ARM64) unsigned emitter::emitTotalIDescCnsCnt; unsigned emitter::emitTotalIDescDspCnt; -unsigned emitter::emitTotalIDescCnsDspCnt; +#ifdef TARGET_ARM64 +unsigned emitter::emitTotalIDescLclVarPairCnt; +unsigned emitter::emitTotalIDescLclVarPairCnsCnt; +#endif // TARGET_ARM64 +#ifdef TARGET_ARM +unsigned emitter::emitTotalIDescRelocCnt; +#endif // TARGET_ARM #ifdef TARGET_XARCH unsigned emitter::emitTotalIDescAmdCnt; unsigned emitter::emitTotalIDescCnsAmdCnt; #endif // TARGET_XARCH +unsigned emitter::emitTotalIDescCnsDspCnt; +#if FEATURE_LOOP_ALIGN +unsigned emitter::emitTotalIDescAlignCnt; +#endif // FEATURE_LOOP_ALIGN +unsigned emitter::emitTotalIDescJmpCnt; +#if !defined(TARGET_ARM64) +unsigned emitter::emitTotalIDescLblCnt; +#endif // !defined(TARGET_ARM64) unsigned emitter::emitTotalIDescCGCACnt; -#ifdef TARGET_ARM -unsigned emitter::emitTotalIDescRelocCnt; -#endif // TARGET_ARM unsigned emitter::emitSmallDspCnt; unsigned emitter::emitLargeDspCnt; +unsigned emitter::emitSmallCns[SMALL_CNS_TSZ]; unsigned emitter::emitSmallCnsCnt; unsigned emitter::emitLargeCnsCnt; -unsigned emitter::emitSmallCns[SMALL_CNS_TSZ]; - -unsigned emitter::emitTotalDescAlignCnt; +unsigned emitter::emitInt8CnsCnt; +unsigned emitter::emitInt16CnsCnt; +unsigned emitter::emitInt32CnsCnt; +unsigned emitter::emitNegCnsCnt; +unsigned emitter::emitPow2CnsCnt; void emitterStaticStats(FILE* fout) { @@ -219,116 +229,156 @@ void emitterStaticStats(FILE* fout) fprintf(fout, "\n"); fprintf(fout, "insGroup:\n"); - fprintf(fout, "Offset / size of igNext = %2zu / %2zu\n", offsetof(insGroup, igNext), + fprintf(fout, "Offset / size of igNext = %3zu / %2zu\n", offsetof(insGroup, igNext), sizeof(igDummy->igNext)); #if EMIT_BACKWARDS_NAVIGATION - fprintf(fout, "Offset / size of igPrev = %2zu / %2zu\n", offsetof(insGroup, igPrev), + fprintf(fout, "Offset / size of igPrev = %3zu / %2zu\n", offsetof(insGroup, igPrev), sizeof(igDummy->igPrev)); #endif // EMIT_BACKWARDS_NAVIGATION #ifdef DEBUG - fprintf(fout, "Offset / size of igSelf = %2zu / %2zu\n", offsetof(insGroup, igSelf), + fprintf(fout, "Offset / size of igSelf = %3zu / %2zu\n", offsetof(insGroup, igSelf), sizeof(igDummy->igSelf)); -#endif - fprintf(fout, "Offset / size of igNum = %2zu / %2zu\n", offsetof(insGroup, igNum), +#endif // DEBUG +#if defined(DEBUG) || defined(LATE_DISASM) + fprintf(fout, "Offset / size of igWeight = %3zu / %2zu\n", offsetof(insGroup, igWeight), + sizeof(igDummy->igWeight)); + fprintf(fout, "Offset / size of igPerfScore = %3zu / %2zu\n", offsetof(insGroup, igPerfScore), + sizeof(igDummy->igPerfScore)); +#endif // DEBUG || LATE_DISASM +#ifdef DEBUG + fprintf(fout, "Offset / size of lastGeneratedBlock = %3zu / %2zu\n", offsetof(insGroup, lastGeneratedBlock), + sizeof(igDummy->lastGeneratedBlock)); + fprintf(fout, "Offset / size of igBlocks = %3zu / %2zu\n", offsetof(insGroup, igBlocks), + sizeof(igDummy->igBlocks)); + fprintf(fout, "Offset / size of igDataSize = %3zu / %2zu\n", offsetof(insGroup, igDataSize), + sizeof(igDummy->igDataSize)); +#endif // DEBUG + fprintf(fout, "Offset / size of igNum = %3zu / %2zu\n", offsetof(insGroup, igNum), sizeof(igDummy->igNum)); - fprintf(fout, "Offset / size of igOffs = %2zu / %2zu\n", offsetof(insGroup, igOffs), + fprintf(fout, "Offset / size of igOffs = %3zu / %2zu\n", offsetof(insGroup, igOffs), sizeof(igDummy->igOffs)); - fprintf(fout, "Offset / size of igFuncIdx = %2zu / %2zu\n", offsetof(insGroup, igFuncIdx), + fprintf(fout, "Offset / size of igFuncIdx = %3zu / %2zu\n", offsetof(insGroup, igFuncIdx), sizeof(igDummy->igFuncIdx)); - fprintf(fout, "Offset / size of igFlags = %2zu / %2zu\n", offsetof(insGroup, igFlags), + fprintf(fout, "Offset / size of igFlags = %3zu / %2zu\n", offsetof(insGroup, igFlags), sizeof(igDummy->igFlags)); - fprintf(fout, "Offset / size of igSize = %2zu / %2zu\n", offsetof(insGroup, igSize), + fprintf(fout, "Offset / size of igSize = %3zu / %2zu\n", offsetof(insGroup, igSize), sizeof(igDummy->igSize)); - fprintf(fout, "Offset / size of igData = %2zu / %2zu\n", offsetof(insGroup, igData), +#if FEATURE_LOOP_ALIGN + fprintf(fout, "Offset / size of igLoopBackEdge = %3zu / %2zu\n", offsetof(insGroup, igLoopBackEdge), + sizeof(igDummy->igLoopBackEdge)); +#endif // FEATURE_LOOP_ALIGN +#if !(REGMASK_BITS <= 32) + fprintf(fout, "Offset / size of igGCregs = %3zu / %2zu\n", offsetof(insGroup, igGCregs), + sizeof(igDummy->igGCregs)); +#endif // !(REGMASK_BITS <= 32) + fprintf(fout, "Offset / size of igData = %3zu / %2zu\n", offsetof(insGroup, igData), sizeof(igDummy->igData)); - fprintf(fout, "Offset / size of igPhData = %2zu / %2zu\n", offsetof(insGroup, igPhData), + fprintf(fout, "Offset / size of igPhData = %3zu / %2zu\n", offsetof(insGroup, igPhData), sizeof(igDummy->igPhData)); #if EMIT_BACKWARDS_NAVIGATION - fprintf(fout, "Offset / size of igLastIns = %2zu / %2zu\n", offsetof(insGroup, igLastIns), + fprintf(fout, "Offset / size of igLastIns = %3zu / %2zu\n", offsetof(insGroup, igLastIns), sizeof(igDummy->igLastIns)); #endif // EMIT_BACKWARDS_NAVIGATION #if EMIT_TRACK_STACK_DEPTH - fprintf(fout, "Offset / size of igStkLvl = %2zu / %2zu\n", offsetof(insGroup, igStkLvl), + fprintf(fout, "Offset / size of igStkLvl = %3zu / %2zu\n", offsetof(insGroup, igStkLvl), sizeof(igDummy->igStkLvl)); -#endif - fprintf(fout, "Offset / size of igGCregs = %2zu / %2zu\n", offsetof(insGroup, igGCregs), +#endif // EMIT_TRACK_STACK_DEPTH +#if REGMASK_BITS <= 32 + fprintf(fout, "Offset / size of igGCregs = %3zu / %2zu\n", offsetof(insGroup, igGCregs), sizeof(igDummy->igGCregs)); - fprintf(fout, "Offset / size of igInsCnt = %2zu / %2zu\n", offsetof(insGroup, igInsCnt), +#endif // REGMASK_BITS <= 32 + fprintf(fout, "Offset / size of igInsCnt = %3zu / %2zu\n", offsetof(insGroup, igInsCnt), sizeof(igDummy->igInsCnt)); fprintf(fout, "\n"); - fprintf(fout, "Size of insGroup = %zu\n", sizeof(insGroup)); + fprintf(fout, "Size of insGroup = %zu\n", sizeof(insGroup)); // insPlaceholderGroupData members + insPlaceholderGroupData* ipgdDummy = nullptr; + fprintf(fout, "\n"); fprintf(fout, "insPlaceholderGroupData:\n"); - fprintf(fout, "Offset of igPhNext = %2zu\n", offsetof(insPlaceholderGroupData, igPhNext)); - fprintf(fout, "Offset of igPhBB = %2zu\n", offsetof(insPlaceholderGroupData, igPhBB)); - fprintf(fout, "Offset of igPhInitGCrefVars = %2zu\n", offsetof(insPlaceholderGroupData, igPhInitGCrefVars)); - fprintf(fout, "Offset of igPhInitGCrefRegs = %2zu\n", offsetof(insPlaceholderGroupData, igPhInitGCrefRegs)); - fprintf(fout, "Offset of igPhInitByrefRegs = %2zu\n", offsetof(insPlaceholderGroupData, igPhInitByrefRegs)); - fprintf(fout, "Offset of igPhPrevGCrefVars = %2zu\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefVars)); - fprintf(fout, "Offset of igPhPrevGCrefRegs = %2zu\n", offsetof(insPlaceholderGroupData, igPhPrevGCrefRegs)); - fprintf(fout, "Offset of igPhPrevByrefRegs = %2zu\n", offsetof(insPlaceholderGroupData, igPhPrevByrefRegs)); - fprintf(fout, "Offset of igPhType = %2zu\n", offsetof(insPlaceholderGroupData, igPhType)); - fprintf(fout, "Size of insPlaceholderGroupData = %zu\n", sizeof(insPlaceholderGroupData)); + fprintf(fout, "Offset / size of igPhNext = %3zu / %2zu\n", offsetof(insPlaceholderGroupData, igPhNext), + sizeof(ipgdDummy->igPhNext)); + fprintf(fout, "Offset / size of igPhBB = %3zu / %2zu\n", offsetof(insPlaceholderGroupData, igPhBB), + sizeof(ipgdDummy->igPhBB)); + fprintf(fout, "Offset / size of igPhInitGCrefVars = %3zu / %2zu\n", + offsetof(insPlaceholderGroupData, igPhInitGCrefVars), sizeof(ipgdDummy->igPhInitGCrefVars)); + fprintf(fout, "Offset / size of igPhInitGCrefRegs = %3zu / %2zu\n", + offsetof(insPlaceholderGroupData, igPhInitGCrefRegs), sizeof(ipgdDummy->igPhInitGCrefRegs)); + fprintf(fout, "Offset / size of igPhInitByrefRegs = %3zu / %2zu\n", + offsetof(insPlaceholderGroupData, igPhInitByrefRegs), sizeof(ipgdDummy->igPhInitByrefRegs)); + fprintf(fout, "Offset / size of igPhPrevGCrefVars = %3zu / %2zu\n", + offsetof(insPlaceholderGroupData, igPhPrevGCrefVars), sizeof(ipgdDummy->igPhPrevGCrefVars)); + fprintf(fout, "Offset / size of igPhPrevGCrefRegs = %3zu / %2zu\n", + offsetof(insPlaceholderGroupData, igPhPrevGCrefRegs), sizeof(ipgdDummy->igPhPrevGCrefRegs)); + fprintf(fout, "Offset / size of igPhPrevByrefRegs = %3zu / %2zu\n", + offsetof(insPlaceholderGroupData, igPhPrevByrefRegs), sizeof(ipgdDummy->igPhPrevByrefRegs)); + fprintf(fout, "Offset / size of igPhType = %3zu / %2zu\n", offsetof(insPlaceholderGroupData, igPhType), + sizeof(ipgdDummy->igPhType)); + fprintf(fout, "\n"); + fprintf(fout, "Size of insPlaceholderGroupData = %zu\n", sizeof(insPlaceholderGroupData)); fprintf(fout, "\n"); - fprintf(fout, "SMALL_IDSC_SIZE = %2u\n", SMALL_IDSC_SIZE); - fprintf(fout, "Size of instrDesc = %2zu\n", sizeof(emitter::instrDesc)); - // fprintf(fout, "Offset of _idIns = %2zu\n", offsetof(emitter::instrDesc, _idIns )); - // fprintf(fout, "Offset of _idInsFmt = %2zu\n", offsetof(emitter::instrDesc, _idInsFmt )); - // fprintf(fout, "Offset of _idOpSize = %2zu\n", offsetof(emitter::instrDesc, _idOpSize )); - // fprintf(fout, "Offset of idSmallCns = %2zu\n", offsetof(emitter::instrDesc, idSmallCns )); - // fprintf(fout, "Offset of _idAddrUnion= %2zu\n", offsetof(emitter::instrDesc, _idAddrUnion)); - // fprintf(fout, "\n"); - // fprintf(fout, "Size of _idAddrUnion= %2zu\n", sizeof(((emitter::instrDesc*)0)->_idAddrUnion)); - - fprintf(fout, "Size of instrDescJmp = %2zu\n", sizeof(emitter::instrDescJmp)); + fprintf(fout, "SMALL_IDSC_SIZE = %2u\n", SMALL_IDSC_SIZE); + fprintf(fout, "Size of instrDesc = %2zu\n", sizeof(emitter::instrDesc)); + fprintf(fout, "Size of instrDescCns = %2zu\n", sizeof(emitter::instrDescCns)); + fprintf(fout, "Size of instrDescDsp = %2zu\n", sizeof(emitter::instrDescDsp)); +#ifdef TARGET_ARM64 + fprintf(fout, "Size of instrDescLclVarPair = %2zu\n", sizeof(emitter::instrDescLclVarPair)); + fprintf(fout, "Size of instrDescLclVarPairCns = %2zu\n", sizeof(emitter::instrDescLclVarPairCns)); +#endif // TARGET_ARM64 +#ifdef TARGET_ARM + fprintf(fout, "Size of instrDescReloc = %2zu\n", sizeof(emitter::instrDescReloc)); +#endif // TARGET_ARM +#ifdef TARGET_XARCH + fprintf(fout, "Size of instrDescAmd = %2zu\n", sizeof(emitter::instrDescAmd)); + fprintf(fout, "Size of instrDescCnsAmd = %2zu\n", sizeof(emitter::instrDescCnsAmd)); +#endif // TARGET_XARCH + fprintf(fout, "Size of instrDescCnsDsp = %2zu\n", sizeof(emitter::instrDescCnsDsp)); #if FEATURE_LOOP_ALIGN - fprintf(fout, "Size of instrDescAlign = %2zu\n", sizeof(emitter::instrDescAlign)); + fprintf(fout, "Size of instrDescAlign = %2zu\n", sizeof(emitter::instrDescAlign)); #endif // FEATURE_LOOP_ALIGN + fprintf(fout, "Size of instrDescJmp = %2zu\n", sizeof(emitter::instrDescJmp)); #if !defined(TARGET_ARM64) - fprintf(fout, "Size of instrDescLbl = %2zu\n", sizeof(emitter::instrDescLbl)); + fprintf(fout, "Size of instrDescLbl = %2zu\n", sizeof(emitter::instrDescLbl)); #endif // !defined(TARGET_ARM64) - fprintf(fout, "Size of instrDescCns = %2zu\n", sizeof(emitter::instrDescCns)); - fprintf(fout, "Size of instrDescDsp = %2zu\n", sizeof(emitter::instrDescDsp)); - fprintf(fout, "Size of instrDescCnsDsp = %2zu\n", sizeof(emitter::instrDescCnsDsp)); -#ifdef TARGET_XARCH - fprintf(fout, "Size of instrDescAmd = %2zu\n", sizeof(emitter::instrDescAmd)); - fprintf(fout, "Size of instrDescCnsAmd = %2zu\n", sizeof(emitter::instrDescCnsAmd)); -#endif // TARGET_XARCH - fprintf(fout, "Size of instrDescCGCA = %2zu\n", sizeof(emitter::instrDescCGCA)); -#ifdef TARGET_ARM - fprintf(fout, "Size of instrDescReloc = %2zu\n", sizeof(emitter::instrDescReloc)); -#endif // TARGET_ARM + fprintf(fout, "Size of instrDescCGCA = %2zu\n", sizeof(emitter::instrDescCGCA)); fprintf(fout, "\n"); - fprintf(fout, "igBuffSize = %2zu\n", igBuffSize); - fprintf(fout, "SMALL_IDSC_SIZE per IG buffer = %2zu\n", igBuffSize / SMALL_IDSC_SIZE); - fprintf(fout, "instrDesc per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDesc)); - fprintf(fout, "instrDescJmp per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescJmp)); -#if !defined(TARGET_ARM64) - fprintf(fout, "instrDescLbl per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescLbl)); -#endif // !defined(TARGET_ARM64) - fprintf(fout, "instrDescCns per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescCns)); - fprintf(fout, "instrDescDsp per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescDsp)); - fprintf(fout, "instrDescCnsDsp per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescCnsDsp)); -#ifdef TARGET_XARCH - fprintf(fout, "instrDescAmd per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescAmd)); - fprintf(fout, "instrDescCnsAmd per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescCnsAmd)); -#endif // TARGET_XARCH - fprintf(fout, "instrDescCGCA per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescCGCA)); + fprintf(fout, "igBuffSize = %2zu\n", igBuffSize); + fprintf(fout, "SMALL_IDSC_SIZE per IG buffer = %2zu\n", igBuffSize / SMALL_IDSC_SIZE); + fprintf(fout, "instrDesc per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDesc)); + fprintf(fout, "instrDescCns per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescCns)); + fprintf(fout, "instrDescDsp per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescDsp)); +#ifdef TARGET_ARM64 + fprintf(fout, "instrDescLclVarPair per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescLclVarPair)); + fprintf(fout, "instrDescLclVarPairCns per IG buffer = %2zu\n", + igBuffSize / sizeof(emitter::instrDescLclVarPairCns)); +#endif // TARGET_ARM64 #ifdef TARGET_ARM - fprintf(fout, "instrDescReloc per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescReloc)); + fprintf(fout, "instrDescReloc per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescReloc)); #endif // TARGET_ARM +#ifdef TARGET_XARCH + fprintf(fout, "instrDescAmd per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescAmd)); + fprintf(fout, "instrDescCnsAmd per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescCnsAmd)); +#endif // TARGET_XARCH + fprintf(fout, "instrDescCnsDsp per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescCnsDsp)); +#if FEATURE_LOOP_ALIGN + fprintf(fout, "instrDescAlign per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescAlign)); +#endif // FEATURE_LOOP_ALIGN + fprintf(fout, "instrDescJmp per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescJmp)); +#if !defined(TARGET_ARM64) + fprintf(fout, "instrDescLbl per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescLbl)); +#endif // !defined(TARGET_ARM64) + fprintf(fout, "instrDescCGCA per IG buffer = %2zu\n", igBuffSize / sizeof(emitter::instrDescCGCA)); fprintf(fout, "\n"); fprintf(fout, "GCInfo::regPtrDsc:\n"); fprintf(fout, "Offset of rpdNext = %2zu\n", offsetof(GCInfo::regPtrDsc, rpdNext)); fprintf(fout, "Offset of rpdOffs = %2zu\n", offsetof(GCInfo::regPtrDsc, rpdOffs)); fprintf(fout, "Offset of = %2zu\n", offsetof(GCInfo::regPtrDsc, rpdPtrArg)); - fprintf(fout, "Size of GCInfo::regPtrDsc = %2zu\n", sizeof(GCInfo::regPtrDsc)); + fprintf(fout, "Size of GCInfo::regPtrDsc = %2zu\n", sizeof(GCInfo::regPtrDsc)); fprintf(fout, "\n"); } @@ -420,37 +470,45 @@ void emitterStats(FILE* fout) fprintf(fout, "A total of %8zu desc. bytes\n", emitter::emitTotalIGsize); fprintf(fout, "\n"); - fprintf(fout, "Total instructions: %8u\n", emitter::emitTotalInsCnt); - fprintf(fout, "Total small instrDesc: %8u (%5.2f%%)\n", emitter::emitTotalIDescSmallCnt, + fprintf(fout, "Total instructions: %8u\n", emitter::emitTotalInsCnt); + fprintf(fout, "Total small instrDesc: %8u (%5.2f%%)\n", emitter::emitTotalIDescSmallCnt, 100.0 * emitter::emitTotalIDescSmallCnt / emitter::emitTotalInsCnt); - fprintf(fout, "Total instrDesc: %8u (%5.2f%%)\n", emitter::emitTotalIDescCnt, + fprintf(fout, "Total instrDesc: %8u (%5.2f%%)\n", emitter::emitTotalIDescCnt, 100.0 * emitter::emitTotalIDescCnt / emitter::emitTotalInsCnt); - fprintf(fout, "Total instrDescJmp: %8u (%5.2f%%)\n", emitter::emitTotalIDescJmpCnt, - 100.0 * emitter::emitTotalIDescJmpCnt / emitter::emitTotalInsCnt); -#if !defined(TARGET_ARM64) - fprintf(fout, "Total instrDescLbl: %8u (%5.2f%%)\n", emitter::emitTotalIDescLblCnt, - 100.0 * emitter::emitTotalIDescLblCnt / emitter::emitTotalInsCnt); -#endif // !defined(TARGET_ARM64) - fprintf(fout, "Total instrDescCns: %8u (%5.2f%%)\n", emitter::emitTotalIDescCnsCnt, + fprintf(fout, "Total instrDescCns: %8u (%5.2f%%)\n", emitter::emitTotalIDescCnsCnt, 100.0 * emitter::emitTotalIDescCnsCnt / emitter::emitTotalInsCnt); - fprintf(fout, "Total instrDescDsp: %8u (%5.2f%%)\n", emitter::emitTotalIDescDspCnt, + fprintf(fout, "Total instrDescDsp: %8u (%5.2f%%)\n", emitter::emitTotalIDescDspCnt, 100.0 * emitter::emitTotalIDescDspCnt / emitter::emitTotalInsCnt); - fprintf(fout, "Total instrDescCnsDsp: %8u (%5.2f%%)\n", emitter::emitTotalIDescCnsDspCnt, - 100.0 * emitter::emitTotalIDescCnsDspCnt / emitter::emitTotalInsCnt); +#ifdef TARGET_ARM64 + fprintf(fout, "Total instrDescLclVarPair: %8u (%5.2f%%)\n", emitter::emitTotalIDescLclVarPairCnt, + 100.0 * emitter::emitTotalIDescLclVarPairCnt / emitter::emitTotalInsCnt); + fprintf(fout, "Total instrDescLclVarPairCns: %8u (%5.2f%%)\n", emitter::emitTotalIDescLclVarPairCnsCnt, + 100.0 * emitter::emitTotalIDescLclVarPairCnsCnt / emitter::emitTotalInsCnt); +#endif // TARGET_ARM64 +#ifdef TARGET_ARM + fprintf(fout, "Total instrDescReloc: %8u (%5.2f%%)\n", emitter::emitTotalIDescRelocCnt, + 100.0 * emitter::emitTotalIDescRelocCnt / emitter::emitTotalInsCnt); +#endif // TARGET_ARM #ifdef TARGET_XARCH - fprintf(fout, "Total instrDescAmd: %8u (%5.2f%%)\n", emitter::emitTotalIDescAmdCnt, + fprintf(fout, "Total instrDescAmd: %8u (%5.2f%%)\n", emitter::emitTotalIDescAmdCnt, 100.0 * emitter::emitTotalIDescAmdCnt / emitter::emitTotalInsCnt); - fprintf(fout, "Total instrDescCnsAmd: %8u (%5.2f%%)\n", emitter::emitTotalIDescCnsAmdCnt, + fprintf(fout, "Total instrDescCnsAmd: %8u (%5.2f%%)\n", emitter::emitTotalIDescCnsAmdCnt, 100.0 * emitter::emitTotalIDescCnsAmdCnt / emitter::emitTotalInsCnt); #endif // TARGET_XARCH - fprintf(fout, "Total instrDescCGCA: %8u (%5.2f%%)\n", emitter::emitTotalIDescCGCACnt, + fprintf(fout, "Total instrDescCnsDsp: %8u (%5.2f%%)\n", emitter::emitTotalIDescCnsDspCnt, + 100.0 * emitter::emitTotalIDescCnsDspCnt / emitter::emitTotalInsCnt); +#if FEATURE_LOOP_ALIGN + fprintf(fout, "Total instrDescAlign: %8u (%5.2f%%)\n", emitter::emitTotalIDescAlignCnt, + 100.0 * emitter::emitTotalIDescAlignCnt / emitter::emitTotalInsCnt); +#endif // FEATURE_LOOP_ALIGN + fprintf(fout, "Total instrDescJmp: %8u (%5.2f%%)\n", emitter::emitTotalIDescJmpCnt, + 100.0 * emitter::emitTotalIDescJmpCnt / emitter::emitTotalInsCnt); +#if !defined(TARGET_ARM64) + fprintf(fout, "Total instrDescLbl: %8u (%5.2f%%)\n", emitter::emitTotalIDescLblCnt, + 100.0 * emitter::emitTotalIDescLblCnt / emitter::emitTotalInsCnt); +#endif // !defined(TARGET_ARM64) + fprintf(fout, "Total instrDescCGCA: %8u (%5.2f%%)\n", emitter::emitTotalIDescCGCACnt, 100.0 * emitter::emitTotalIDescCGCACnt / emitter::emitTotalInsCnt); -#ifdef TARGET_ARM - fprintf(fout, "Total instrDescReloc: %8u (%5.2f%%)\n", emitter::emitTotalIDescRelocCnt, - 100.0 * emitter::emitTotalIDescRelocCnt / emitter::emitTotalInsCnt); -#endif // TARGET_ARM - fprintf(fout, "Total instrDescAlign: %8u (%5.2f%%)\n", emitter::emitTotalDescAlignCnt, - 100.0 * emitter::emitTotalDescAlignCnt / emitter::emitTotalInsCnt); fprintf(fout, "\n"); } @@ -467,33 +525,58 @@ void emitterStats(FILE* fout) stkDepthTable.dump(fout); fprintf(fout, "\n"); - if ((emitter::emitSmallCnsCnt > 0) || (emitter::emitLargeCnsCnt > 0)) + unsigned emitTotalCnsCnt = emitter::emitLargeCnsCnt + emitter::emitSmallCnsCnt; + + if (emitTotalCnsCnt != 0) { - fprintf(fout, "SmallCnsCnt = %6u\n", emitter::emitSmallCnsCnt); - fprintf(fout, "LargeCnsCnt = %6u (%3u %% of total)\n", emitter::emitLargeCnsCnt, - 100 * emitter::emitLargeCnsCnt / (emitter::emitLargeCnsCnt + emitter::emitSmallCnsCnt)); + fprintf(fout, "SmallCnsCnt = %8u (%5.2f%%)\n", emitter::emitSmallCnsCnt, + (100.0 * emitter::emitSmallCnsCnt) / emitTotalCnsCnt); + fprintf(fout, "LargeCnsCnt = %8u (%5.2f%%)\n", emitter::emitLargeCnsCnt, + (100.0 * emitter::emitLargeCnsCnt) / emitTotalCnsCnt); + fprintf(fout, "Int8CnsCnt = %8u (%5.2f%%)\n", emitter::emitInt8CnsCnt, + (100.0 * emitter::emitInt8CnsCnt) / emitTotalCnsCnt); + fprintf(fout, "Int16CnsCnt = %8u (%5.2f%%)\n", emitter::emitInt16CnsCnt, + (100.0 * emitter::emitInt16CnsCnt) / emitTotalCnsCnt); + fprintf(fout, "Int32CnsCnt = %8u (%5.2f%%)\n", emitter::emitInt32CnsCnt, + (100.0 * emitter::emitInt32CnsCnt) / emitTotalCnsCnt); + fprintf(fout, "NegCnsCnt = %8u (%5.2f%%)\n", emitter::emitNegCnsCnt, + (100.0 * emitter::emitNegCnsCnt) / emitTotalCnsCnt); + fprintf(fout, "Pow2CnsCnt = %8u (%5.2f%%)\n", emitter::emitPow2CnsCnt, + (100.0 * emitter::emitPow2CnsCnt) / emitTotalCnsCnt); } // Print out the most common small constants. - if (emitter::emitSmallCnsCnt > 0) + if (emitter::emitSmallCnsCnt != 0) { fprintf(fout, "\n\n"); - fprintf(fout, "Common small constants >= %2u, <= %2u\n", ID_MIN_SMALL_CNS, ID_MAX_SMALL_CNS); + fprintf(fout, "Common small constants >= %2d, <= %2d\n", ID_MIN_SMALL_CNS, ID_MAX_SMALL_CNS); - unsigned m = emitter::emitSmallCnsCnt / 1000 + 1; + // Only print constants representing more than 0.1% of the total constants + unsigned m = (emitter::emitSmallCnsCnt / 1000) + 1; - for (int i = ID_MIN_SMALL_CNS; (i <= ID_MAX_SMALL_CNS) && (i < SMALL_CNS_TSZ); i++) + for (int i = 0; (i <= ID_CNT_SMALL_CNS) && (i < SMALL_CNS_TSZ); i++) { - unsigned c = emitter::emitSmallCns[i - ID_MIN_SMALL_CNS]; + unsigned c = emitter::emitSmallCns[i]; + if (c >= m) { - if (i == SMALL_CNS_TSZ - 1) + // We make an assumption that MIN is negative and MAX is positive + assert((ID_MIN_SMALL_CNS < 0) && (ID_MAX_SMALL_CNS > 0)); + + // Adjust the index to match the allowed value range + int v = i - (SMALL_CNS_TSZ / 2); + + if (i == 0) + { + fprintf(fout, "cns[<=%4d] = %8u (%5.2f%%)\n", v, c, (100.0 * c) / emitTotalCnsCnt); + } + else if (i == (SMALL_CNS_TSZ - 1)) { - fprintf(fout, "cns[>=%4d] = %u\n", i, c); + fprintf(fout, "cns[>=%4d] = %8u (%5.2f%%)\n", v, c, (100.0 * c) / emitTotalCnsCnt); } else { - fprintf(fout, "cns[%4d] = %u\n", i, c); + fprintf(fout, "cns[ %4d] = %8u (%5.2f%%)\n", v, c, (100.0 * c) / emitTotalCnsCnt); } } } @@ -2642,11 +2725,7 @@ emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, target_ssize_t cn id->idSmallCns(cns); #if EMITTER_STATS - emitSmallCnsCnt++; - if ((cns - ID_MIN_SMALL_CNS) >= (SMALL_CNS_TSZ - 1)) - emitSmallCns[SMALL_CNS_TSZ - 1]++; - else - emitSmallCns[cns - ID_MIN_SMALL_CNS]++; + TrackSmallCns(cns); emitSmallDspCnt++; #endif @@ -2657,7 +2736,7 @@ emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, target_ssize_t cn instrDescCns* id = emitAllocInstrCns(size, cns); #if EMITTER_STATS - emitLargeCnsCnt++; + TrackLargeCns(cns); emitSmallDspCnt++; #endif @@ -2676,12 +2755,8 @@ emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, target_ssize_t cn id->idSmallCns(cns); #if EMITTER_STATS + TrackSmallCns(cns); emitLargeDspCnt++; - emitSmallCnsCnt++; - if ((cns - ID_MIN_SMALL_CNS) >= (SMALL_CNS_TSZ - 1)) - emitSmallCns[SMALL_CNS_TSZ - 1]++; - else - emitSmallCns[cns - ID_MIN_SMALL_CNS]++; #endif return id; @@ -2697,8 +2772,8 @@ emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, target_ssize_t cn id->iddcDspVal = dsp; #if EMITTER_STATS + TrackLargeCns(cns); emitLargeDspCnt++; - emitLargeCnsCnt++; #endif return id; diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 9cab8e6fcea2ff..0602a67784370a 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -323,7 +323,10 @@ struct insGroup // Try to do better packing based on how large regMaskSmall is (8, 16, or 64 bits). CLANG_FORMAT_COMMENT_ANCHOR; -#if REGMASK_BITS <= 32 + +#if !(REGMASK_BITS <= 32) + regMaskSmall igGCregs; // set of registers with live GC refs +#endif // !(REGMASK_BITS <= 32) union { BYTE* igData; // addr of instruction descriptors @@ -334,37 +337,18 @@ struct insGroup // Last instruction in group, if any (nullptr if none); used for backwards navigation. // (Should be type emitter::instrDesc*). void* igLastIns; -#endif +#endif // EMIT_BACKWARDS_NAVIGATION #if EMIT_TRACK_STACK_DEPTH unsigned igStkLvl; // stack level on entry -#endif - regMaskSmall igGCregs; // set of registers with live GC refs - unsigned char igInsCnt; // # of instructions in this group - -#else // REGMASK_BITS +#endif // EMIT_TRACK_STACK_DEPTH +#if REGMASK_BITS <= 32 regMaskSmall igGCregs; // set of registers with live GC refs - - union { - BYTE* igData; // addr of instruction descriptors - insPlaceholderGroupData* igPhData; // when igFlags & IGF_PLACEHOLDER - }; - -#if EMIT_BACKWARDS_NAVIGATION - // Last instruction in group, if any (nullptr if none); used for backwards navigation. - // (Should be type emitter::instrDesc*). - void* igLastIns; -#endif - -#if EMIT_TRACK_STACK_DEPTH - unsigned igStkLvl; // stack level on entry -#endif +#endif // REGMASK_BITS <= 32 unsigned char igInsCnt; // # of instructions in this group -#endif // REGMASK_BITS - VARSET_VALRET_TP igGCvars() const { assert(igFlags & IGF_GC_VARS); @@ -725,11 +709,12 @@ class emitter //////////////////////////////////////////////////////////////////////// // Space taken up to here: - // x86: 17 bits - // amd64: 17 bits - // arm: 16 bits - // arm64: 17 bits + // x86: 17 bits + // amd64: 17 bits + // arm: 16 bits + // arm64: 17 bits // loongarch64: 14 bits + // risc-v: 14 bits private: #if defined(TARGET_XARCH) @@ -766,11 +751,12 @@ class emitter //////////////////////////////////////////////////////////////////////// // Space taken up to here: - // x86: 38 bits - // amd64: 38 bits - // arm: 32 bits - // arm64: 31 bits + // x86: 38 bits + // amd64: 38 bits + // arm: 32 bits + // arm64: 31 bits // loongarch64: 28 bits + // risc-v: 28 bits unsigned _idSmallDsc : 1; // is this a "small" descriptor? unsigned _idLargeCns : 1; // does a large constant follow? @@ -817,11 +803,12 @@ class emitter //////////////////////////////////////////////////////////////////////// // Space taken up to here: - // x86: 47 bits - // amd64: 47 bits - // arm: 48 bits - // arm64: 50 bits + // x86: 47 bits + // amd64: 47 bits + // arm: 48 bits + // arm64: 50 bits // loongarch64: 46 bits + // risc-v: 46 bits // // How many bits have been used beyond the first 32? @@ -871,11 +858,12 @@ class emitter //////////////////////////////////////////////////////////////////////// // Space taken up to here (with/without prev offset, assuming host==target): - // x86: 53/49 bits - // amd64: 54/49 bits - // arm: 54/50 bits - // arm64: 57/52 bits + // x86: 53/49 bits + // amd64: 54/49 bits + // arm: 54/50 bits + // arm64: 57/52 bits // loongarch64: 53/48 bits + // risc-v: 53/48 bits CLANG_FORMAT_COMMENT_ANCHOR; #define ID_EXTRA_BITS (ID_EXTRA_RELOC_BITS + ID_EXTRA_BITFIELD_BITS + ID_EXTRA_PREV_OFFSET_BITS) @@ -884,18 +872,26 @@ class emitter #define ID_BIT_SMALL_CNS (32 - ID_EXTRA_BITS) C_ASSERT(ID_BIT_SMALL_CNS > 0); -#define ID_MIN_SMALL_CNS 0 -#define ID_MAX_SMALL_CNS (int)((1 << ID_BIT_SMALL_CNS) - 1U) //////////////////////////////////////////////////////////////////////// // Small constant size (with/without prev offset, assuming host==target): - // x86: 12/16 bits - // amd64: 11/16 bits - // arm: 10/14 bits - // arm64: 7/12 bits + // x86: 11/15 bits + // amd64: 10/15 bits + // arm: 10/14 bits + // arm64: 7/12 bits // loongarch64: 11/16 bits + // risc-v: 11/16 bits + CLANG_FORMAT_COMMENT_ANCHOR; + +#define ID_ADJ_SMALL_CNS (int)(1 << (ID_BIT_SMALL_CNS - 1)) +#define ID_CNT_SMALL_CNS (int)(1 << ID_BIT_SMALL_CNS) - unsigned _idSmallCns : ID_BIT_SMALL_CNS; +#define ID_MIN_SMALL_CNS (int)(0 - ID_ADJ_SMALL_CNS) +#define ID_MAX_SMALL_CNS (int)(ID_CNT_SMALL_CNS - ID_ADJ_SMALL_CNS - 1) + + // We encounter many constants, but there is a disproportionate amount that are in the range [-1, +4] + // and otherwise powers of 2. We therefore allow the tracked range here to include negative values. + signed _idSmallCns : ID_BIT_SMALL_CNS; //////////////////////////////////////////////////////////////////////// // Space taken up to here: 64 bits, all architectures, by design. @@ -1468,7 +1464,7 @@ class emitter #endif // TARGET_RISCV64 - inline static bool fitsInSmallCns(ssize_t val) + inline static bool fitsInSmallCns(cnsval_ssize_t val) { return ((val >= ID_MIN_SMALL_CNS) && (val <= ID_MAX_SMALL_CNS)); } @@ -1646,14 +1642,15 @@ class emitter #endif // EMIT_BACKWARDS_NAVIGATION - unsigned idSmallCns() const + signed idSmallCns() const { return _idSmallCns; } - void idSmallCns(size_t value) + void idSmallCns(cnsval_ssize_t value) { assert(fitsInSmallCns(value)); _idSmallCns = value; + assert(value == idSmallCns()); } inline const idAddrUnion* idAddr() const @@ -2757,6 +2754,9 @@ class emitter #if defined(TARGET_ARM64) instrDescLclVarPair* emitAllocInstrLclVarPair(emitAttr attr) { +#if EMITTER_STATS + emitTotalIDescLclVarPairCnt++; +#endif // EMITTER_STATS instrDescLclVarPair* result = (instrDescLclVarPair*)emitAllocAnyInstr(sizeof(instrDescLclVarPair), attr); result->idSetIsLclVarPair(); return result; @@ -2764,6 +2764,9 @@ class emitter instrDescLclVarPairCns* emitAllocInstrLclVarPairCns(emitAttr attr, cnsval_size_t cns) { +#if EMITTER_STATS + emitTotalIDescLclVarPairCnsCnt++; +#endif // EMITTER_STATS instrDescLclVarPairCns* result = (instrDescLclVarPairCns*)emitAllocAnyInstr(sizeof(instrDescLclVarPairCns), attr); result->idSetIsLargeCns(); @@ -2837,7 +2840,7 @@ class emitter instrDescAlign* emitAllocInstrAlign() { #if EMITTER_STATS - emitTotalDescAlignCnt++; + emitTotalIDescAlignCnt++; #endif // EMITTER_STATS return (instrDescAlign*)emitAllocAnyInstr(sizeof(instrDescAlign), EA_1BYTE); } @@ -3178,35 +3181,114 @@ class emitter static unsigned emitTotalIDescSmallCnt; static unsigned emitTotalIDescCnt; - static unsigned emitTotalIDescJmpCnt; -#if !defined(TARGET_ARM64) - static unsigned emitTotalIDescLblCnt; -#endif // !defined(TARGET_ARM64) static unsigned emitTotalIDescCnsCnt; static unsigned emitTotalIDescDspCnt; - static unsigned emitTotalIDescCnsDspCnt; +#ifdef TARGET_ARM64 + static unsigned emitTotalIDescLclVarPairCnt; + static unsigned emitTotalIDescLclVarPairCnsCnt; +#endif // TARGET_ARM64 +#ifdef TARGET_ARM + static unsigned emitTotalIDescRelocCnt; +#endif // TARGET_ARM #ifdef TARGET_XARCH static unsigned emitTotalIDescAmdCnt; static unsigned emitTotalIDescCnsAmdCnt; #endif // TARGET_XARCH + static unsigned emitTotalIDescCnsDspCnt; +#if FEATURE_LOOP_ALIGN + static unsigned emitTotalIDescAlignCnt; +#endif // FEATURE_LOOP_ALIGN + static unsigned emitTotalIDescJmpCnt; +#if !defined(TARGET_ARM64) + static unsigned emitTotalIDescLblCnt; +#endif // !defined(TARGET_ARM64) static unsigned emitTotalIDescCGCACnt; -#ifdef TARGET_ARM - static unsigned emitTotalIDescRelocCnt; -#endif // TARGET_ARM static size_t emitTotMemAlloc; static unsigned emitSmallDspCnt; static unsigned emitLargeDspCnt; - static unsigned emitSmallCnsCnt; #define SMALL_CNS_TSZ 256 static unsigned emitSmallCns[SMALL_CNS_TSZ]; + static unsigned emitSmallCnsCnt; static unsigned emitLargeCnsCnt; - static unsigned emitTotalDescAlignCnt; + static unsigned emitInt8CnsCnt; + static unsigned emitInt16CnsCnt; + static unsigned emitInt32CnsCnt; + static unsigned emitNegCnsCnt; + static unsigned emitPow2CnsCnt; static unsigned emitIFcounts[IF_COUNT]; + void TrackCns(cnsval_ssize_t value) + { + if (value < 0) + { + emitNegCnsCnt++; + + if (value >= INT8_MIN) + { + emitInt8CnsCnt++; + } + else if (value >= INT16_MIN) + { + emitInt16CnsCnt++; + } + else if (value >= INT32_MIN) + { + emitInt32CnsCnt++; + } + } + else if (value <= INT8_MAX) + { + emitInt8CnsCnt++; + } + else if (value <= INT16_MAX) + { + emitInt16CnsCnt++; + } + else if (value <= INT32_MAX) + { + emitInt32CnsCnt++; + } + + if (isPow2(value)) + { + emitPow2CnsCnt++; + } + } + + void TrackSmallCns(cnsval_ssize_t value) + { + // We only track a subset of the allowed small constants and + // so we'll split the tracked range between positive/negative + // aggregating those outside the tracked range into the min/max + // instead. + + assert(fitsInSmallCns(value)); + uint32_t index = 0; + + if (value >= ((SMALL_CNS_TSZ / 2) - 1)) + { + index = static_cast(SMALL_CNS_TSZ - 1); + } + else if (value >= (0 - SMALL_CNS_TSZ / 2)) + { + index = static_cast(value + (SMALL_CNS_TSZ / 2)); + } + + emitSmallCnsCnt++; + emitSmallCns[index]++; + + TrackCns(value); + } + + void TrackLargeCns(cnsval_ssize_t value) + { + emitLargeCnsCnt++; + TrackCns(value); + } #endif // EMITTER_STATS /************************************************************************* @@ -3434,21 +3516,21 @@ inline emitter::instrDesc* emitter::emitNewInstrLclVarPair(emitAttr attr, cnsval { instrDescLclVarPair* id = emitAllocInstrLclVarPair(attr); id->idSmallCns(cns); + #if EMITTER_STATS - emitSmallCnsCnt++; - if ((cns - ID_MIN_SMALL_CNS) >= (SMALL_CNS_TSZ - 1)) - emitSmallCns[SMALL_CNS_TSZ - 1]++; - else - emitSmallCns[cns - ID_MIN_SMALL_CNS]++; + TrackSmallCns(cns); #endif + return id; } else { instrDescLclVarPairCns* id = emitAllocInstrLclVarPairCns(attr, cns); + #if EMITTER_STATS - emitLargeCnsCnt++; + TrackLargeCns(cns); #endif + return id; } } @@ -3497,11 +3579,7 @@ inline emitter::instrDesc* emitter::emitNewInstrCns(emitAttr attr, cnsval_ssize_ id->idSmallCns(cns); #if EMITTER_STATS - emitSmallCnsCnt++; - if ((cns - ID_MIN_SMALL_CNS) >= (SMALL_CNS_TSZ - 1)) - emitSmallCns[SMALL_CNS_TSZ - 1]++; - else - emitSmallCns[cns - ID_MIN_SMALL_CNS]++; + TrackSmallCns(cns); #endif return id; @@ -3511,7 +3589,7 @@ inline emitter::instrDesc* emitter::emitNewInstrCns(emitAttr attr, cnsval_ssize_ instrDescCns* id = emitAllocInstrCns(attr, cns); #if EMITTER_STATS - emitLargeCnsCnt++; + TrackLargeCns(cns); #endif return id; @@ -3569,11 +3647,7 @@ inline emitter::instrDesc* emitter::emitNewInstrSC(emitAttr attr, cnsval_ssize_t id->idSmallCns(cns); #if EMITTER_STATS - emitSmallCnsCnt++; - if ((cns - ID_MIN_SMALL_CNS) >= (SMALL_CNS_TSZ - 1)) - emitSmallCns[SMALL_CNS_TSZ - 1]++; - else - emitSmallCns[cns - ID_MIN_SMALL_CNS]++; + TrackSmallCns(cns); #endif return id; @@ -3583,7 +3657,7 @@ inline emitter::instrDesc* emitter::emitNewInstrSC(emitAttr attr, cnsval_ssize_t instrDescCns* id = emitAllocInstrCns(attr, cns); #if EMITTER_STATS - emitLargeCnsCnt++; + TrackLargeCns(cns); #endif return id;