private void RunCore(
     ControlFlowGraph cfg,
     SortedSet <int> worklist,
     SortedSet <int> pendingBlocksNeedingAtLeastOnePass,
     TAnalysisData initialAnalysisDataOpt,
     DataFlowAnalysisResultBuilder <TAnalysisData> resultBuilder,
     PooledHashSet <BasicBlock> uniqueSuccessors,
     PooledDictionary <int, List <BranchWithInfo> > finallyBlockSuccessorsMap,
     PooledDictionary <ControlFlowRegion, TAnalysisData> catchBlockInputDataMap,
     PooledDictionary <int, TAnalysisData> inputDataFromInfeasibleBranchesMap,
     PooledDictionary <int, (int Ordinal, ControlFlowConditionKind BranchKind)?> blockToUniqueInputFlowMap,
        private TAnalysisResult Run(TAnalysisContext analysisContext)
        {
            var cfg              = analysisContext.ControlFlowGraph;
            var resultBuilder    = new DataFlowAnalysisResultBuilder <TAnalysisData>();
            var uniqueSuccessors = PooledHashSet <BasicBlock> .GetInstance();

            var finallyBlockSuccessorsMap = PooledDictionary <int, List <BranchWithInfo> > .GetInstance();

            var catchBlockInputDataMap = PooledDictionary <ControlFlowRegion, TAnalysisData> .GetInstance();

            var inputDataFromInfeasibleBranchesMap = PooledDictionary <int, TAnalysisData> .GetInstance();

            var unreachableBlocks = PooledHashSet <int> .GetInstance();

            var worklist = new SortedSet <int>();
            var pendingBlocksNeedingAtLeastOnePass = new SortedSet <int>(cfg.Blocks.Select(b => b.Ordinal));

            // Map from Ordinal -> (Ordinal, ControlFlowConditionKind)? with following semantics:
            //  1. Key is a valid basic block ordinal.
            //  2. Value tuple indicates the following:
            //      a. Non-null tuple value: Indicates a unique branch entering the block, with following tuple values:
            //         i. Ordinal of the single unique block from which analysis data has been transferred into the Key,
            //            which is normally a predecessor but can be a non-predecessor block for finally/catch.
            //         ii. ControlFlowConditionKind indicating the nature of branch, i.e. conditional or fall through.
            //             This is required as CFG can have both conditional and fall through branches
            //             with the same source and destination blocks.
            //      b. Null tuple value: Block had analysis data flowing into it from multiple different branches.
            //
            //  This map allows us to optimize the number of merge operations. We can avoid merge and directly
            //  overwrite analysis data into a successor if successor block has no entry or entry with non-null tuple value
            //  with the matching input branch.
            var blockToUniqueInputFlowMap = PooledDictionary <int, (int Ordinal, ControlFlowConditionKind BranchKind)?> .GetInstance();

            // Map from basic block ordinals that are destination of back edge(s) to the minimum block ordinal that dominates it,
            // i.e. for every '{key, value}' pair in the dictionary, 'key' is the destination of at least one back edge
            // and 'value' is the minimum ordinal such that there is no back edge to 'key' from any basic block with ordinal > 'value'.
            var loopRangeMap = PooledDictionary <int, int> .GetInstance();

            ComputeLoopRangeMap(cfg, loopRangeMap);

            TAnalysisData normalPathsExitBlockData = null, exceptionPathsExitBlockDataOpt = null;

            try
            {
                // Add each basic block to the result.
                foreach (var block in cfg.Blocks)
                {
                    resultBuilder.Add(block);
                }

                var entry = cfg.GetEntry();

                // Initialize the input of the entry block.
                // For context sensitive inter-procedural analysis, use the provided initial analysis data.
                // Otherwise, initialize with the default bottom value of the analysis domain.
                var initialAnalysisDataOpt = analysisContext.InterproceduralAnalysisDataOpt?.InitialAnalysisData;
                UpdateInput(resultBuilder, entry, GetClonedAnalysisDataOrEmptyData(initialAnalysisDataOpt));

                // Add the block to the worklist.
                worklist.Add(entry.Ordinal);

                RunCore(cfg, worklist, pendingBlocksNeedingAtLeastOnePass, initialAnalysisDataOpt, resultBuilder,
                        uniqueSuccessors, finallyBlockSuccessorsMap, catchBlockInputDataMap, inputDataFromInfeasibleBranchesMap,
                        blockToUniqueInputFlowMap, loopRangeMap, exceptionPathsAnalysisPostPass: false);
                normalPathsExitBlockData = resultBuilder.ExitBlockOutputData;

                if (analysisContext.ExceptionPathsAnalysis)
                {
                    // Clone and save exit block data
                    normalPathsExitBlockData = AnalysisDomain.Clone(normalPathsExitBlockData);

                    OperationVisitor.ExecutingExceptionPathsAnalysisPostPass = true;
                    foreach (var block in cfg.Blocks)
                    {
                        blockToUniqueInputFlowMap[block.Ordinal] = null;

                        // Skip entry block analysis.
                        if (block.Kind == BasicBlockKind.Entry)
                        {
                            continue;
                        }

                        if (block.IsReachable)
                        {
                            worklist.Add(block.Ordinal);
                        }
                        else
                        {
                            pendingBlocksNeedingAtLeastOnePass.Add(block.Ordinal);
                        }
                    }

                    RunCore(cfg, worklist, pendingBlocksNeedingAtLeastOnePass, initialAnalysisDataOpt, resultBuilder, uniqueSuccessors,
                            finallyBlockSuccessorsMap, catchBlockInputDataMap, inputDataFromInfeasibleBranchesMap,
                            blockToUniqueInputFlowMap, loopRangeMap, exceptionPathsAnalysisPostPass: true);
                    exceptionPathsExitBlockDataOpt = resultBuilder.ExitBlockOutputData;
                    OperationVisitor.ExecutingExceptionPathsAnalysisPostPass = false;
                }

                var mergedDataForUnhandledThrowOperationsOpt = OperationVisitor.GetMergedDataForUnhandledThrowOperations();

                var dataflowAnalysisResult = resultBuilder.ToResult(ToBlockResult, OperationVisitor.GetStateMap(),
                                                                    OperationVisitor.GetPredicateValueKindMap(), OperationVisitor.GetReturnValueAndPredicateKind(), OperationVisitor.InterproceduralResultsMap,
                                                                    resultBuilder.EntryBlockOutputData, normalPathsExitBlockData, exceptionPathsExitBlockDataOpt,
                                                                    mergedDataForUnhandledThrowOperationsOpt, OperationVisitor.AnalysisDataForUnhandledThrowOperations, cfg, OperationVisitor.ValueDomain.UnknownOrMayBeValue);
                return(ToResult(analysisContext, dataflowAnalysisResult));
            }
            finally
            {
                resultBuilder.Dispose();
                uniqueSuccessors.Free();
                finallyBlockSuccessorsMap.Free();
                catchBlockInputDataMap.Values.Dispose();
                catchBlockInputDataMap.Free();
                inputDataFromInfeasibleBranchesMap.Values.Dispose();
                inputDataFromInfeasibleBranchesMap.Free();
                unreachableBlocks.Free();
                blockToUniqueInputFlowMap.Free();
                loopRangeMap.Free();
            }
        }