Beispiel #1
0
        /// <inheritdoc/>
        public ValueLiveness Analyze(FlowGraph graph)
        {
            var liveness = new Dictionary <BasicBlockTag, BlockLiveness>();

            // First create liveness data for blocks in isolation.
            foreach (var block in graph.BasicBlocks)
            {
                liveness[block.Tag] = BlockLiveness.Create(block);
            }

            var preds = graph.GetAnalysisResult <BasicBlockPredecessors>();

            // Then propagate imports until a fixpoint is reached.
            // The idea is to create a worklist of basic blocks that
            // still need to be processed.
            var worklist = new Queue <BasicBlockTag>(graph.BasicBlockTags);
            var workset  = new HashSet <BasicBlockTag>(graph.BasicBlockTags);

            while (worklist.Count > 0)
            {
                // Dequeue a block from the worklist.
                var blockTag = worklist.Dequeue();
                workset.Remove(blockTag);

                var blockData = liveness[blockTag];

                // Propagate imports to predecessors.
                foreach (var predTag in preds.GetPredecessorsOf(blockTag))
                {
                    // Every predecessor must export each and every one of the
                    // block's imports.
                    var predData = liveness[predTag];
                    foreach (var import in blockData.Imports)
                    {
                        // Have the predecessor export the imported value.
                        if (predData.Export(import))
                        {
                            // The predecessor block doesn't define the imported value
                            // and hence also had to import the imported value. Add the
                            // predecessor block to the worklist.
                            if (workset.Add(predTag))
                            {
                                worklist.Enqueue(predTag);
                            }
                        }
                    }
                }
            }

            return(new ValueLiveness(liveness));
        }
Beispiel #2
0
        /// <summary>
        /// Creates block liveness data for a particular block.
        /// Live and dead positions are recorded for all definitions
        /// and uses in the block.
        /// </summary>
        /// <param name="block">The block to analyze.</param>
        /// <returns>
        /// Block liveness data for a single block.
        /// </returns>
        internal static BlockLiveness Create(BasicBlock block)
        {
            var result = new BlockLiveness(block);

            // Mark parameters as defined here.
            foreach (var parameter in block.Parameters)
            {
                result.livePositions.Add(parameter.Tag, ParameterIndex);
                result.deadPositions.Add(parameter.Tag, ParameterIndex);
            }

            // Mark instructions as defined here, use their arguments.
            foreach (var selection in block.NamedInstructions)
            {
                result.livePositions.Add(selection.Tag, selection.InstructionIndex);
                result.deadPositions.Add(selection.Tag, selection.InstructionIndex);

                foreach (var argTag in selection.Instruction.Arguments)
                {
                    result.UseAt(argTag, selection.InstructionIndex);
                }
            }

            int insnCount = block.InstructionTags.Count;

            foreach (var flowInsn in block.Flow.Instructions)
            {
                foreach (var argTag in flowInsn.Arguments)
                {
                    result.UseAt(argTag, insnCount);
                }
                insnCount++;
            }

            foreach (var branch in block.Flow.Branches)
            {
                foreach (var arg in branch.Arguments)
                {
                    if (arg.IsValue)
                    {
                        result.Export(arg.ValueOrNull);
                    }
                }
            }

            return(result);
        }