/// <summary> /// Compues the liveness for the given control flow graph /// </summary> /// <param name="controlFlowGraph">The control flow graph</param> public static IList<LiveInterval> ComputeLiveness(VirtualControlFlowGraph controlFlowGraph) { var liveIntervals = new List<LiveInterval>(); var virtualRegisters = GetVirtualRegisters(controlFlowGraph); //Get the register usage IDictionary<VirtualRegister, IList<UsageSite>> useSites; IDictionary<VirtualRegister, IList<UsageSite>> assignSites; GetRegisterUsage(controlFlowGraph, out useSites, out assignSites); //Get the backflow graph var backflowGraph = GetBackflow(controlFlowGraph); //Perform the analysis for one register at a time foreach (var reg in virtualRegisters) { IList<UsageSite> registerUseSites; if (useSites.TryGetValue(reg, out registerUseSites)) { var aliveAt = new HashSet<int>(); ComputeLiveness(backflowGraph, reg, registerUseSites, aliveAt); liveIntervals.Add(GetLiveInterval(reg, aliveAt)); } else { //This mean that the register is not used. Atm, we do not remove write-only virtual registers. //So we need to compute the liveness information, else there won't exist any liveness information for the register. var aliveAt = new HashSet<int>(); foreach (var assignSite in assignSites[reg]) { aliveAt.ElementAt(assignSite.Block.StartOffset + assignSite.Offset); } liveIntervals.Add(GetLiveInterval(reg, aliveAt)); } } return liveIntervals; }
/// <summary> /// Returns the virtual register usage from the registers in the given control flow graph /// </summary> /// <param name="controlFlowGraph">The control flow graph</param> /// <param name="useSites">The use sites</param> /// <param name="assignSites">The assign sites</param> private static void GetRegisterUsage(VirtualControlFlowGraph controlFlowGraph, out IDictionary<VirtualRegister, IList<UsageSite>> useSites, out IDictionary<VirtualRegister, IList<UsageSite>> assignSites) { useSites = new Dictionary<VirtualRegister, IList<UsageSite>>(); assignSites = new Dictionary<VirtualRegister, IList<UsageSite>>(); foreach (var block in controlFlowGraph.Vertices) { int offset = 0; foreach (var instruction in block.Instructions) { if (instruction.AssignRegister != null) { var register = instruction.AssignRegister.Value; IList<UsageSite> assigns; if (!useSites.TryGetValue(register, out assigns)) { assigns = new List<UsageSite>(); useSites.Add(register, assigns); } assigns.Add(new UsageSite() { Block = block, Offset = offset }); } foreach (var register in instruction.UsesRegisters) { IList<UsageSite> uses; if (!useSites.TryGetValue(register, out uses)) { uses = new List<UsageSite>(); useSites.Add(register, uses); } uses.Add(new UsageSite() { Block = block, Offset = offset }); } offset++; } } }
/// <summary> /// Computes the number of virtual registers in the given control flow graph /// </summary> /// <param name="controlFlowGraph">The control flow graph</param> private static int NumVirtualRegister(VirtualControlFlowGraph controlFlowGraph) { var virtualRegisters = new HashSet<VirtualRegister>(); foreach (var block in controlFlowGraph.Vertices) { foreach (var instruction in block.Instructions) { if (instruction.AssignRegister.HasValue) { virtualRegisters.Add(instruction.AssignRegister.Value); } foreach (var register in instruction.UsesRegisters) { virtualRegisters.Add(register); } } } return virtualRegisters.Count; }
/// <summary> /// Returns the backflow for the given control flow graph /// </summary> /// <param name="controlFlowGraph">The control flow graph</param> private static BackflowGraph GetBackflow(VirtualControlFlowGraph controlFlowGraph) { var backflowEdges = new Dictionary<VirtualBasicBlock, ISet<VirtualBasicBlock>>(); foreach (var edgeList in controlFlowGraph.NeighborLists.Values) { foreach (var edge in edgeList) { ISet<VirtualBasicBlock> edges; if (!backflowEdges.TryGetValue(edge.To, out edges)) { edges = new HashSet<VirtualBasicBlock>(); backflowEdges.Add(edge.To, edges); } edges.Add(edge.From); } } return new BackflowGraph() { Edges = backflowEdges }; }