private void InitializeOptimal(AILBlock[] Graph, AILBlock Root) { //This will go through all possible paths on the graph, //and store all inputs/outputs for each block. A register //that was previously written to already is not considered an input. //When a block can be reached by more than one path, then the //output from all paths needs to be set for this block, and //only outputs present in all of the parent blocks can be considered //when doing input elimination. Each block chain have a root, that's where //the code starts executing. They are present on the subroutine start point, //and on call return points too (address written to X30 by BL). HashSet <BlockIo> Visited = new HashSet <BlockIo>(); Queue <BlockIo> Unvisited = new Queue <BlockIo>(); void Enqueue(BlockIo Block) { if (!Visited.Contains(Block)) { Unvisited.Enqueue(Block); Visited.Add(Block); } } Enqueue(new BlockIo() { Block = Root, Entry = Root }); while (Unvisited.Count > 0) { BlockIo Current = Unvisited.Dequeue(); Current.IntInputs |= Current.Block.IntInputs & ~Current.IntOutputs; Current.VecInputs |= Current.Block.VecInputs & ~Current.VecOutputs; Current.IntOutputs |= Current.Block.IntOutputs; Current.VecOutputs |= Current.Block.VecOutputs; //Check if this is a exit block //(a block that returns or calls another sub). if ((Current.Block.Next == null && Current.Block.Branch == null) || Current.Block.HasStateStore) { if (!IntPaths.TryGetValue(Current.Block, out PathIo IntPath)) { IntPaths.Add(Current.Block, IntPath = new PathIo()); } if (!VecPaths.TryGetValue(Current.Block, out PathIo VecPath)) { VecPaths.Add(Current.Block, VecPath = new PathIo()); } IntPath.Set(Current.Entry, Current.IntInputs, Current.IntOutputs); VecPath.Set(Current.Entry, Current.VecInputs, Current.VecOutputs); } void EnqueueFromCurrent(AILBlock Block, bool RetTarget) { BlockIo BlkIO = new BlockIo() { Block = Block }; if (RetTarget) { BlkIO.Entry = Block; } else { BlkIO.Entry = Current.Entry; BlkIO.IntInputs = Current.IntInputs; BlkIO.VecInputs = Current.VecInputs; BlkIO.IntOutputs = Current.IntOutputs; BlkIO.VecOutputs = Current.VecOutputs; } Enqueue(BlkIO); } if (Current.Block.Next != null) { EnqueueFromCurrent(Current.Block.Next, Current.Block.HasStateStore); } if (Current.Block.Branch != null) { EnqueueFromCurrent(Current.Block.Branch, false); } } }
public void BuildUses(ILBlock entry) { //This will go through all possible paths on the graph, //and store all inputs/outputs for each block. A register //that was previously written to already is not considered an input. //When a block can be reached by more than one path, then the //output from all paths needs to be set for this block, and //only outputs present in all of the parent blocks can be considered //when doing input elimination. Each block chain has a entry, that's where //the code starts executing. They are present on the subroutine start point, //and on call return points too (address written to X30 by BL). HashSet <BlockIo> visited = new HashSet <BlockIo>(); Queue <BlockIo> unvisited = new Queue <BlockIo>(); void Enqueue(BlockIo block) { if (visited.Add(block)) { unvisited.Enqueue(block); } } Enqueue(new BlockIo(entry, entry)); while (unvisited.Count > 0) { BlockIo current = unvisited.Dequeue(); current.IntInputs |= current.Block.IntInputs & ~current.IntOutputs; current.VecInputs |= current.Block.VecInputs & ~current.VecOutputs; current.IntOutputs |= current.Block.IntOutputs; current.VecOutputs |= current.Block.VecOutputs; //Check if this is a exit block //(a block that returns or calls another sub). if ((current.Block.Next == null && current.Block.Branch == null) || current.Block.HasStateStore) { if (!_intPaths.TryGetValue(current.Block, out PathIo intPath)) { _intPaths.Add(current.Block, intPath = new PathIo()); } if (!_vecPaths.TryGetValue(current.Block, out PathIo vecPath)) { _vecPaths.Add(current.Block, vecPath = new PathIo()); } intPath.Set(current.Entry, current.IntInputs, current.IntOutputs); vecPath.Set(current.Entry, current.VecInputs, current.VecOutputs); } void EnqueueFromCurrent(ILBlock block, bool retTarget) { BlockIo blockIo; if (retTarget) { blockIo = new BlockIo(block, block); } else { blockIo = new BlockIo( block, current.Entry, current.IntInputs, current.VecInputs, current.IntOutputs, current.VecOutputs); } Enqueue(blockIo); } if (current.Block.Next != null) { EnqueueFromCurrent(current.Block.Next, current.Block.HasStateStore); } if (current.Block.Branch != null) { EnqueueFromCurrent(current.Block.Branch, false); } } }