From d43347e043beb3ae64c8db55f72708c1ce60511e Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Thu, 30 Aug 2018 08:01:46 -0700 Subject: JIT: don't compute edge weights if not optimizing (#19736) We were spending a bit less than 1% of jit time computing edge weights for minopts an debug codegen, but then never using them. Also when optimizing we wanted to just compute edge weights but ran through a bit more code than that. Restructure the code so it's clearer what runs when, and bypass the edge weight computations for minopts and debug codegen. --- src/jit/flowgraph.cpp | 190 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 116 insertions(+), 74 deletions(-) (limited to 'src/jit/flowgraph.cpp') diff --git a/src/jit/flowgraph.cpp b/src/jit/flowgraph.cpp index 872fc1d490..4a7a0ae5cc 100644 --- a/src/jit/flowgraph.cpp +++ b/src/jit/flowgraph.cpp @@ -12994,50 +12994,64 @@ bool Compiler::fgMightHaveLoop() return false; } -void Compiler::fgComputeEdgeWeights() +//------------------------------------------------------------- +// fgComputeBlockAndEdgeWeights: determine weights for blocks +// and optionally for edges +// +void Compiler::fgComputeBlockAndEdgeWeights() { -#ifdef DEBUG + JITDUMP("*************** In fgComputeBlockAndEdgeWeights()\n"); + + const bool usingProfileWeights = fgIsUsingProfileWeights(); + const bool isOptimizing = !opts.MinOpts() && !opts.compDbgCode; + + fgHaveValidEdgeWeights = false; + fgCalledCount = BB_UNITY_WEIGHT; + +#if DEBUG if (verbose) { - printf("*************** In fgComputeEdgeWeights()\n"); + fgDispBasicBlocks(); + printf("\n"); } #endif // DEBUG - if (fgIsUsingProfileWeights() == false) + const BasicBlock::weight_t returnWeight = fgComputeMissingBlockWeights(); + + if (usingProfileWeights) { -#ifdef DEBUG - if (verbose) - { - printf("fgComputeEdgeWeights() we do not have any profile data so we are not using the edge weights\n"); - } -#endif // DEBUG - fgHaveValidEdgeWeights = false; - fgCalledCount = BB_UNITY_WEIGHT; + fgComputeCalledCount(returnWeight); + } + else + { + JITDUMP(" -- no profile data, so using default called count\n"); } -#if DEBUG - if (verbose) + if (isOptimizing) { - fgDispBasicBlocks(); - printf("\n"); + fgComputeEdgeWeights(); } -#endif // DEBUG + else + { + JITDUMP(" -- not optimizing, so not computing edge weights\n"); + } +} - BasicBlock* bSrc; - BasicBlock* bDst; - flowList* edge; - unsigned iterations = 0; - unsigned goodEdgeCountCurrent = 0; - unsigned goodEdgeCountPrevious = 0; - bool inconsistentProfileData = false; - bool hasIncompleteEdgeWeights = false; - unsigned numEdges = 0; - bool usedSlop = false; - bool changed; - bool modified; +//------------------------------------------------------------- +// fgComputeMissingBlockWeights: determine weights for blocks +// that were not profiled and do not yet have weights. +// +// Returns: +// sum of weights for all return and throw blocks in the method +BasicBlock::weight_t Compiler::fgComputeMissingBlockWeights() +{ + BasicBlock* bSrc; + BasicBlock* bDst; + unsigned iterations = 0; + bool changed; + bool modified = false; BasicBlock::weight_t returnWeight; - BasicBlock::weight_t slop; // If we have any blocks that did not have profile derived weight // we will try to fix their weight up here @@ -13144,68 +13158,96 @@ void Compiler::fgComputeEdgeWeights() #if DEBUG if (verbose && modified) { - printf("fgComputeEdgeWeights() adjusted the weight of some blocks\n"); + printf("fgComputeMissingBlockWeights() adjusted the weight of some blocks\n"); fgDispBasicBlocks(); printf("\n"); } #endif + return returnWeight; +} + +//------------------------------------------------------------- +// fgComputeCalledCount: when profile information is in use, +// compute fgCalledCount +// +// Argument: +// returnWeight - sum of weights for all return and throw blocks + +void Compiler::fgComputeCalledCount(BasicBlock::weight_t returnWeight) +{ // When we are not using profile data we have already setup fgCalledCount // only set it here if we are using profile data - // - if (fgIsUsingProfileWeights()) - { - BasicBlock* firstILBlock = fgFirstBB; // The first block for IL code (i.e. for the IL code at offset 0) + assert(fgIsUsingProfileWeights()); - // Do we have an internal block as our first Block? - if (firstILBlock->bbFlags & BBF_INTERNAL) - { - // Skip past any/all BBF_INTERNAL blocks that may have been added before the first real IL block. - // - while (firstILBlock->bbFlags & BBF_INTERNAL) - { - firstILBlock = firstILBlock->bbNext; - } - // The 'firstILBlock' is now expected to have a profile-derived weight - assert(firstILBlock->hasProfileWeight()); - } + BasicBlock* firstILBlock = fgFirstBB; // The first block for IL code (i.e. for the IL code at offset 0) - // If the first block only has one ref then we use it's weight for fgCalledCount. - // Otherwise we have backedge's into the first block, so instead we use the sum - // of the return block weights for fgCalledCount. - // - // If the profile data has a 0 for the returnWeight - // (i.e. the function never returns because it always throws) - // then just use the first block weight rather than 0. + // Do we have an internal block as our first Block? + if (firstILBlock->bbFlags & BBF_INTERNAL) + { + // Skip past any/all BBF_INTERNAL blocks that may have been added before the first real IL block. // - if ((firstILBlock->countOfInEdges() == 1) || (returnWeight == 0)) - { - assert(firstILBlock->hasProfileWeight()); // This should always be a profile-derived weight - fgCalledCount = firstILBlock->bbWeight; - } - else + while (firstILBlock->bbFlags & BBF_INTERNAL) { - fgCalledCount = returnWeight; + firstILBlock = firstILBlock->bbNext; } + // The 'firstILBlock' is now expected to have a profile-derived weight + assert(firstILBlock->hasProfileWeight()); + } - // If we allocated a scratch block as the first BB then we need - // to set its profile-derived weight to be fgCalledCount - if (fgFirstBBisScratch()) + // If the first block only has one ref then we use it's weight for fgCalledCount. + // Otherwise we have backedge's into the first block, so instead we use the sum + // of the return block weights for fgCalledCount. + // + // If the profile data has a 0 for the returnWeight + // (i.e. the function never returns because it always throws) + // then just use the first block weight rather than 0. + // + if ((firstILBlock->countOfInEdges() == 1) || (returnWeight == 0)) + { + assert(firstILBlock->hasProfileWeight()); // This should always be a profile-derived weight + fgCalledCount = firstILBlock->bbWeight; + } + else + { + fgCalledCount = returnWeight; + } + + // If we allocated a scratch block as the first BB then we need + // to set its profile-derived weight to be fgCalledCount + if (fgFirstBBisScratch()) + { + fgFirstBB->setBBProfileWeight(fgCalledCount); + if (fgFirstBB->bbWeight == 0) { - fgFirstBB->setBBProfileWeight(fgCalledCount); - if (fgFirstBB->bbWeight == 0) - { - fgFirstBB->bbFlags |= BBF_RUN_RARELY; - } + fgFirstBB->bbFlags |= BBF_RUN_RARELY; } + } #if DEBUG - if (verbose) - { - printf("We are using the Profile Weights and fgCalledCount is %d.\n", fgCalledCount); - } -#endif + if (verbose) + { + printf("We are using the Profile Weights and fgCalledCount is %d.\n", fgCalledCount); } +#endif +} + +//------------------------------------------------------------- +// fgComputeEdgeWeights: compute edge weights from block weights + +void Compiler::fgComputeEdgeWeights() +{ + BasicBlock* bSrc; + BasicBlock* bDst; + flowList* edge; + BasicBlock::weight_t slop; + unsigned goodEdgeCountCurrent = 0; + unsigned goodEdgeCountPrevious = 0; + bool inconsistentProfileData = false; + bool hasIncompleteEdgeWeights = false; + bool usedSlop = false; + unsigned numEdges = 0; + unsigned iterations = 0; // Now we will compute the initial flEdgeWeightMin and flEdgeWeightMax values for (bDst = fgFirstBB; bDst != nullptr; bDst = bDst->bbNext) -- cgit v1.2.3