From db98a132c216cf561b74a3cb86980e3f22d80852 Mon Sep 17 00:00:00 2001 From: Bruce Forstall Date: Mon, 18 Mar 2019 14:53:52 -0700 Subject: [PATCH] Update emitter statistics 1. Move BasicBlock static statistics output to block.cpp, and update it to match the current BasicBlock declaration. 2. Add counts for each instrDesc type that is used. 3. Dump instrDesc type sizes. 4. Dump IG "static" buffer sizes. 5. Dump how many of each instrDesc can fit in the "static" IG. 6. Dump the maximum prolog instrDesc count and prolog IG size. 7. Fix and enable the "common small constants" output. --- src/jit/block.cpp | 140 +++++++++++++++++++++++++++++++ src/jit/block.h | 2 + src/jit/compiler.cpp | 106 +----------------------- src/jit/emit.cpp | 225 +++++++++++++++++++++++++++++++++++++++++--------- src/jit/emit.h | 142 +++++++++++++++++++++++-------- src/jit/emitarm.cpp | 4 +- src/jit/emitarm64.cpp | 2 +- src/jit/emitxarch.cpp | 28 ++----- 8 files changed, 440 insertions(+), 209 deletions(-) diff --git a/src/jit/block.cpp b/src/jit/block.cpp index 9598366..8d1a83f 100644 --- a/src/jit/block.cpp +++ b/src/jit/block.cpp @@ -1357,3 +1357,143 @@ BasicBlock* Compiler::bbNewBasicBlock(BBjumpKinds jumpKind) return block; } + +//------------------------------------------------------------------------------ +// DisplayStaticSizes: display various static sizes of the BasicBlock data structure. +// +// Arguments: +// fout - where to write the output +// +// Return Value: +// None +// +// Note: This function only does something if MEASURE_BLOCK_SIZE is defined, which it might +// be in private Release builds. +// +/* static */ +void BasicBlock::DisplayStaticSizes(FILE* fout) +{ +#if MEASURE_BLOCK_SIZE + + BasicBlock* bbDummy = nullptr; + + fprintf(fout, "\n"); + fprintf(fout, "Offset / size of bbNext = %3u / %3u\n", offsetof(BasicBlock, bbNext), + sizeof(bbDummy->bbNext)); + fprintf(fout, "Offset / size of bbPrev = %3u / %3u\n", offsetof(BasicBlock, bbPrev), + sizeof(bbDummy->bbPrev)); + fprintf(fout, "Offset / size of bbFlags = %3u / %3u\n", offsetof(BasicBlock, bbFlags), + sizeof(bbDummy->bbFlags)); + fprintf(fout, "Offset / size of bbNum = %3u / %3u\n", offsetof(BasicBlock, bbNum), + sizeof(bbDummy->bbNum)); + fprintf(fout, "Offset / size of bbPostOrderNum = %3u / %3u\n", offsetof(BasicBlock, bbPostOrderNum), + sizeof(bbDummy->bbPostOrderNum)); + fprintf(fout, "Offset / size of bbRefs = %3u / %3u\n", offsetof(BasicBlock, bbRefs), + sizeof(bbDummy->bbRefs)); + fprintf(fout, "Offset / size of bbWeight = %3u / %3u\n", offsetof(BasicBlock, bbWeight), + sizeof(bbDummy->bbWeight)); + fprintf(fout, "Offset / size of bbJumpKind = %3u / %3u\n", offsetof(BasicBlock, bbJumpKind), + sizeof(bbDummy->bbJumpKind)); + fprintf(fout, "Offset / size of bbJumpOffs = %3u / %3u\n", offsetof(BasicBlock, bbJumpOffs), + sizeof(bbDummy->bbJumpOffs)); + fprintf(fout, "Offset / size of bbJumpDest = %3u / %3u\n", offsetof(BasicBlock, bbJumpDest), + sizeof(bbDummy->bbJumpDest)); + fprintf(fout, "Offset / size of bbJumpSwt = %3u / %3u\n", offsetof(BasicBlock, bbJumpSwt), + sizeof(bbDummy->bbJumpSwt)); + fprintf(fout, "Offset / size of bbEntryState = %3u / %3u\n", offsetof(BasicBlock, bbEntryState), + sizeof(bbDummy->bbEntryState)); + fprintf(fout, "Offset / size of bbStkTempsIn = %3u / %3u\n", offsetof(BasicBlock, bbStkTempsIn), + sizeof(bbDummy->bbStkTempsIn)); + fprintf(fout, "Offset / size of bbStkTempsOut = %3u / %3u\n", offsetof(BasicBlock, bbStkTempsOut), + sizeof(bbDummy->bbStkTempsOut)); + fprintf(fout, "Offset / size of bbTryIndex = %3u / %3u\n", offsetof(BasicBlock, bbTryIndex), + sizeof(bbDummy->bbTryIndex)); + fprintf(fout, "Offset / size of bbHndIndex = %3u / %3u\n", offsetof(BasicBlock, bbHndIndex), + sizeof(bbDummy->bbHndIndex)); + fprintf(fout, "Offset / size of bbCatchTyp = %3u / %3u\n", offsetof(BasicBlock, bbCatchTyp), + sizeof(bbDummy->bbCatchTyp)); + fprintf(fout, "Offset / size of bbStkDepth = %3u / %3u\n", offsetof(BasicBlock, bbStkDepth), + sizeof(bbDummy->bbStkDepth)); + fprintf(fout, "Offset / size of bbFPinVars = %3u / %3u\n", offsetof(BasicBlock, bbFPinVars), + sizeof(bbDummy->bbFPinVars)); + fprintf(fout, "Offset / size of bbCheapPreds = %3u / %3u\n", offsetof(BasicBlock, bbCheapPreds), + sizeof(bbDummy->bbCheapPreds)); + fprintf(fout, "Offset / size of bbPreds = %3u / %3u\n", offsetof(BasicBlock, bbPreds), + sizeof(bbDummy->bbPreds)); + fprintf(fout, "Offset / size of bbReach = %3u / %3u\n", offsetof(BasicBlock, bbReach), + sizeof(bbDummy->bbReach)); + fprintf(fout, "Offset / size of bbIDom = %3u / %3u\n", offsetof(BasicBlock, bbIDom), + sizeof(bbDummy->bbIDom)); + fprintf(fout, "Offset / size of bbDfsNum = %3u / %3u\n", offsetof(BasicBlock, bbDfsNum), + sizeof(bbDummy->bbDfsNum)); + fprintf(fout, "Offset / size of bbCodeOffs = %3u / %3u\n", offsetof(BasicBlock, bbCodeOffs), + sizeof(bbDummy->bbCodeOffs)); + fprintf(fout, "Offset / size of bbCodeOffsEnd = %3u / %3u\n", offsetof(BasicBlock, bbCodeOffsEnd), + sizeof(bbDummy->bbCodeOffsEnd)); + fprintf(fout, "Offset / size of bbVarUse = %3u / %3u\n", offsetof(BasicBlock, bbVarUse), + sizeof(bbDummy->bbVarUse)); + fprintf(fout, "Offset / size of bbVarDef = %3u / %3u\n", offsetof(BasicBlock, bbVarDef), + sizeof(bbDummy->bbVarDef)); + fprintf(fout, "Offset / size of bbLiveIn = %3u / %3u\n", offsetof(BasicBlock, bbLiveIn), + sizeof(bbDummy->bbLiveIn)); + fprintf(fout, "Offset / size of bbLiveOut = %3u / %3u\n", offsetof(BasicBlock, bbLiveOut), + sizeof(bbDummy->bbLiveOut)); + // Can't do bitfield bbMemoryUse, bbMemoryDef, bbMemoryLiveIn, bbMemoryLiveOut, bbMemoryHavoc + fprintf(fout, "Offset / size of bbMemorySsaPhiFunc = %3u / %3u\n", offsetof(BasicBlock, bbMemorySsaPhiFunc), + sizeof(bbDummy->bbMemorySsaPhiFunc)); + fprintf(fout, "Offset / size of bbMemorySsaNumIn = %3u / %3u\n", offsetof(BasicBlock, bbMemorySsaNumIn), + sizeof(bbDummy->bbMemorySsaNumIn)); + fprintf(fout, "Offset / size of bbMemorySsaNumOut = %3u / %3u\n", offsetof(BasicBlock, bbMemorySsaNumOut), + sizeof(bbDummy->bbMemorySsaNumOut)); + fprintf(fout, "Offset / size of bbScope = %3u / %3u\n", offsetof(BasicBlock, bbScope), + sizeof(bbDummy->bbScope)); + fprintf(fout, "Offset / size of bbCseGen = %3u / %3u\n", offsetof(BasicBlock, bbCseGen), + sizeof(bbDummy->bbCseGen)); +#if ASSERTION_PROP + fprintf(fout, "Offset / size of bbAssertionGen = %3u / %3u\n", offsetof(BasicBlock, bbAssertionGen), + sizeof(bbDummy->bbAssertionGen)); +#endif // ASSERTION_PROP + fprintf(fout, "Offset / size of bbCseIn = %3u / %3u\n", offsetof(BasicBlock, bbCseIn), + sizeof(bbDummy->bbCseIn)); +#if ASSERTION_PROP + fprintf(fout, "Offset / size of bbAssertionIn = %3u / %3u\n", offsetof(BasicBlock, bbAssertionIn), + sizeof(bbDummy->bbAssertionIn)); +#endif // ASSERTION_PROP + fprintf(fout, "Offset / size of bbCseOut = %3u / %3u\n", offsetof(BasicBlock, bbCseOut), + sizeof(bbDummy->bbCseOut)); +#if ASSERTION_PROP + fprintf(fout, "Offset / size of bbAssertionOut = %3u / %3u\n", offsetof(BasicBlock, bbAssertionOut), + sizeof(bbDummy->bbAssertionOut)); +#endif // ASSERTION_PROP + fprintf(fout, "Offset / size of bbEmitCookie = %3u / %3u\n", offsetof(BasicBlock, bbEmitCookie), + sizeof(bbDummy->bbEmitCookie)); + +#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_) + fprintf(fout, "Offset / size of bbUnwindNopEmitCookie = %3u / %3u\n", offsetof(BasicBlock, bbUnwindNopEmitCookie), + sizeof(bbDummy->bbUnwindNopEmitCookie)); +#endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_) + +#ifdef VERIFIER + fprintf(fout, "Offset / size of bbStackIn = %3u / %3u\n", offsetof(BasicBlock, bbStackIn), + sizeof(bbDummy->bbStackIn)); + fprintf(fout, "Offset / size of bbStackOut = %3u / %3u\n", offsetof(BasicBlock, bbStackOut), + sizeof(bbDummy->bbStackOut)); + fprintf(fout, "Offset / size of bbTypesIn = %3u / %3u\n", offsetof(BasicBlock, bbTypesIn), + sizeof(bbDummy->bbTypesIn)); + fprintf(fout, "Offset / size of bbTypesOut = %3u / %3u\n", offsetof(BasicBlock, bbTypesOut), + sizeof(bbDummy->bbTypesOut)); +#endif // VERIFIER + +#ifdef DEBUG + fprintf(fout, "Offset / size of bbLoopNum = %3u / %3u\n", offsetof(BasicBlock, bbLoopNum), + sizeof(bbDummy->bbLoopNum)); +#endif // DEBUG + + fprintf(fout, "Offset / size of bbNatLoopNum = %3u / %3u\n", offsetof(BasicBlock, bbNatLoopNum), + sizeof(bbDummy->bbNatLoopNum)); + + fprintf(fout, "\n"); + fprintf(fout, "Size of BasicBlock = %3u\n", sizeof(BasicBlock)); + +#endif // MEASURE_BLOCK_SIZE +} diff --git a/src/jit/block.h b/src/jit/block.h index d447429..56b1c73 100644 --- a/src/jit/block.h +++ b/src/jit/block.h @@ -1183,6 +1183,8 @@ struct BasicBlock : private LIR::Range return false; } #endif // DEBUG + + static void DisplayStaticSizes(FILE* fout); }; template <> diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index 3887f0e..7bb93a2 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -1783,115 +1783,11 @@ void Compiler::compShutdown() /* static */ void Compiler::compDisplayStaticSizes(FILE* fout) { - #if MEASURE_NODE_SIZE GenTree::DumpNodeSizes(fout); #endif -#if MEASURE_BLOCK_SIZE - - BasicBlock* bbDummy = nullptr; - - fprintf(fout, "\n"); - fprintf(fout, "Offset / size of bbNext = %3u / %3u\n", offsetof(BasicBlock, bbNext), - sizeof(bbDummy->bbNext)); - fprintf(fout, "Offset / size of bbNum = %3u / %3u\n", offsetof(BasicBlock, bbNum), - sizeof(bbDummy->bbNum)); - fprintf(fout, "Offset / size of bbPostOrderNum = %3u / %3u\n", offsetof(BasicBlock, bbPostOrderNum), - sizeof(bbDummy->bbPostOrderNum)); - fprintf(fout, "Offset / size of bbRefs = %3u / %3u\n", offsetof(BasicBlock, bbRefs), - sizeof(bbDummy->bbRefs)); - fprintf(fout, "Offset / size of bbFlags = %3u / %3u\n", offsetof(BasicBlock, bbFlags), - sizeof(bbDummy->bbFlags)); - fprintf(fout, "Offset / size of bbWeight = %3u / %3u\n", offsetof(BasicBlock, bbWeight), - sizeof(bbDummy->bbWeight)); - fprintf(fout, "Offset / size of bbJumpKind = %3u / %3u\n", offsetof(BasicBlock, bbJumpKind), - sizeof(bbDummy->bbJumpKind)); - fprintf(fout, "Offset / size of bbJumpOffs = %3u / %3u\n", offsetof(BasicBlock, bbJumpOffs), - sizeof(bbDummy->bbJumpOffs)); - fprintf(fout, "Offset / size of bbJumpDest = %3u / %3u\n", offsetof(BasicBlock, bbJumpDest), - sizeof(bbDummy->bbJumpDest)); - fprintf(fout, "Offset / size of bbJumpSwt = %3u / %3u\n", offsetof(BasicBlock, bbJumpSwt), - sizeof(bbDummy->bbJumpSwt)); - fprintf(fout, "Offset / size of bbEntryState = %3u / %3u\n", offsetof(BasicBlock, bbEntryState), - sizeof(bbDummy->bbEntryState)); - fprintf(fout, "Offset / size of bbStkTempsIn = %3u / %3u\n", offsetof(BasicBlock, bbStkTempsIn), - sizeof(bbDummy->bbStkTempsIn)); - fprintf(fout, "Offset / size of bbStkTempsOut = %3u / %3u\n", offsetof(BasicBlock, bbStkTempsOut), - sizeof(bbDummy->bbStkTempsOut)); - fprintf(fout, "Offset / size of bbTryIndex = %3u / %3u\n", offsetof(BasicBlock, bbTryIndex), - sizeof(bbDummy->bbTryIndex)); - fprintf(fout, "Offset / size of bbHndIndex = %3u / %3u\n", offsetof(BasicBlock, bbHndIndex), - sizeof(bbDummy->bbHndIndex)); - fprintf(fout, "Offset / size of bbCatchTyp = %3u / %3u\n", offsetof(BasicBlock, bbCatchTyp), - sizeof(bbDummy->bbCatchTyp)); - fprintf(fout, "Offset / size of bbStkDepth = %3u / %3u\n", offsetof(BasicBlock, bbStkDepth), - sizeof(bbDummy->bbStkDepth)); - fprintf(fout, "Offset / size of bbFPinVars = %3u / %3u\n", offsetof(BasicBlock, bbFPinVars), - sizeof(bbDummy->bbFPinVars)); - fprintf(fout, "Offset / size of bbPreds = %3u / %3u\n", offsetof(BasicBlock, bbPreds), - sizeof(bbDummy->bbPreds)); - fprintf(fout, "Offset / size of bbReach = %3u / %3u\n", offsetof(BasicBlock, bbReach), - sizeof(bbDummy->bbReach)); - fprintf(fout, "Offset / size of bbIDom = %3u / %3u\n", offsetof(BasicBlock, bbIDom), - sizeof(bbDummy->bbIDom)); - fprintf(fout, "Offset / size of bbDfsNum = %3u / %3u\n", offsetof(BasicBlock, bbDfsNum), - sizeof(bbDummy->bbDfsNum)); - fprintf(fout, "Offset / size of bbCodeOffs = %3u / %3u\n", offsetof(BasicBlock, bbCodeOffs), - sizeof(bbDummy->bbCodeOffs)); - fprintf(fout, "Offset / size of bbCodeOffsEnd = %3u / %3u\n", offsetof(BasicBlock, bbCodeOffsEnd), - sizeof(bbDummy->bbCodeOffsEnd)); - fprintf(fout, "Offset / size of bbVarUse = %3u / %3u\n", offsetof(BasicBlock, bbVarUse), - sizeof(bbDummy->bbVarUse)); - fprintf(fout, "Offset / size of bbVarDef = %3u / %3u\n", offsetof(BasicBlock, bbVarDef), - sizeof(bbDummy->bbVarDef)); - fprintf(fout, "Offset / size of bbLiveIn = %3u / %3u\n", offsetof(BasicBlock, bbLiveIn), - sizeof(bbDummy->bbLiveIn)); - fprintf(fout, "Offset / size of bbLiveOut = %3u / %3u\n", offsetof(BasicBlock, bbLiveOut), - sizeof(bbDummy->bbLiveOut)); - fprintf(fout, "Offset / size of bbMemorySsaPhiFunc = %3u / %3u\n", offsetof(BasicBlock, bbMemorySsaPhiFunc), - sizeof(bbDummy->bbMemorySsaPhiFunc)); - fprintf(fout, "Offset / size of bbMemorySsaNumIn = %3u / %3u\n", offsetof(BasicBlock, bbMemorySsaNumIn), - sizeof(bbDummy->bbMemorySsaNumIn)); - fprintf(fout, "Offset / size of bbMemorySsaNumOut = %3u / %3u\n", offsetof(BasicBlock, bbMemorySsaNumOut), - sizeof(bbDummy->bbMemorySsaNumOut)); - fprintf(fout, "Offset / size of bbScope = %3u / %3u\n", offsetof(BasicBlock, bbScope), - sizeof(bbDummy->bbScope)); - fprintf(fout, "Offset / size of bbCseGen = %3u / %3u\n", offsetof(BasicBlock, bbCseGen), - sizeof(bbDummy->bbCseGen)); - fprintf(fout, "Offset / size of bbCseIn = %3u / %3u\n", offsetof(BasicBlock, bbCseIn), - sizeof(bbDummy->bbCseIn)); - fprintf(fout, "Offset / size of bbCseOut = %3u / %3u\n", offsetof(BasicBlock, bbCseOut), - sizeof(bbDummy->bbCseOut)); - - fprintf(fout, "Offset / size of bbEmitCookie = %3u / %3u\n", offsetof(BasicBlock, bbEmitCookie), - sizeof(bbDummy->bbEmitCookie)); - -#if FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_) - fprintf(fout, "Offset / size of bbUnwindNopEmitCookie = %3u / %3u\n", offsetof(BasicBlock, bbUnwindNopEmitCookie), - sizeof(bbDummy->bbUnwindNopEmitCookie)); -#endif // FEATURE_EH_FUNCLETS && defined(_TARGET_ARM_) - -#ifdef VERIFIER - fprintf(fout, "Offset / size of bbStackIn = %3u / %3u\n", offsetof(BasicBlock, bbStackIn), - sizeof(bbDummy->bbStackIn)); - fprintf(fout, "Offset / size of bbStackOut = %3u / %3u\n", offsetof(BasicBlock, bbStackOut), - sizeof(bbDummy->bbStackOut)); - fprintf(fout, "Offset / size of bbTypesIn = %3u / %3u\n", offsetof(BasicBlock, bbTypesIn), - sizeof(bbDummy->bbTypesIn)); - fprintf(fout, "Offset / size of bbTypesOut = %3u / %3u\n", offsetof(BasicBlock, bbTypesOut), - sizeof(bbDummy->bbTypesOut)); -#endif // VERIFIER - -#ifdef DEBUG - fprintf(fout, "Offset / size of bbLoopNum = %3u / %3u\n", offsetof(BasicBlock, bbLoopNum), - sizeof(bbDummy->bbLoopNum)); -#endif // DEBUG - - fprintf(fout, "\n"); - fprintf(fout, "Size of BasicBlock = %3u\n", sizeof(BasicBlock)); - -#endif // MEASURE_BLOCK_SIZE + BasicBlock::DisplayStaticSizes(fout); #if EMITTER_STATS emitterStaticStats(fout); diff --git a/src/jit/emit.cpp b/src/jit/emit.cpp index 982417d..daaf237 100644 --- a/src/jit/emit.cpp +++ b/src/jit/emit.cpp @@ -267,6 +267,10 @@ size_t emitter::emitSizeMethod; size_t emitter::emitTotMemAlloc; unsigned emitter::emitTotalInsCnt; +unsigned emitter::emitCurPrologInsCnt; +size_t emitter::emitCurPrologIGSize; +unsigned emitter::emitMaxPrologInsCnt; +size_t emitter::emitMaxPrologIGSize; unsigned emitter::emitTotalIGcnt; unsigned emitter::emitTotalPhIGcnt; unsigned emitter::emitTotalIGjmps; @@ -274,6 +278,25 @@ unsigned emitter::emitTotalIGptrs; unsigned emitter::emitTotalIGicnt; size_t emitter::emitTotalIGsize; unsigned emitter::emitTotalIGmcnt; +unsigned emitter::emitTotalIGEmitAdd; + +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_XARCH_ +unsigned emitter::emitTotalIDescAmdCnt; +unsigned emitter::emitTotalIDescCnsAmdCnt; +#endif // _TARGET_XARCH_ +unsigned emitter::emitTotalIDescCGCACnt; +#ifdef _TARGET_ARM_ +unsigned emitter::emitTotalIDescRelocCnt; +#endif // _TARGET_ARM_ unsigned emitter::emitSmallDspCnt; unsigned emitter::emitLargeDspCnt; @@ -286,24 +309,40 @@ void emitterStaticStats(FILE* fout) { // insGroup members + insGroup* igDummy = nullptr; + fprintf(fout, "\n"); fprintf(fout, "insGroup:\n"); - fprintf(fout, "Offset of igNext = %2u\n", offsetof(insGroup, igNext)); + fprintf(fout, "Offset / size of igNext = %2u / %2u\n", offsetof(insGroup, igNext), + sizeof(igDummy->igNext)); #ifdef DEBUG - fprintf(fout, "Offset of igSelf = %2u\n", offsetof(insGroup, igSelf)); + fprintf(fout, "Offset / size of igSelf = %2u / %2u\n", offsetof(insGroup, igSelf), + sizeof(igDummy->igSelf)); #endif - fprintf(fout, "Offset of igNum = %2u\n", offsetof(insGroup, igNum)); - fprintf(fout, "Offset of igOffs = %2u\n", offsetof(insGroup, igOffs)); - fprintf(fout, "Offset of igFuncIdx = %2u\n", offsetof(insGroup, igFuncIdx)); - fprintf(fout, "Offset of igFlags = %2u\n", offsetof(insGroup, igFlags)); - fprintf(fout, "Offset of igSize = %2u\n", offsetof(insGroup, igSize)); - fprintf(fout, "Offset of igData = %2u\n", offsetof(insGroup, igData)); + fprintf(fout, "Offset / size of igNum = %2u / %2u\n", offsetof(insGroup, igNum), + sizeof(igDummy->igNum)); + fprintf(fout, "Offset / size of igOffs = %2u / %2u\n", offsetof(insGroup, igOffs), + sizeof(igDummy->igOffs)); + fprintf(fout, "Offset / size of igFuncIdx = %2u / %2u\n", offsetof(insGroup, igFuncIdx), + sizeof(igDummy->igFuncIdx)); + fprintf(fout, "Offset / size of igFlags = %2u / %2u\n", offsetof(insGroup, igFlags), + sizeof(igDummy->igFlags)); + fprintf(fout, "Offset / size of igSize = %2u / %2u\n", offsetof(insGroup, igSize), + sizeof(igDummy->igSize)); + fprintf(fout, "Offset / size of igData = %2u / %2u\n", offsetof(insGroup, igData), + sizeof(igDummy->igData)); + fprintf(fout, "Offset / size of igPhData = %2u / %2u\n", offsetof(insGroup, igPhData), + sizeof(igDummy->igPhData)); #if EMIT_TRACK_STACK_DEPTH - fprintf(fout, "Offset of igStkLvl = %2u\n", offsetof(insGroup, igStkLvl)); + fprintf(fout, "Offset / size of igStkLvl = %2u / %2u\n", offsetof(insGroup, igStkLvl), + sizeof(igDummy->igStkLvl)); #endif - fprintf(fout, "Offset of igGCregs = %2u\n", offsetof(insGroup, igGCregs)); - fprintf(fout, "Offset of igInsCnt = %2u\n", offsetof(insGroup, igInsCnt)); - fprintf(fout, "Size of insGroup = %u\n", sizeof(insGroup)); + fprintf(fout, "Offset / size of igGCregs = %2u / %2u\n", offsetof(insGroup, igGCregs), + sizeof(igDummy->igGCregs)); + fprintf(fout, "Offset / size of igInsCnt = %2u / %2u\n", offsetof(insGroup, igInsCnt), + sizeof(igDummy->igInsCnt)); + fprintf(fout, "\n"); + fprintf(fout, "Size of insGroup = %u\n", sizeof(insGroup)); // insPlaceholderGroupData members @@ -321,7 +360,8 @@ void emitterStaticStats(FILE* fout) fprintf(fout, "Size of insPlaceholderGroupData = %u\n", sizeof(insPlaceholderGroupData)); fprintf(fout, "\n"); - fprintf(fout, "Size of instrDesc = %2u\n", sizeof(emitter::instrDesc)); + fprintf(fout, "SMALL_IDSC_SIZE = %2u\n", SMALL_IDSC_SIZE); + fprintf(fout, "Size of instrDesc = %2u\n", sizeof(emitter::instrDesc)); // fprintf(fout, "Offset of _idIns = %2u\n", offsetof(emitter::instrDesc, _idIns )); // fprintf(fout, "Offset of _idInsFmt = %2u\n", offsetof(emitter::instrDesc, _idInsFmt )); // fprintf(fout, "Offset of _idOpSize = %2u\n", offsetof(emitter::instrDesc, _idOpSize )); @@ -330,6 +370,42 @@ void emitterStaticStats(FILE* fout) // fprintf(fout, "\n"); // fprintf(fout, "Size of _idAddrUnion= %2u\n", sizeof(((emitter::instrDesc*)0)->_idAddrUnion)); + fprintf(fout, "Size of instrDescJmp = %2u\n", sizeof(emitter::instrDescJmp)); +#if !defined(_TARGET_ARM64_) + fprintf(fout, "Size of instrDescLbl = %2u\n", sizeof(emitter::instrDescLbl)); +#endif // !defined(_TARGET_ARM64_) + fprintf(fout, "Size of instrDescCns = %2u\n", sizeof(emitter::instrDescCns)); + fprintf(fout, "Size of instrDescDsp = %2u\n", sizeof(emitter::instrDescDsp)); + fprintf(fout, "Size of instrDescCnsDsp = %2u\n", sizeof(emitter::instrDescCnsDsp)); +#ifdef _TARGET_XARCH_ + fprintf(fout, "Size of instrDescAmd = %2u\n", sizeof(emitter::instrDescAmd)); + fprintf(fout, "Size of instrDescCnsAmd = %2u\n", sizeof(emitter::instrDescCnsAmd)); +#endif // _TARGET_XARCH_ + fprintf(fout, "Size of instrDescCGCA = %2u\n", sizeof(emitter::instrDescCGCA)); +#ifdef _TARGET_ARM_ + fprintf(fout, "Size of instrDescReloc = %2u\n", sizeof(emitter::instrDescReloc)); +#endif // _TARGET_ARM_ + + fprintf(fout, "\n"); + fprintf(fout, "SC_IG_BUFFER_SIZE = %2u\n", SC_IG_BUFFER_SIZE); + fprintf(fout, "SMALL_IDSC_SIZE per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / SMALL_IDSC_SIZE); + fprintf(fout, "instrDesc per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDesc)); + fprintf(fout, "instrDescJmp per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescJmp)); +#if !defined(_TARGET_ARM64_) + fprintf(fout, "instrDescLbl per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescLbl)); +#endif // !defined(_TARGET_ARM64_) + fprintf(fout, "instrDescCns per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCns)); + fprintf(fout, "instrDescDsp per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescDsp)); + fprintf(fout, "instrDescCnsDsp per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCnsDsp)); +#ifdef _TARGET_XARCH_ + fprintf(fout, "instrDescAmd per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescAmd)); + fprintf(fout, "instrDescCnsAmd per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCnsAmd)); +#endif // _TARGET_XARCH_ + fprintf(fout, "instrDescCGCA per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescCGCA)); +#ifdef _TARGET_ARM_ + fprintf(fout, "instrDescReloc per IG buffer = %2u\n", SC_IG_BUFFER_SIZE / sizeof(emitter::instrDescReloc)); +#endif // _TARGET_ARM_ + fprintf(fout, "\n"); fprintf(fout, "GCInfo::regPtrDsc:\n"); fprintf(fout, "Offset of rpdNext = %2u\n", offsetof(GCInfo::regPtrDsc, rpdNext)); @@ -356,7 +432,7 @@ void emitterStats(FILE* fout) fprintf(fout, "\n"); } - assert(emitter::emitTotalInsCnt); + assert(emitter::emitTotalInsCnt > 0); fprintf(fout, "Average of %4.2f bytes of code generated per instruction\n", (double)totActualSize / emitter::emitTotalInsCnt); @@ -378,26 +454,33 @@ void emitterStats(FILE* fout) if ((c > 0) && (1000 * c >= ic)) { dc += c; - fprintf(fout, " %-13s %8u (%5.2f%%)\n", emitter::emitIfName(f), c, 100.0 * c / ic); + fprintf(fout, " %-14s %8u (%5.2f%%)\n", emitter::emitIfName(f), c, 100.0 * c / ic); } } - fprintf(fout, " --------------------------------\n"); - fprintf(fout, " %-13s %8u (%5.2f%%)\n", "Total shown", dc, 100.0 * dc / ic); + fprintf(fout, " ---------------------------------\n"); + fprintf(fout, " %-14s %8u (%5.2f%%)\n", "Total shown", dc, 100.0 * dc / ic); - if (emitter::emitTotalIGmcnt) + if (emitter::emitTotalIGmcnt > 0) { + fprintf(fout, "\n"); fprintf(fout, "Total of %8u methods\n", emitter::emitTotalIGmcnt); fprintf(fout, "Total of %8u insGroup\n", emitter::emitTotalIGcnt); fprintf(fout, "Total of %8u insPlaceholderGroupData\n", emitter::emitTotalPhIGcnt); + fprintf(fout, "Total of %8u emitAdd insGroup\n", emitter::emitTotalIGEmitAdd); fprintf(fout, "Total of %8u instructions\n", emitter::emitTotalIGicnt); fprintf(fout, "Total of %8u jumps\n", emitter::emitTotalIGjmps); fprintf(fout, "Total of %8u GC livesets\n", emitter::emitTotalIGptrs); fprintf(fout, "\n"); + fprintf(fout, "Max prolog instrDesc count: %8u\n", emitter::emitMaxPrologInsCnt); + fprintf(fout, "Max prolog insGroup size : %8u\n", emitter::emitMaxPrologIGSize); + fprintf(fout, "\n"); fprintf(fout, "Average of %8.1lf insGroup per method\n", (double)emitter::emitTotalIGcnt / emitter::emitTotalIGmcnt); fprintf(fout, "Average of %8.1lf insPhGroup per method\n", (double)emitter::emitTotalPhIGcnt / emitter::emitTotalIGmcnt); + fprintf(fout, "Average of %8.1lf emitAdd IG per method\n", + (double)emitter::emitTotalIGEmitAdd / emitter::emitTotalIGmcnt); fprintf(fout, "Average of %8.1lf instructions per method\n", (double)emitter::emitTotalIGicnt / emitter::emitTotalIGmcnt); fprintf(fout, "Average of %8.1lf desc. bytes per method\n", @@ -419,6 +502,37 @@ void emitterStats(FILE* fout) fprintf(fout, "\n"); fprintf(fout, "A total of %8u 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, + 100.0 * emitter::emitTotalIDescSmallCnt / emitter::emitTotalInsCnt); + 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, + 100.0 * emitter::emitTotalIDescCnsCnt / emitter::emitTotalInsCnt); + 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_XARCH_ + 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, + 100.0 * emitter::emitTotalIDescCnsAmdCnt / emitter::emitTotalInsCnt); +#endif // _TARGET_XARCH_ + 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, "\n"); } fprintf(fout, "Descriptor size distribution:\n"); @@ -433,33 +547,37 @@ void emitterStats(FILE* fout) stkDepthTable.dump(fout); fprintf(fout, "\n"); - int i; - unsigned c; - unsigned m; - - if (emitter::emitSmallCnsCnt || emitter::emitLargeCnsCnt) + if ((emitter::emitSmallCnsCnt > 0) || (emitter::emitLargeCnsCnt > 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)); } -#if 0 - // TODO-Cleanup: WHy is this in #if 0 - Is EMITTER_STATS ever used? Fix or delete this. - if (emitter::emitSmallCnsCnt) + // Print out the most common small constants. + if (emitter::emitSmallCnsCnt > 0) { - fprintf(fout, "\n"); + fprintf(fout, "\n\n"); + fprintf(fout, "Common small constants >= %2u, <= %2u\n", ID_MIN_SMALL_CNS, ID_MAX_SMALL_CNS); - m = emitter::emitSmallCnsCnt/1000 + 1; + unsigned m = emitter::emitSmallCnsCnt / 1000 + 1; - for (i = ID_MIN_SMALL_CNS; i < ID_MAX_SMALL_CNS; i++) + for (int i = ID_MIN_SMALL_CNS; (i <= ID_MAX_SMALL_CNS) && (i < SMALL_CNS_TSZ); i++) { - c = emitter::emitSmallCns[i-ID_MIN_SMALL_CNS]; - if (c >= m) - fprintf(fout, "cns[%4d] = %u\n", i, c); + unsigned c = emitter::emitSmallCns[i - ID_MIN_SMALL_CNS]; + if (c >= m) + { + if (i == SMALL_CNS_TSZ - 1) + { + fprintf(fout, "cns[>=%4d] = %u\n", i, c); + } + else + { + fprintf(fout, "cns[%4d] = %u\n", i, c); + } + } } } -#endif // 0 fprintf(fout, "%8u bytes allocated in the emitter\n", emitter::emitTotMemAlloc); } @@ -789,6 +907,22 @@ insGroup* emitter::emitSavIG(bool emitAdd) emitTotalIGicnt += emitCurIGinsCnt; emitTotalIGsize += sz; emitSizeMethod += sz; + + if (emitIGisInProlog(ig)) + { + emitCurPrologInsCnt += emitCurIGinsCnt; + emitCurPrologIGSize += sz; + + // Keep track of the maximums. + if (emitCurPrologInsCnt > emitMaxPrologInsCnt) + { + emitMaxPrologInsCnt = emitCurPrologInsCnt; + } + if (emitCurPrologIGSize > emitMaxPrologIGSize) + { + emitMaxPrologIGSize = emitCurPrologIGSize; + } + } #endif // printf("Group [%08X]%3u has %2u instructions (%4u bytes at %08X)\n", ig, ig->igNum, emitCurIGinsCnt, sz, id); @@ -1019,7 +1153,9 @@ void emitter::emitBegFN(bool hasFramePtr #if EMITTER_STATS emitTotalIGmcnt++; - emitSizeMethod = 0; + emitSizeMethod = 0; + emitCurPrologInsCnt = 0; + emitCurPrologIGSize = 0; #endif emitInsCount = 0; @@ -1170,7 +1306,7 @@ size_t emitter::emitGenEpilogLst(size_t (*fp)(void*, unsigned), void* cp) * The following series of methods allocates instruction descriptors. */ -void* emitter::emitAllocInstr(size_t sz, emitAttr opsz) +void* emitter::emitAllocAnyInstr(size_t sz, emitAttr opsz) { instrDesc* id; @@ -2154,7 +2290,10 @@ emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, target_ssize_t cn #if EMITTER_STATS emitSmallCnsCnt++; - emitSmallCns[cns - ID_MIN_SMALL_CNS]++; + if ((cns - ID_MIN_SMALL_CNS) >= (SMALL_CNS_TSZ - 1)) + emitSmallCns[SMALL_CNS_TSZ - 1]++; + else + emitSmallCns[cns - ID_MIN_SMALL_CNS]++; emitSmallDspCnt++; #endif @@ -2162,10 +2301,7 @@ emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, target_ssize_t cn } else { - instrDescCns* id = emitAllocInstrCns(size); - - id->idSetIsLargeCns(); - id->idcCnsVal = cns; + instrDescCns* id = emitAllocInstrCns(size, cns); #if EMITTER_STATS emitLargeCnsCnt++; @@ -2189,7 +2325,10 @@ emitter::instrDesc* emitter::emitNewInstrCnsDsp(emitAttr size, target_ssize_t cn #if EMITTER_STATS emitLargeDspCnt++; emitSmallCnsCnt++; - emitSmallCns[cns - ID_MIN_SMALL_CNS]++; + 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; @@ -6861,6 +7000,10 @@ void emitter::emitNxtIG(bool emitAdd) if (emitAdd) { emitCurIG->igFlags |= IGF_EMIT_ADD; + +#if EMITTER_STATS + emitTotalIGEmitAdd++; +#endif // EMITTER_STATS } // We've created a new IG; no need to force another one. diff --git a/src/jit/emit.h b/src/jit/emit.h index c5b50a5..1308531 100644 --- a/src/jit/emit.h +++ b/src/jit/emit.h @@ -589,7 +589,8 @@ protected: static_assert_no_msg(INS_count <= 256); instruction _idIns : 8; #endif // !(defined(_TARGET_XARCH_) || defined(_TARGET_ARM64_)) - // The format for the instruction + +// The format for the instruction #if defined(_TARGET_XARCH_) static_assert_no_msg(IF_COUNT <= 128); insFormat _idInsFmt : 7; @@ -1613,9 +1614,9 @@ private: // and must store them all to the frame on entry. If the frame is very large, we generate // ugly code like "movw r10, 0x488; add r10, sp; vstr s0, [r10]" for each store, which // eats up our insGroup buffer. -#define SC_IG_BUFFER_SIZE (100 * sizeof(instrDesc) + 14 * SMALL_IDSC_SIZE) +#define SC_IG_BUFFER_SIZE (100 * sizeof(emitter::instrDesc) + 14 * SMALL_IDSC_SIZE) #else // !_TARGET_ARMARCH_ -#define SC_IG_BUFFER_SIZE (50 * sizeof(instrDesc) + 14 * SMALL_IDSC_SIZE) +#define SC_IG_BUFFER_SIZE (50 * sizeof(emitter::instrDesc) + 14 * SMALL_IDSC_SIZE) #endif // !_TARGET_ARMARCH_ size_t emitIGbuffSize; @@ -1771,32 +1772,52 @@ private: int emitNextRandomNop(); - void* emitAllocInstr(size_t sz, emitAttr attr); + // + // Functions for allocating instrDescs. + // + // The emitAllocXXX functions are the base level that allocate memory, and do little else. + // The emitters themselves use emitNewXXX, which might be thin wrappers over the emitAllocXXX functions. + // + + void* emitAllocAnyInstr(size_t sz, emitAttr attr); instrDesc* emitAllocInstr(emitAttr attr) { - return (instrDesc*)emitAllocInstr(sizeof(instrDesc), attr); +#if EMITTER_STATS + emitTotalIDescCnt++; +#endif // EMITTER_STATS + return (instrDesc*)emitAllocAnyInstr(sizeof(instrDesc), attr); } instrDescJmp* emitAllocInstrJmp() { - return (instrDescJmp*)emitAllocInstr(sizeof(instrDescJmp), EA_1BYTE); +#if EMITTER_STATS + emitTotalIDescJmpCnt++; +#endif // EMITTER_STATS + return (instrDescJmp*)emitAllocAnyInstr(sizeof(instrDescJmp), EA_1BYTE); } #if !defined(_TARGET_ARM64_) instrDescLbl* emitAllocInstrLbl() { - return (instrDescLbl*)emitAllocInstr(sizeof(instrDescLbl), EA_4BYTE); +#if EMITTER_STATS + emitTotalIDescLblCnt++; +#endif // EMITTER_STATS + return (instrDescLbl*)emitAllocAnyInstr(sizeof(instrDescLbl), EA_4BYTE); } #endif // !_TARGET_ARM64_ instrDescCns* emitAllocInstrCns(emitAttr attr) { - return (instrDescCns*)emitAllocInstr(sizeof(instrDescCns), attr); +#if EMITTER_STATS + emitTotalIDescCnsCnt++; +#endif // EMITTER_STATS + return (instrDescCns*)emitAllocAnyInstr(sizeof(instrDescCns), attr); } - instrDescCns* emitAllocInstrCns(emitAttr attr, int cns) + + instrDescCns* emitAllocInstrCns(emitAttr attr, target_size_t cns) { - instrDescCns* result = (instrDescCns*)emitAllocInstr(sizeof(instrDescCns), attr); + instrDescCns* result = emitAllocInstrCns(attr); result->idSetIsLargeCns(); result->idcCnsVal = cns; return result; @@ -1804,31 +1825,46 @@ private: instrDescDsp* emitAllocInstrDsp(emitAttr attr) { - return (instrDescDsp*)emitAllocInstr(sizeof(instrDescDsp), attr); +#if EMITTER_STATS + emitTotalIDescDspCnt++; +#endif // EMITTER_STATS + return (instrDescDsp*)emitAllocAnyInstr(sizeof(instrDescDsp), attr); } instrDescCnsDsp* emitAllocInstrCnsDsp(emitAttr attr) { - return (instrDescCnsDsp*)emitAllocInstr(sizeof(instrDescCnsDsp), attr); +#if EMITTER_STATS + emitTotalIDescCnsDspCnt++; +#endif // EMITTER_STATS + return (instrDescCnsDsp*)emitAllocAnyInstr(sizeof(instrDescCnsDsp), attr); } #ifdef _TARGET_XARCH_ instrDescAmd* emitAllocInstrAmd(emitAttr attr) { - return (instrDescAmd*)emitAllocInstr(sizeof(instrDescAmd), attr); +#if EMITTER_STATS + emitTotalIDescAmdCnt++; +#endif // EMITTER_STATS + return (instrDescAmd*)emitAllocAnyInstr(sizeof(instrDescAmd), attr); } instrDescCnsAmd* emitAllocInstrCnsAmd(emitAttr attr) { - return (instrDescCnsAmd*)emitAllocInstr(sizeof(instrDescCnsAmd), attr); +#if EMITTER_STATS + emitTotalIDescCnsAmdCnt++; +#endif // EMITTER_STATS + return (instrDescCnsAmd*)emitAllocAnyInstr(sizeof(instrDescCnsAmd), attr); } #endif // _TARGET_XARCH_ instrDescCGCA* emitAllocInstrCGCA(emitAttr attr) { - return (instrDescCGCA*)emitAllocInstr(sizeof(instrDescCGCA), attr); +#if EMITTER_STATS + emitTotalIDescCGCACnt++; +#endif // EMITTER_STATS + return (instrDescCGCA*)emitAllocAnyInstr(sizeof(instrDescCGCA), attr); } instrDesc* emitNewInstrSmall(emitAttr attr); @@ -2103,14 +2139,38 @@ public: static unsigned emitTotalInsCnt; + static unsigned emitCurPrologInsCnt; // current number of prolog instrDescs + static size_t emitCurPrologIGSize; // current size of prolog instrDescs + static unsigned emitMaxPrologInsCnt; // maximum number of prolog instrDescs + static size_t emitMaxPrologIGSize; // maximum size of prolog instrDescs + static unsigned emitTotalIGcnt; // total number of insGroup allocated static unsigned emitTotalPhIGcnt; // total number of insPlaceholderGroupData allocated static unsigned emitTotalIGicnt; static size_t emitTotalIGsize; - static unsigned emitTotalIGmcnt; // total method count + static unsigned emitTotalIGmcnt; // total method count + static unsigned emitTotalIGEmitAdd; // total number of 'emitAdd' (overflow) groups static unsigned emitTotalIGjmps; static unsigned emitTotalIGptrs; + 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_XARCH_ + static unsigned emitTotalIDescAmdCnt; + static unsigned emitTotalIDescCnsAmdCnt; +#endif // _TARGET_XARCH_ + static unsigned emitTotalIDescCGCACnt; +#ifdef _TARGET_ARM_ + static unsigned emitTotalIDescRelocCnt; +#endif // _TARGET_ARM_ + static size_t emitTotMemAlloc; static unsigned emitSmallDspCnt; @@ -2294,10 +2354,13 @@ inline emitter::instrDesc* emitter::emitNewInstrSmall(emitAttr attr) { instrDesc* id; - // This is larger than the Tiny Descr - id = (instrDesc*)emitAllocInstr(SMALL_IDSC_SIZE, attr); + id = (instrDesc*)emitAllocAnyInstr(SMALL_IDSC_SIZE, attr); id->idSetIsSmallDsc(); +#if EMITTER_STATS + emitTotalIDescSmallCnt++; +#endif // EMITTER_STATS + return id; } @@ -2359,12 +2422,11 @@ inline emitter::instrDesc* emitter::emitNewInstrCns(emitAttr attr, target_ssize_ if (instrDesc::fitsInSmallCns(cns)) { instrDesc* id = emitAllocInstr(attr); - id->idSmallCns(cns); #if EMITTER_STATS emitSmallCnsCnt++; - if (cns - ID_MIN_SMALL_CNS >= SMALL_CNS_TSZ) + if ((cns - ID_MIN_SMALL_CNS) >= (SMALL_CNS_TSZ - 1)) emitSmallCns[SMALL_CNS_TSZ - 1]++; else emitSmallCns[cns - ID_MIN_SMALL_CNS]++; @@ -2374,10 +2436,7 @@ inline emitter::instrDesc* emitter::emitNewInstrCns(emitAttr attr, target_ssize_ } else { - instrDescCns* id = emitAllocInstrCns(attr); - - id->idSetIsLargeCns(); - id->idcCnsVal = cns; + instrDescCns* id = emitAllocInstrCns(attr, cns); #if EMITTER_STATS emitLargeCnsCnt++; @@ -2414,29 +2473,36 @@ inline size_t emitter::emitGetInstrDescSize(const instrDesc* id) * constant operand. This is the same as emitNewInstrCns() except that here * any constant that is small enough for instrDesc::fitsInSmallCns() only gets * allocated SMALL_IDSC_SIZE bytes (and is thus a small descriptor, whereas - * emitNewInstrCns() always allocates at least sizeof(instrDesc). + * emitNewInstrCns() always allocates at least sizeof(instrDesc)). */ inline emitter::instrDesc* emitter::emitNewInstrSC(emitAttr attr, target_ssize_t cns) { - instrDesc* id; - if (instrDesc::fitsInSmallCns(cns)) { - id = (instrDesc*)emitAllocInstr(SMALL_IDSC_SIZE, attr); - + instrDesc* id = emitNewInstrSmall(attr); id->idSmallCns(cns); - id->idSetIsSmallDsc(); + +#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]++; +#endif + + return id; } else { - id = (instrDesc*)emitAllocInstr(sizeof(instrDescCns), attr); + instrDescCns* id = emitAllocInstrCns(attr, cns); - id->idSetIsLargeCns(); - ((instrDescCns*)id)->idcCnsVal = cns; - } +#if EMITTER_STATS + emitLargeCnsCnt++; +#endif - return id; + return id; + } } /***************************************************************************** @@ -2466,11 +2532,15 @@ inline emitter::instrDesc* emitter::emitNewInstrReloc(emitAttr attr, BYTE* addr) { assert(EA_IS_RELOC(attr)); - instrDescReloc* id = (instrDescReloc*)emitAllocInstr(sizeof(instrDescReloc), attr); + instrDescReloc* id = (instrDescReloc*)emitAllocAnyInstr(sizeof(instrDescReloc), attr); assert(id->idIsReloc()); id->idrRelocVal = addr; +#if EMITTER_STATS + emitTotalIDescRelocCnt++; +#endif // EMITTER_STATS + return id; } diff --git a/src/jit/emitarm.cpp b/src/jit/emitarm.cpp index 8098c60..3d7089b 100644 --- a/src/jit/emitarm.cpp +++ b/src/jit/emitarm.cpp @@ -3344,9 +3344,7 @@ void emitter::emitIns_R_R_R_I(instruction ins, assert(sf != INS_FLAGS_DONT_CARE); // 3-reg ops can't use the small instrdesc - instrDescCns* id = emitAllocInstrCns(attr); - id->idSetIsLargeCns(); - id->idcCnsVal = imm; + instrDesc* id = emitNewInstrCns(attr, imm); id->idIns(ins); id->idInsFmt(fmt); diff --git a/src/jit/emitarm64.cpp b/src/jit/emitarm64.cpp index 9f4208a..d066edf 100644 --- a/src/jit/emitarm64.cpp +++ b/src/jit/emitarm64.cpp @@ -7020,7 +7020,7 @@ void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize // add reg, reg, imm ins = INS_add; fmt = IF_DI_2A; - instrDesc* id = emitAllocInstr(attr); + instrDesc* id = emitNewInstr(attr); assert(id->idIsReloc()); id->idIns(ins); diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp index bbaeb81..8bba1f6 100644 --- a/src/jit/emitxarch.cpp +++ b/src/jit/emitxarch.cpp @@ -2407,33 +2407,15 @@ emitter::instrDesc* emitter::emitNewInstrAmdCns(emitAttr size, ssize_t dsp, int { if (dsp >= AM_DISP_MIN && dsp <= AM_DISP_MAX) { - if (cns >= ID_MIN_SMALL_CNS && cns <= ID_MAX_SMALL_CNS) - { - instrDesc* id = emitAllocInstr(size); - - id->idSmallCns(cns); - - id->idAddr()->iiaAddrMode.amDisp = dsp; - assert(id->idAddr()->iiaAddrMode.amDisp == dsp); // make sure the value fit - - return id; - } - else - { - instrDescCns* id = emitAllocInstrCns(size); - - id->idSetIsLargeCns(); - id->idcCnsVal = cns; - - id->idAddr()->iiaAddrMode.amDisp = dsp; - assert(id->idAddr()->iiaAddrMode.amDisp == dsp); // make sure the value fit + instrDesc* id = emitNewInstrCns(size, cns); + id->idAddr()->iiaAddrMode.amDisp = dsp; + assert(id->idAddr()->iiaAddrMode.amDisp == dsp); // make sure the value fit - return id; - } + return id; } else { - if (cns >= ID_MIN_SMALL_CNS && cns <= ID_MAX_SMALL_CNS) + if (instrDesc::fitsInSmallCns(cns)) { instrDescAmd* id = emitAllocInstrAmd(size); -- 2.7.4