Beispiel #1
0
 public Instruction(IL.Instruction instr, IL.Function func)
 {
     ILInstruction = instr;
     ILFunction    = func;
     if (instr is IL.ReturnInstruction || instr is IL.CallInstruction)
     {
         Necessary = true;
     }
 }
 public void GenInstruction(IL.Instruction instr)
 {
     if (instr is IL.CallInstruction)
     {
         GenCall(instr as IL.CallInstruction);
     }
     else if (instr is IL.FunctionInstruction)
     {
         GenFunction(instr as IL.FunctionInstruction);
     }
     else if (instr is IL.MoveInstruction)
     {
         GenMove(instr as IL.MoveInstruction);
     }
     else if (instr is IL.ReturnInstruction)
     {
         GenReturn(instr as IL.ReturnInstruction);
     }
     else if (instr is IL.Label)
     {
         GenLabel(instr as IL.Label);
     }
     else if (instr is IL.UnconditionalJumpInstruction)
     {
         GenUnconditionalJump(instr as IL.UnconditionalJumpInstruction);
     }
     else if (instr is IL.ConditionalJumpInstruction)
     {
         GenConditionalJump(instr as IL.ConditionalJumpInstruction);
     }
     else if (instr is Optimization.TailCallInstruction)
     {
         GenTailCall(instr as Optimization.TailCallInstruction);
     }
     else
     {
         throw new NotImplementedException();
     }
 }
            public Graph(Function func)
            {
                NodeList = new List <Node>();

                Dictionary <IL.Instruction, Node> Map = new Dictionary <IL.Instruction, Node>();

                foreach (IL.Instruction instr in func.InstructionList)
                {
                    Node node = new Node(instr);
                    NodeList.Add(node);
                    Map[instr] = node;
                }

                // Calculate successors.
                for (int i = 0; i < func.InstructionList.Count; i++)
                {
                    IL.Instruction instr = func.InstructionList[i];
                    if (instr is IL.UnconditionalJumpInstruction uncondJump)
                    {
                        Map[instr].Next.Add(Map[uncondJump.Target]);
                    }
                    else
                    {
                        if (i + 1 < func.InstructionList.Count)
                        {
                            Map[instr].Next.Add(Map[func.InstructionList[i + 1]]);
                        }

                        if (instr is IL.ConditionalJumpInstruction condJump)
                        {
                            Map[instr].Next.Add(Map[condJump.Target]);
                        }
                    }
                }

                // The entry is the first instruction.
                Entry = Map[func.InstructionList[0]];
            }
Beispiel #4
0
        private void EndBasicBlock(BasicBlock block, IL.Instruction next)
        {
            // Calculate successors.
            IL.Instruction instr = block.LeavingInstruction;

            if (!(instr is IL.UnconditionalJumpInstruction) && next != null)
            {
                block.AddSuccessor(LookupByLeader[next]);
            }

            if (instr is IL.ConditionalJumpInstruction condJump)
            {
                block.AddSuccessor(LookupByLeader[condJump.Target]);
            }
            else if (instr is IL.UnconditionalJumpInstruction uncondJump)
            {
                block.AddSuccessor(LookupByLeader[uncondJump.Target]);
            }
            else if (instr is IL.ReturnInstruction)
            {
                // The successor of a return instruction is the dummy exit block.
                block.AddSuccessor(Exit);
            }
        }
Beispiel #5
0
        public static bool Optimize(List <IL.Instruction> list, HashSet <IL.Variable> aliveVars)
        {
            bool changed = false;

            for (int i = list.Count - 1; i >= 0; i--)
            {
                IL.Instruction instr = list[i];

                if ((instr is IL.FunctionInstruction || instr is IL.MoveInstruction) && !aliveVars.Contains(instr.DefinedVariable) && !Variable.NonLocalVariables.Contains(instr.DefinedVariable))
                {
                    // The variable is not alive, we can safely delete the instruction.
                    // Also, the variable must not be in a closure.
                    list.RemoveAt(i);
                    changed = true;
                }
                else
                {
                    // Update alive variables info.
                    aliveVars.UnionWith(instr.UsedVariables);
                }
            }

            return(changed);
        }
 public Node(IL.Instruction instr)
 {
     Instruction = instr;
     Next        = new HashSet <Node>();
 }
