From a274b5af4bdc6af0919a28708b3085a59da32cd1 Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Mon, 13 Feb 2017 15:39:33 -0800 Subject: [PATCH] Add IR size after certain phases to the JIT log. This change adds support for measuring and reporting the number of nodes in a function after a certain subset of the JIT's phases. This reporting is enabled by setting `COMPlus_JitMeasureIR` and `COMPlus_JtiTimeLogCsv` in conjunction with each other. --- src/jit/compiler.cpp | 35 ++++++++++--- src/jit/compiler.h | 10 +++- src/jit/compiler.hpp | 2 +- src/jit/compphases.h | 123 +++++++++++++++++++++++----------------------- src/jit/flowgraph.cpp | 31 ++++++++++++ src/jit/jitconfigvalues.h | 3 ++ 6 files changed, 134 insertions(+), 70 deletions(-) diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index 613e8ee..9b19a6d 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -7218,29 +7218,34 @@ double JitTimer::s_cyclesPerSec = CycleTimer::CyclesPerSecond(); #if defined(FEATURE_JIT_METHOD_PERF) || DUMP_FLOWGRAPHS || defined(FEATURE_TRACELOGGING) const char* PhaseNames[] = { -#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) string_nm, +#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) string_nm, #include "compphases.h" }; const char* PhaseEnums[] = { -#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) #enum_nm, +#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) #enum_nm, #include "compphases.h" }; const LPCWSTR PhaseShortNames[] = { -#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) W(short_nm), +#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) W(short_nm), #include "compphases.h" }; #endif // defined(FEATURE_JIT_METHOD_PERF) || DUMP_FLOWGRAPHS #ifdef FEATURE_JIT_METHOD_PERF bool PhaseHasChildren[] = { -#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) hasChildren, +#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) hasChildren, #include "compphases.h" }; int PhaseParent[] = { -#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) parent, +#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) parent, +#include "compphases.h" +}; + +bool PhaseReportsIRSize[] = { +#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) measureIR, #include "compphases.h" }; @@ -7648,7 +7653,7 @@ JitTimer::JitTimer(unsigned byteCodeSize) : m_info(byteCodeSize) } } -void JitTimer::EndPhase(Phases phase) +void JitTimer::EndPhase(Compiler* compiler, Phases phase) { // Otherwise... // We re-run some phases currently, so this following assert doesn't work. @@ -7699,6 +7704,15 @@ void JitTimer::EndPhase(Phases phase) m_curPhaseStart = threadCurCycles; } } + + if ((JitConfig.JitMeasureIR() != 0) && PhaseReportsIRSize[phase]) + { + m_info.m_nodeCountAfterPhase[phase] = compiler->fgMeasureIR(); + } + else + { + m_info.m_nodeCountAfterPhase[phase] = 0; + } } #ifdef DEBUG @@ -7820,6 +7834,10 @@ void JitTimer::PrintCsvHeader() for (int i = 0; i < PHASE_NUMBER_OF; i++) { fprintf(fp, "\"%s\",", PhaseNames[i]); + if (PhaseReportsIRSize[i]) + { + fprintf(fp, "\"Node Count After %s\",", PhaseNames[i]); + } } InlineStrategy::DumpCsvHeader(fp); @@ -7871,6 +7889,11 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp) totCycles += m_info.m_cyclesByPhase[i]; } fprintf(fp, "%I64u,", m_info.m_cyclesByPhase[i]); + + if (PhaseReportsIRSize[i]) + { + fprintf(fp, "%u,", m_info.m_nodeCountAfterPhase[i]); + } } comp->m_inlineStrategy->DumpCsvData(fp); diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 7c5565c..da36b3f 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -917,7 +917,7 @@ struct ArrayInfo // partition a compilation. enum Phases { -#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent) enum_nm, +#define CompPhaseNameMacro(enum_nm, string_nm, short_nm, hasChildren, parent, measureIR) enum_nm, #include "compphases.h" PHASE_NUMBER_OF }; @@ -952,6 +952,7 @@ struct CompTimeInfo static bool PhaseHasChildren[]; static int PhaseParent[]; + static bool PhaseReportsIRSize[]; unsigned m_byteCodeBytes; unsigned __int64 m_totalCycles; @@ -961,6 +962,9 @@ struct CompTimeInfo unsigned __int64 m_CLRinvokesByPhase[PHASE_NUMBER_OF]; unsigned __int64 m_CLRcyclesByPhase[PHASE_NUMBER_OF]; #endif + + unsigned m_nodeCountAfterPhase[PHASE_NUMBER_OF]; + // For better documentation, we call EndPhase on // non-leaf phases. We should also call EndPhase on the // last leaf subphase; obviously, the elapsed cycles between the EndPhase @@ -1077,7 +1081,7 @@ public: static void PrintCsvHeader(); // Ends the current phase (argument is for a redundant check). - void EndPhase(Phases phase); + void EndPhase(Compiler* compiler, Phases phase); #if MEASURE_CLRAPI_CALLS // Start and end a timed CLR API call. @@ -3470,6 +3474,8 @@ public: void fgInsertBBafter(BasicBlock* insertAfterBlk, BasicBlock* newBlk); void fgUnlinkBlock(BasicBlock* block); + unsigned fgMeasureIR(); + #if OPT_BOOL_OPS // Used to detect multiple logical "not" assignments. bool fgMultipleNots; #endif diff --git a/src/jit/compiler.hpp b/src/jit/compiler.hpp index 6baf601..beb3c79 100644 --- a/src/jit/compiler.hpp +++ b/src/jit/compiler.hpp @@ -4450,7 +4450,7 @@ inline void Compiler::EndPhase(Phases phase) #if defined(FEATURE_JIT_METHOD_PERF) if (pCompJitTimer != nullptr) { - pCompJitTimer->EndPhase(phase); + pCompJitTimer->EndPhase(this, phase); } #endif #if DUMP_FLOWGRAPHS diff --git a/src/jit/compphases.h b/src/jit/compphases.h index 5038d6e..d86b4c8 100644 --- a/src/jit/compphases.h +++ b/src/jit/compphases.h @@ -11,95 +11,96 @@ // corresponding array of string names of those phases. This include file undefines CompPhaseNameMacro // after the last use. // The arguments are: -// CompPhaseNameMacro(enumName, stringName, shortName, hasChildren, parent) +// CompPhaseNameMacro(enumName, stringName, shortName, hasChildren, parent, measureIR) // "enumName" is an Enumeration-style all-caps name. // "stringName" is a self-explanatory. // "shortName" is an abbreviated form for stringName // "hasChildren" is true if this phase is broken out into subphases. // (We should never do EndPhase on a phase that has children, only on 'leaf phases.') // "parent" is -1 for leaf phases, otherwise it is the "enumName" of the parent phase. +// "measureIR" is true for phases that generate a count of IR nodes during EndPhase when JitConfig.MeasureIR is true. // clang-format off -CompPhaseNameMacro(PHASE_PRE_IMPORT, "Pre-import", "PRE-IMP", false, -1) -CompPhaseNameMacro(PHASE_IMPORTATION, "Importation", "IMPORT", false, -1) -CompPhaseNameMacro(PHASE_POST_IMPORT, "Post-import", "POST-IMP", false, -1) -CompPhaseNameMacro(PHASE_MORPH_INIT, "Morph - Init", "MOR-INIT" ,false, -1) -CompPhaseNameMacro(PHASE_MORPH_INLINE, "Morph - Inlining", "MOR-INL", false, -1) -CompPhaseNameMacro(PHASE_MORPH_IMPBYREF, "Morph - ByRefs", "MOR-BYREF",false, -1) -CompPhaseNameMacro(PHASE_EMPTY_TRY, "Remove empty try", "EMPTYTRY", false, -1) -CompPhaseNameMacro(PHASE_EMPTY_FINALLY, "Remove empty finally", "EMPTYFIN", false, -1) -CompPhaseNameMacro(PHASE_CLONE_FINALLY, "Clone finally", "CLONEFIN", false, -1) -CompPhaseNameMacro(PHASE_STR_ADRLCL, "Morph - Structs/AddrExp", "MOR-STRAL",false, -1) -CompPhaseNameMacro(PHASE_MORPH_GLOBAL, "Morph - Global", "MOR-GLOB", false, -1) -CompPhaseNameMacro(PHASE_MORPH_END, "Morph - Finish", "MOR-END", false, -1) -CompPhaseNameMacro(PHASE_GS_COOKIE, "GS Cookie", "GS-COOK", false, -1) -CompPhaseNameMacro(PHASE_COMPUTE_PREDS, "Compute preds", "PREDS", false, -1) -CompPhaseNameMacro(PHASE_MARK_GC_POLL_BLOCKS, "Mark GC poll blocks", "GC-POLL", false, -1) -CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS, "Compute edge weights (1)", "EDG-WGT", false, -1) +CompPhaseNameMacro(PHASE_PRE_IMPORT, "Pre-import", "PRE-IMP", false, -1, false) +CompPhaseNameMacro(PHASE_IMPORTATION, "Importation", "IMPORT", false, -1, true) +CompPhaseNameMacro(PHASE_POST_IMPORT, "Post-import", "POST-IMP", false, -1, false) +CompPhaseNameMacro(PHASE_MORPH_INIT, "Morph - Init", "MOR-INIT" ,false, -1, false) +CompPhaseNameMacro(PHASE_MORPH_INLINE, "Morph - Inlining", "MOR-INL", false, -1, true) +CompPhaseNameMacro(PHASE_MORPH_IMPBYREF, "Morph - ByRefs", "MOR-BYREF",false, -1, false) +CompPhaseNameMacro(PHASE_EMPTY_TRY, "Remove empty try", "EMPTYTRY", false, -1, false) +CompPhaseNameMacro(PHASE_EMPTY_FINALLY, "Remove empty finally", "EMPTYFIN", false, -1, false) +CompPhaseNameMacro(PHASE_CLONE_FINALLY, "Clone finally", "CLONEFIN", false, -1, false) +CompPhaseNameMacro(PHASE_STR_ADRLCL, "Morph - Structs/AddrExp", "MOR-STRAL",false, -1, false) +CompPhaseNameMacro(PHASE_MORPH_GLOBAL, "Morph - Global", "MOR-GLOB", false, -1, false) +CompPhaseNameMacro(PHASE_MORPH_END, "Morph - Finish", "MOR-END", false, -1, true) +CompPhaseNameMacro(PHASE_GS_COOKIE, "GS Cookie", "GS-COOK", false, -1, false) +CompPhaseNameMacro(PHASE_COMPUTE_PREDS, "Compute preds", "PREDS", false, -1, false) +CompPhaseNameMacro(PHASE_MARK_GC_POLL_BLOCKS, "Mark GC poll blocks", "GC-POLL", false, -1, false) +CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS, "Compute edge weights (1, false)", "EDG-WGT", false, -1, false) #if FEATURE_EH_FUNCLETS -CompPhaseNameMacro(PHASE_CREATE_FUNCLETS, "Create EH funclets", "EH-FUNC", false, -1) +CompPhaseNameMacro(PHASE_CREATE_FUNCLETS, "Create EH funclets", "EH-FUNC", false, -1, false) #endif // FEATURE_EH_FUNCLETS -CompPhaseNameMacro(PHASE_OPTIMIZE_LAYOUT, "Optimize layout", "LAYOUT", false, -1) -CompPhaseNameMacro(PHASE_ALLOCATE_OBJECTS, "Allocate Objects", "ALLOC-OBJ",false, -1) -CompPhaseNameMacro(PHASE_OPTIMIZE_LOOPS, "Optimize loops", "LOOP-OPT", false, -1) -CompPhaseNameMacro(PHASE_CLONE_LOOPS, "Clone loops", "LP-CLONE", false, -1) -CompPhaseNameMacro(PHASE_UNROLL_LOOPS, "Unroll loops", "UNROLL", false, -1) -CompPhaseNameMacro(PHASE_HOIST_LOOP_CODE, "Hoist loop code", "LP-HOIST", false, -1) -CompPhaseNameMacro(PHASE_MARK_LOCAL_VARS, "Mark local vars", "MARK-LCL", false, -1) -CompPhaseNameMacro(PHASE_OPTIMIZE_BOOLS, "Optimize bools", "OPT-BOOL", false, -1) -CompPhaseNameMacro(PHASE_FIND_OPER_ORDER, "Find oper order", "OPER-ORD", false, -1) -CompPhaseNameMacro(PHASE_SET_BLOCK_ORDER, "Set block order", "BLK-ORD", false, -1) -CompPhaseNameMacro(PHASE_BUILD_SSA, "Build SSA representation", "SSA", true, -1) -CompPhaseNameMacro(PHASE_BUILD_SSA_TOPOSORT, "SSA: topological sort", "SSA-SORT", false, PHASE_BUILD_SSA) -CompPhaseNameMacro(PHASE_BUILD_SSA_DOMS, "SSA: Doms1", "SSA-DOMS", false, PHASE_BUILD_SSA) -CompPhaseNameMacro(PHASE_BUILD_SSA_LIVENESS, "SSA: liveness", "SSA-LIVE", false, PHASE_BUILD_SSA) -CompPhaseNameMacro(PHASE_BUILD_SSA_IDF, "SSA: IDF", "SSA-IDF", false, PHASE_BUILD_SSA) -CompPhaseNameMacro(PHASE_BUILD_SSA_INSERT_PHIS, "SSA: insert phis", "SSA-PHI", false, PHASE_BUILD_SSA) -CompPhaseNameMacro(PHASE_BUILD_SSA_RENAME, "SSA: rename", "SSA-REN", false, PHASE_BUILD_SSA) +CompPhaseNameMacro(PHASE_OPTIMIZE_LAYOUT, "Optimize layout", "LAYOUT", false, -1, false) +CompPhaseNameMacro(PHASE_ALLOCATE_OBJECTS, "Allocate Objects", "ALLOC-OBJ",false, -1, false) +CompPhaseNameMacro(PHASE_OPTIMIZE_LOOPS, "Optimize loops", "LOOP-OPT", false, -1, false) +CompPhaseNameMacro(PHASE_CLONE_LOOPS, "Clone loops", "LP-CLONE", false, -1, false) +CompPhaseNameMacro(PHASE_UNROLL_LOOPS, "Unroll loops", "UNROLL", false, -1, false) +CompPhaseNameMacro(PHASE_HOIST_LOOP_CODE, "Hoist loop code", "LP-HOIST", false, -1, false) +CompPhaseNameMacro(PHASE_MARK_LOCAL_VARS, "Mark local vars", "MARK-LCL", false, -1, false) +CompPhaseNameMacro(PHASE_OPTIMIZE_BOOLS, "Optimize bools", "OPT-BOOL", false, -1, false) +CompPhaseNameMacro(PHASE_FIND_OPER_ORDER, "Find oper order", "OPER-ORD", false, -1, false) +CompPhaseNameMacro(PHASE_SET_BLOCK_ORDER, "Set block order", "BLK-ORD", false, -1, true) +CompPhaseNameMacro(PHASE_BUILD_SSA, "Build SSA representation", "SSA", true, -1, false) +CompPhaseNameMacro(PHASE_BUILD_SSA_TOPOSORT, "SSA: topological sort", "SSA-SORT", false, PHASE_BUILD_SSA, false) +CompPhaseNameMacro(PHASE_BUILD_SSA_DOMS, "SSA: Doms1", "SSA-DOMS", false, PHASE_BUILD_SSA, false) +CompPhaseNameMacro(PHASE_BUILD_SSA_LIVENESS, "SSA: liveness", "SSA-LIVE", false, PHASE_BUILD_SSA, false) +CompPhaseNameMacro(PHASE_BUILD_SSA_IDF, "SSA: IDF", "SSA-IDF", false, PHASE_BUILD_SSA, false) +CompPhaseNameMacro(PHASE_BUILD_SSA_INSERT_PHIS, "SSA: insert phis", "SSA-PHI", false, PHASE_BUILD_SSA, false) +CompPhaseNameMacro(PHASE_BUILD_SSA_RENAME, "SSA: rename", "SSA-REN", false, PHASE_BUILD_SSA, false) -CompPhaseNameMacro(PHASE_EARLY_PROP, "Early Value Propagation", "ERL-PROP", false, -1) -CompPhaseNameMacro(PHASE_VALUE_NUMBER, "Do value numbering", "VAL-NUM", false, -1) +CompPhaseNameMacro(PHASE_EARLY_PROP, "Early Value Propagation", "ERL-PROP", false, -1, false) +CompPhaseNameMacro(PHASE_VALUE_NUMBER, "Do value numbering", "VAL-NUM", false, -1, false) -CompPhaseNameMacro(PHASE_OPTIMIZE_INDEX_CHECKS, "Optimize index checks", "OPT-CHK", false, -1) +CompPhaseNameMacro(PHASE_OPTIMIZE_INDEX_CHECKS, "Optimize index checks", "OPT-CHK", false, -1, false) #if FEATURE_VALNUM_CSE -CompPhaseNameMacro(PHASE_OPTIMIZE_VALNUM_CSES, "Optimize Valnum CSEs", "OPT-CSE", false, -1) +CompPhaseNameMacro(PHASE_OPTIMIZE_VALNUM_CSES, "Optimize Valnum CSEs", "OPT-CSE", false, -1, false) #endif -CompPhaseNameMacro(PHASE_VN_COPY_PROP, "VN based copy prop", "CP-PROP", false, -1) +CompPhaseNameMacro(PHASE_VN_COPY_PROP, "VN based copy prop", "CP-PROP", false, -1, false) #if ASSERTION_PROP -CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop", "AST-PROP", false, -1) +CompPhaseNameMacro(PHASE_ASSERTION_PROP_MAIN, "Assertion prop", "AST-PROP", false, -1, false) #endif -CompPhaseNameMacro(PHASE_UPDATE_FLOW_GRAPH, "Update flow graph", "UPD-FG", false, -1) -CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2)", "EDG-WGT2", false, -1) -CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", "COLD-BLK", false, -1) -CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", "RAT", false, -1) -CompPhaseNameMacro(PHASE_SIMPLE_LOWERING, "Do 'simple' lowering", "SMP-LWR", false, -1) +CompPhaseNameMacro(PHASE_UPDATE_FLOW_GRAPH, "Update flow graph", "UPD-FG", false, -1, false) +CompPhaseNameMacro(PHASE_COMPUTE_EDGE_WEIGHTS2, "Compute edge weights (2, false)", "EDG-WGT2", false, -1, false) +CompPhaseNameMacro(PHASE_DETERMINE_FIRST_COLD_BLOCK, "Determine first cold block", "COLD-BLK", false, -1, true) +CompPhaseNameMacro(PHASE_RATIONALIZE, "Rationalize IR", "RAT", false, -1, false) +CompPhaseNameMacro(PHASE_SIMPLE_LOWERING, "Do 'simple' lowering", "SMP-LWR", false, -1, false) -CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", "LIVENESS", true, -1) -CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INIT, "Local var liveness init", "LIV-INIT", false, PHASE_LCLVARLIVENESS) -CompPhaseNameMacro(PHASE_LCLVARLIVENESS_PERBLOCK,"Per block local var liveness", "LIV-BLK", false, PHASE_LCLVARLIVENESS) -CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INTERBLOCK, "Global local var liveness", "LIV-GLBL", false, PHASE_LCLVARLIVENESS) +CompPhaseNameMacro(PHASE_LCLVARLIVENESS, "Local var liveness", "LIVENESS", true, -1, false) +CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INIT, "Local var liveness init", "LIV-INIT", false, PHASE_LCLVARLIVENESS, false) +CompPhaseNameMacro(PHASE_LCLVARLIVENESS_PERBLOCK,"Per block local var liveness", "LIV-BLK", false, PHASE_LCLVARLIVENESS, false) +CompPhaseNameMacro(PHASE_LCLVARLIVENESS_INTERBLOCK, "Global local var liveness", "LIV-GLBL", false, PHASE_LCLVARLIVENESS, false) #ifdef LEGACY_BACKEND -CompPhaseNameMacro(PHASE_RA_ASSIGN_VARS, "RA assign vars", "REGALLOC", false, -1) +CompPhaseNameMacro(PHASE_RA_ASSIGN_VARS, "RA assign vars", "REGALLOC", false, -1, false) #endif // LEGACY_BACKEND -CompPhaseNameMacro(PHASE_LOWERING_DECOMP, "Lowering decomposition", "LWR-DEC", false, -1) -CompPhaseNameMacro(PHASE_LOWERING, "Lowering nodeinfo", "LWR-INFO", false, -1) +CompPhaseNameMacro(PHASE_LOWERING_DECOMP, "Lowering decomposition", "LWR-DEC", false, -1, false) +CompPhaseNameMacro(PHASE_LOWERING, "Lowering nodeinfo", "LWR-INFO", false, -1, true) #ifndef LEGACY_BACKEND -CompPhaseNameMacro(PHASE_LINEAR_SCAN, "Linear scan register alloc", "LSRA", true, -1) -CompPhaseNameMacro(PHASE_LINEAR_SCAN_BUILD, "LSRA build intervals", "LSRA-BLD", false, PHASE_LINEAR_SCAN) -CompPhaseNameMacro(PHASE_LINEAR_SCAN_ALLOC, "LSRA allocate", "LSRA-ALL", false, PHASE_LINEAR_SCAN) -CompPhaseNameMacro(PHASE_LINEAR_SCAN_RESOLVE, "LSRA resolve", "LSRA-RES", false, PHASE_LINEAR_SCAN) +CompPhaseNameMacro(PHASE_LINEAR_SCAN, "Linear scan register alloc", "LSRA", true, -1, true) +CompPhaseNameMacro(PHASE_LINEAR_SCAN_BUILD, "LSRA build intervals", "LSRA-BLD", false, PHASE_LINEAR_SCAN, false) +CompPhaseNameMacro(PHASE_LINEAR_SCAN_ALLOC, "LSRA allocate", "LSRA-ALL", false, PHASE_LINEAR_SCAN, false) +CompPhaseNameMacro(PHASE_LINEAR_SCAN_RESOLVE, "LSRA resolve", "LSRA-RES", false, PHASE_LINEAR_SCAN, false) #endif // !LEGACY_BACKEND -CompPhaseNameMacro(PHASE_GENERATE_CODE, "Generate code", "CODEGEN", false, -1) -CompPhaseNameMacro(PHASE_EMIT_CODE, "Emit code", "EMIT", false, -1) -CompPhaseNameMacro(PHASE_EMIT_GCEH, "Emit GC+EH tables", "EMT-GCEH", false, -1) +CompPhaseNameMacro(PHASE_GENERATE_CODE, "Generate code", "CODEGEN", false, -1, false) +CompPhaseNameMacro(PHASE_EMIT_CODE, "Emit code", "EMIT", false, -1, false) +CompPhaseNameMacro(PHASE_EMIT_GCEH, "Emit GC+EH tables", "EMT-GCEH", false, -1, false) #if MEASURE_CLRAPI_CALLS // The following is a "pseudo-phase" - it aggregates timing info // for calls through ICorJitInfo across all "real" phases. -CompPhaseNameMacro(PHASE_CLR_API, "CLR API calls", "CLR-API", false, -1) +CompPhaseNameMacro(PHASE_CLR_API, "CLR API calls", "CLR-API", false, -1, false) #endif // clang-format on diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index 50318b0..95a4611 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -24256,3 +24256,34 @@ void Compiler::fgTransformFatCalli() CheckNoFatPointerCandidatesLeft(); #endif } + +//------------------------------------------------------------------------ +// fgMeasureIR: count and return the number of IR nodes in the function. +// +unsigned Compiler::fgMeasureIR() +{ + unsigned nodeCount = 0; + + for (BasicBlock* block = fgFirstBB; block != nullptr; block = block->bbNext) + { + if (!block->IsLIR()) + { + for (GenTreeStmt* stmt = block->firstStmt(); stmt != nullptr; stmt = stmt->getNextStmt()) + { + fgWalkTreePre(&stmt->gtStmtExpr, [](GenTree** slot, fgWalkData* data) -> Compiler::fgWalkResult { + (*reinterpret_cast(data->pCallbackData))++; + return Compiler::WALK_CONTINUE; + }, &nodeCount); + } + } + else + { + for (GenTree* node : LIR::AsRange(block)) + { + nodeCount++; + } + } + } + + return nodeCount; +} diff --git a/src/jit/jitconfigvalues.h b/src/jit/jitconfigvalues.h index ea6a3aa..a3e30de 100644 --- a/src/jit/jitconfigvalues.h +++ b/src/jit/jitconfigvalues.h @@ -258,6 +258,9 @@ CONFIG_STRING(AltJitExcludeAssemblies, W("AltJitExcludeAssemblies")) // Do not use AltJit on this semicolon-delimited list of assemblies. #endif // defined(ALT_JIT) +CONFIG_INTEGER(JitMeasureIR, W("JitMeasureIR"), 0) // If set, measure the IR size after some phases and report it in + // the time log. + CONFIG_STRING(JitFuncInfoFile, W("JitFuncInfoLogFile")) // If set, gather JIT function info and write to this file. CONFIG_STRING(JitTimeLogCsv, W("JitTimeLogCsv")) // If set, gather JIT throughput data and write to a CSV file. This // mode must be used in internal retail builds. -- 2.7.4