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