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