From 30e36c89b3defbf2e4f212456dc0d33406574262 Mon Sep 17 00:00:00 2001 From: Bruce Forstall Date: Fri, 30 Jun 2017 23:04:14 -0700 Subject: [PATCH] Improve fgAddRefPred (dotnet/coreclr#12585) * Improve fgAddRefPred Only do one search through the predecessor list looking for an existing predecessor edge, or looking for the proper location to insert a new predecessor edge. Previously, we traversed the list twice (or part of twice) for new edges. For new edges, stop the search when we reach the correct location in sorted order. This reduces x86 release minopts instruction count by 0.42% and full opts instruction count by 0.33% (of a superpmi replay of the tests). Fixes dotnet/coreclr#12582 * Update for feedback Commit migrated from https://github.com/dotnet/coreclr/commit/58d0ead6d34837fab60da1473090588db415fc1d --- src/coreclr/src/jit/flowgraph.cpp | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/coreclr/src/jit/flowgraph.cpp b/src/coreclr/src/jit/flowgraph.cpp index 9878c69..6f50afd 100644 --- a/src/coreclr/src/jit/flowgraph.cpp +++ b/src/coreclr/src/jit/flowgraph.cpp @@ -1044,10 +1044,28 @@ flowList* Compiler::fgAddRefPred(BasicBlock* block, assert(!fgCheapPredsValid); - flowList* flow = fgGetPredForBlock(block, blockPred); + flowList* flow; - if (flow) + // Keep the predecessor list in lowest to highest bbNum order. This allows us to discover the loops in + // optFindNaturalLoops from innermost to outermost. + // + // TODO-Throughput: Inserting an edge for a block in sorted order requires searching every existing edge. + // Thus, inserting all the edges for a block is quadratic in the number of edges. We need to either + // not bother sorting for debuggable code, or sort in optFindNaturalLoops, or better, make the code in + // optFindNaturalLoops not depend on order. This also requires ensuring that nobody else has taken a + // dependency on this order. Note also that we don't allow duplicates in the list; we maintain a flDupCount + // count of duplication. This also necessitates walking the flow list for every edge we add. + + flowList** listp = &block->bbPreds; + while ((*listp != nullptr) && ((*listp)->flBlock->bbNum < blockPred->bbNum)) + { + listp = &(*listp)->flNext; + } + + if ((*listp != nullptr) && ((*listp)->flBlock == blockPred)) { + // The predecessor block already exists in the flow list; simply add to its duplicate count. + flow = *listp; noway_assert(flow->flDupCount > 0); flow->flDupCount++; } @@ -1063,21 +1081,7 @@ flowList* Compiler::fgAddRefPred(BasicBlock* block, // Any changes to the flow graph invalidate the dominator sets. fgModified = true; - // Keep the predecessor list in lowest to highest bbNum order - // This allows us to discover the loops in optFindNaturalLoops - // from innermost to outermost. - - // TODO-Throughput: This search is quadratic if you have many jumps - // to the same target. We need to either not bother sorting for - // debuggable code, or sort in optFindNaturalLoops, or better, make - // the code in optFindNaturalLoops not depend on order. - - flowList** listp = &block->bbPreds; - while (*listp && ((*listp)->flBlock->bbNum < blockPred->bbNum)) - { - listp = &(*listp)->flNext; - } - + // Insert the new edge in the list in the correct ordered location. flow->flNext = *listp; *listp = flow; -- 2.7.4