Example #1
0
        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);
                }
            }
        }
Example #2
0
        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);
                }
            }
        }