/// <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)); }
/// <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); }