예제 #1
0
        public static void SolveDeadCode(SchemeFunction function)
        {
            //For each command C:
            //. If C uses local variable X that is in V, as input, we remove X from V and the corresponding line from L
            //. If C has local variable output X that is in V, then we remove the line of code that is connected to X (found in L)
            //. If C has local variable output, we store the output variable's name in array V, and the code line in L
            //. If we reach new basic block, we clear V and L

            bool changed = true;

            while (changed)
            {
                changed = false;

                HashSet <int> blocks = GetBlockPositions(function);

                var           commands         = function.Commands;
                HashSet <int> removableIndexes = new HashSet <int>();

                Dictionary <string, int> lastSetLines = new Dictionary <string, int>();

                for (int i = 0; i < commands.Count; ++i)
                {
                    if (blocks.Contains(i))
                    {
                        lastSetLines.Clear();
                    }

                    ISchemeCommand cmd = commands[i];

                    if (cmd is CommandCreateVariable)
                    {
                        continue;                               //We don't want to remove CREATE commands
                    }
                    List <string> inputs  = cmd.GetInputs();
                    List <string> outputs = cmd.GetOutputs();

                    if (inputs != null)
                    {
                        foreach (string input in inputs)
                        {
                            if (SchemeExecutor.IsVariable(input))
                            {
                                lastSetLines.Remove(input);
                            }
                        }
                    }

                    if (outputs != null)
                    {
                        foreach (string output in outputs)
                        {
                            if (SchemeExecutor.IsVariable(output))
                            {
                                if (lastSetLines.ContainsKey(output))
                                {
                                    removableIndexes.Add(lastSetLines[output]);
                                }
                                lastSetLines[output] = i;
                            }
                        }
                    }
                }

                if (removableIndexes.Count > 0)
                {
                    changed = true;
                    RemoveCommandsAt(function, removableIndexes);
                }
            }
        }
예제 #2
0
        public static void SolveRegisterBuffers(SchemeFunction function)
        {
            // if an operation stores its result in a register <reg>, and it is followed by a SET(<var>, <reg>) command
            //      we delete the SET command and set the opperation's output to <var>
            //      we iterate over the following commands and change any <reg> to <var>
            //      we stop if <reg> is set again or we leave the block

            var           commands         = function.Commands;
            HashSet <int> removableIndexes = new HashSet <int>();

            for (int i = 0; i < commands.Count; ++i)
            {
                ISchemeCommand cmd = commands[i];

                var outputs = cmd.GetOutputs();

                if (outputs == null)
                {
                    continue;
                }

                // check if any output is a register
                foreach (var reg in outputs)
                {
                    if (SchemeExecutor.IsRegister(reg))
                    {
                        string variable = null;
                        for (int j = i + 1; j < commands.Count; ++j)
                        {
                            ISchemeCommand cmd2 = commands[j];

                            if (cmd2 is CommandJumpBase)
                            {
                                break;                          // break if we leave the block
                            }
                            if (cmd2.HasOutput(reg))
                            {
                                break;                       // break if the register is set again
                            }
                            if (cmd2 is CommandSetVariable && cmd2.HasInput(reg))
                            {
                                CommandSetVariable setCmd = (CommandSetVariable)cmd2;
                                variable = setCmd.GetVariableName();
                                if (SchemeExecutor.IsRegister(variable))
                                {
                                    variable = null;
                                }
                                else
                                {
                                    cmd.ChangeOutput(reg, variable);
                                    removableIndexes.Add(j);
                                }
                            }

                            if (variable != null && cmd2.HasInput(reg))
                            {
                                cmd2.ChangeInputs(reg, variable);
                            }
                        }
                    }
                }
            }

            RemoveCommandsAt(function, removableIndexes);
        }