public static LocationUsage ForTree(Node Node, bool TopIsDef) { LocationUsage LocationUsage = new LocationUsage(); LocationUsage.TraverseTree(Node, TopIsDef, false); return(LocationUsage); }
public LocDef(BasicBlock BasicBlock, Instruction Instruction, Location DefinedLocation, Node Node) { this.BasicBlock = BasicBlock; this.Instruction = Instruction; this.Node = Node; this.UsedLocations = LocationUsage.ForTree(Node, false).UsedLocations; this.SelfRef = this.UsedLocations.Contains(DefinedLocation); }
public static LocationUsage ForInstruction(Instruction Instruction, Dictionary <System.Reflection.MethodInfo, HlGraphEntry> RelatedGraphs) { LocationUsage LocationUsage = new LocationUsage(); LocationUsage.RelatedGraphs = RelatedGraphs; LocationUsage.TraverseTree(Instruction.Argument, false, false); LocationUsage.TraverseTree(Instruction.Result, true, false); return(LocationUsage); }
/// <summary> /// Get list of dead definitions at the point right before a specified instruction. /// </summary> /// <param name="BasicBlock">Basic block.</param> /// <param name="Index">Index of target instruction.</param> /// <param name="DeadDefinitionList">Optional. List of dead definitions at the end of the basic block.</param> /// <returns>List of dead definitions before instruction with specified <paramref name="Index"/>.</returns> public static LocationList BeforeInstruction(BasicBlock BasicBlock, int Index, LocationList DeadDefinitionList) { if (Index < 0) { throw new ArgumentOutOfRangeException("Index"); } if (DeadDefinitionList == null) { DeadDefinitionList = new LocationList(); } else { DeadDefinitionList = new LocationList(DeadDefinitionList); } for (int i = BasicBlock.Instructions.Count - 1; i >= Index; i--) { Instruction Instruction = BasicBlock.Instructions[i]; LocationUsage LocationUsage = LocationUsage.ForInstruction(Instruction); foreach (Location Location in LocationUsage.DefinedLocations) { if (Location.LocationType == LocationType.CilStack || Location.LocationType == LocationType.LocalVariable || Location.LocationType == LocationType.Argument) { DeadDefinitionList.Add(Location); } } foreach (Location Location in LocationUsage.UsedLocations) { if (Location.LocationType == LocationType.CilStack || Location.LocationType == LocationType.LocalVariable || Location.LocationType == LocationType.Argument) { DeadDefinitionList.Remove(Location); } } } return(DeadDefinitionList); }
private static bool ForBlock(BasicBlock BasicBlock, ref List <Location> DeadDefinitionList) { if (DeadDefinitionList == null) { DeadDefinitionList = new List <Location>(); } bool InstructionsDeleted = false; for (int i = BasicBlock.Instructions.Count - 1; i >= 0; i--) { Instruction Instruction = BasicBlock.Instructions[i]; bool IsDeadAssignment = false; if (Instruction.InstructionType == InstructionType.Assignment && Instruction.Result != null && Instruction.Result.NodeType == NodeType.Location) { Location Location = ((LocationNode)Instruction.Result).Location; // Work around default equality check for stack locations. We only // care about the stack index, not the data type here... if (Location.LocationType == LocationType.CilStack) { foreach (Location Other in DeadDefinitionList) { if (Other.LocationType == LocationType.CilStack && ((StackLocation)Other).Index == ((StackLocation)Location).Index) { IsDeadAssignment = true; break; } } } else if (DeadDefinitionList.Contains(Location)) { IsDeadAssignment = true; } } // TODO: check for side effects... if (IsDeadAssignment && HasSideEffects(Instruction.Argument)) { Instruction.Result = null; } else if (IsDeadAssignment) { BasicBlock.Instructions.RemoveAt(i); InstructionsDeleted = true; continue; } LocationUsage LocationUsage = LocationUsage.ForInstruction(Instruction); foreach (Location Location in LocationUsage.DefinedLocations) { if (!DeadDefinitionList.Contains(Location)) { DeadDefinitionList.Add(Location); } } foreach (Location Location in LocationUsage.UsedLocations) { DeadDefinitionList.Remove(Location); } } return(InstructionsDeleted); }
/// <summary> /// Perform intra-block copy propagation. /// </summary> /// <param name="Graph">HlGraph.</param> /// <returns>TRUE if any changes have occured, FALSE otherwise.</returns> public static bool Do(HlGraph Graph) { bool Changed = false; CpState State = new CpState(); Dictionary <Location, LocDef> InsertedDict = new Dictionary <Location, LocDef>(); List <Location> RemoveKeys = new List <Location>(); List <KeyValuePair <Location, LocDef> > NewDefs = new List <KeyValuePair <Location, LocDef> >(); // // Get the list of undefined locations at the end of each basic block // DataFlow <LocationList> .Result DfResult = DeadAssignmentElimination.DoDF(Graph); // // Iterate through basic blocks // foreach (BasicBlock BB in Graph.BasicBlocks) { // // Iterate through instructions // State.Defs.Clear(); for (int InstructionIndex = 0; InstructionIndex < BB.Instructions.Count; InstructionIndex++) { Instruction Instruction = BB.Instructions[InstructionIndex]; // // Query lists of used and defined locations for the current instruction. If it uses // a location that is present in the CpState, the definition can only be pasted if: // // 1) The definition is not of the form "x := f(..., x, ...)"; i.e., the location // does not depend on an equally-named one at the defining site, // // OR // // 2) The definition is of the form "x := f(..., x, ...)", and the definition is dead after // the current instruction. // // NOTE: Pasting the definition in case (2) duplicates evaluation of "f" at the current // instruction, as dead assignment elimination will not be able to remove the original // defining site due to location x being used here. Therefore, in this case, we need to // remove the instruction itself if the definition is pasted, but we can only do so if the // value is not used afterwards. // LocationUsage LocationUsage = LocationUsage.ForInstruction(Instruction); foreach (Location Location in LocationUsage.UsedLocations) { LocDef LocDef; if (State.Defs.TryGetValue(Location, out LocDef) && LocDef.SelfRef) { LocationList DeadList = DeadAssignmentElimination.BeforeInstruction(BB, InstructionIndex + 1, DfResult.ExitState[BB]); if (!DeadList.Contains(Location)) { State.Defs.Remove(Location); } } } // // Rewrite trees // Instruction.Argument = ForTree(BB, Instruction, State, Instruction.Argument, false, ref Changed, InsertedDict); Instruction.Result = ForTree(BB, Instruction, State, Instruction.Result, true, ref Changed, InsertedDict); // // Change CpState to reflect any newly defined locations // foreach (Location Location in LocationUsage.DefinedLocations) { State.Defs.Remove(Location); if (Location.LocationType == LocationType.CilStack || Location.LocationType == LocationType.LocalVariable) { System.Diagnostics.Debug.Assert(Instruction.InstructionType == InstructionType.Assignment); if (Instruction.Result != null && Instruction.Result.NodeType == NodeType.Location) { LocDef NewLocDef = new LocDef(BB, Instruction, Location, Instruction.Argument); NewDefs.Add(new KeyValuePair <Location, LocDef>(Location, NewLocDef)); } } // // Remove other definition entries that have been invalidated by redefining one of their inputs // foreach (KeyValuePair <Location, LocDef> Entry in State.Defs) { if (Entry.Value.UsedLocations.Contains(Location)) { RemoveKeys.Add(Entry.Key); } } } // // Remove and add entries to CpState as necessary // if (RemoveKeys != null && RemoveKeys.Count != 0) { foreach (Location RemoveLocation in RemoveKeys) { State.Defs.Remove(RemoveLocation); } RemoveKeys.Clear(); } if (NewDefs != null && NewDefs.Count != 0) { foreach (KeyValuePair <Location, LocDef> Entry in NewDefs) { State.Defs.Add(Entry.Key, Entry.Value); } NewDefs.Clear(); } // // Remove instructions at defining sites that have become obsolete. This is only // true for CilStack locations, as they are the only ones guaranteed to be consumed // at most once. All other obsolete instructions are taken care of by dead code // elimination. // // BUGBUG: this fails for the DUP instruction... // if (InsertedDict.Count != 0 && LocationUsage.UsedLocations.Count != 0) { foreach (Location Location in LocationUsage.UsedLocations) { LocDef RemoveLocDef; if (Location.LocationType == LocationType.CilStack && InsertedDict.TryGetValue(Location, out RemoveLocDef)) { bool OK = RemoveLocDef.BasicBlock.Instructions.Remove(RemoveLocDef.Instruction); //System.Diagnostics.Debug.Assert(OK); System.Diagnostics.Debug.Assert(object.ReferenceEquals(RemoveLocDef.BasicBlock, BB)); if (object.ReferenceEquals(RemoveLocDef.BasicBlock, BB) && OK) { System.Diagnostics.Debug.Assert(object.ReferenceEquals(BB.Instructions[InstructionIndex - 1], Instruction)); InstructionIndex--; } } } } InsertedDict.Clear(); } } return(Changed); }