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