private static Node ForTree(BasicBlock BB, Instruction Instruction, CpState State, Node Node, bool TopIsDef, ref bool Changed, Dictionary <Location, LocDef> InsertedDict) { if (Node == null) { return(null); } if (!TopIsDef && Node.NodeType == NodeType.Location) { LocationNode LocationNode = (LocationNode)Node; LocDef LocDef; if (LocationNode.Location.LocationType == LocationType.CilStack && State.Defs.TryGetValue(LocationNode.Location, out LocDef)) { InsertedDict[LocationNode.Location] = LocDef; Changed = true; Node = LocDef.Node; } } else { for (int i = 0; i < Node.SubNodes.Count; i++) { Node SubNode = Node.SubNodes[i]; SubNode = ForTree(BB, Instruction, State, SubNode, (SubNode.NodeType == NodeType.AddressOf) ? true : false, ref Changed, InsertedDict); Node.SubNodes[i] = SubNode; } } return(Node); }
public static extern bool GetCpuStatusH(int ocbNum, out CpState pCpState);
/// <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); }