Beispiel #7
0
        public Graph(Function func)
        {
            Function = func;

            LookupByLeader = new Dictionary <IL.Instruction, BasicBlock>();
            BlockList      = new List <BasicBlock>();

            Exit = new BasicBlock();

            // Mark if an instruction is the leader of a basic block.
            bool[] IsLeader = new bool[func.InstructionList.Count];

            IsLeader[0] = true;

            for (int i = 0; i < IsLeader.Length; i++)
            {
                IL.Instruction instr = func.InstructionList[i];

                if (instr is IL.JumpInstruction)
                {
                    // The current instruction is a jump instruction.
                    // The next instruction is a leader.
                    if (i + 1 < func.InstructionList.Count)
                    {
                        IsLeader[i + 1] = true;
                    }
                }
                //else if (instr is IL.CallInstruction)
                //{
                //    // The current instruction is a call instruction.
                //    // Call instructions are leaders.
                //    IsLeader[i] = true;

                //    // The next instruction is also a leader.
                //    // Call takes up an entire block.
                //    if (i + 1 < func.InstructionList.Count)
                //    {
                //        IsLeader[i + 1] = true;
                //    }
                //}
                else if (instr is IL.Label)
                {
                    IsLeader[i] = true;
                }
            }

            BasicBlock current = null;

            for (int i = 0; i < IsLeader.Length; i++)
            {
                if (IsLeader[i])
                {
                    // New basic block.
                    current = new BasicBlock();

                    // Register in the dictionary.
                    LookupByLeader[func.InstructionList[i]] = current;

                    // Add to the list (used to preserve original order).
                    BlockList.Add(current);
                }

                current.AddInstruction(func.InstructionList[i]);
            }

            current = null;
            for (int i = 0; i < IsLeader.Length; i++)
            {
                if (IsLeader[i])
                {
                    // Make sure `current` is not the first basic block.
                    if (current != null)
                    {
                        EndBasicBlock(current, func.InstructionList[i]);
                    }

                    current = LookupByLeader[func.InstructionList[i]];
                }
            }

            // Finish up the last block.
            EndBasicBlock(current, null);
        }
Beispiel #8
0
        private bool Optimize(Node node)
        {
            // Check if the node has been visited.
            if (node.Optimized)
            {
                return(false);
            }

            // Mark if changes are made.
            bool changed = false;

            // Optimize recursively.
            foreach (Node next in node.Dependencies)
            {
                changed |= Optimize(next);
            }

            // Even if the instruction is not optimized, `Alternative` should be set.
            node.Alternative = node.Original;

            // Essential nodes cannot be removed.
            // (They are alive at the end of the basic block, or are function calls, etc.)
            if (node.Essential)
            {
                return(changed);
            }

            // The current instruction.
            IL.Instruction instr = node.Instruction;

            // Only move instruction may be removed.
            if (instr is IL.MoveInstruction move)
            {
                // If the instruction dependency forms a chain, it can be removed.
                if (node.OutDegree == 1 && node.InDegree == 1)
                {
                    node.Removed = true;

                    changed = true;

                    Node dependency = node.Dependencies.First();

                    if (move.Source == dependency.Instruction.DefinedVariable)
                    {
                        // Pattern: b = a, c = b.
                        node.Alternative = dependency.Alternative;
                    }
                    else
                    {
                        // Unnecessary code?
                        node.Alternative = move.Source;
                    }
                }
                else if (node.OutDegree == 0)
                {
                    node.Removed     = true;
                    node.Alternative = move.Source;
                }
            }

            return(changed);
        }