public static bool MakeByRefCallsSimple(SsaForm ssaForm) { SimplifyByRefCalls instance = new SimplifyByRefCalls(ssaForm); foreach (SsaBlock block in ssaForm.Blocks) { for (int i = 0; i < block.Instructions.Count; i++) { SsaInstruction inst = block.Instructions[i]; if (inst.Instruction != null) { switch (inst.Instruction.OpCode.Code) { case Code.Call: case Code.Callvirt: instance.MakeByRefCallSimple(block, ref i, (IMethodSignature)inst.Instruction.Operand); break; case Code.Initobj: instance.MakeInitObjCallSimple(block, ref i); break; case Code.Ldfld: instance.MakeLoadFieldCallSimple(block, ref i); break; } } } } instance.RemoveRedundantInstructions(); if (instance.couldSimplifySomething) ssaForm.ComputeVariableUsage(); return instance.couldSimplifySomething; }
public static void RemoveDeadAssignments(SsaForm ssaForm) { HashSet <SsaVariable> liveVariables = new HashSet <SsaVariable>(); // find variables that are used directly foreach (SsaBlock block in ssaForm.Blocks) { foreach (SsaInstruction inst in block.Instructions) { if (!CanRemoveAsDeadCode(inst)) { if (inst.Target != null) { liveVariables.Add(inst.Target); } foreach (SsaVariable op in inst.Operands) { liveVariables.Add(op); } } } } Queue <SsaVariable> queue = new Queue <SsaVariable>(liveVariables); // find variables that are used indirectly while (queue.Count > 0) { SsaVariable v = queue.Dequeue(); if (v.IsSingleAssignment) { foreach (SsaVariable op in v.Definition.Operands) { if (liveVariables.Add(op)) { queue.Enqueue(op); } } } } // remove assignments to all unused variables foreach (SsaBlock block in ssaForm.Blocks) { block.Instructions.RemoveAll( inst => { if (inst.Target != null && !liveVariables.Contains(inst.Target)) { Debug.Assert(inst.Target.IsSingleAssignment); return(true); } return(false); }); } ssaForm.ComputeVariableUsage(); // update usage after we modified stuff }
/// <summary> /// When any instructions stores its result in a stack location that's used only once in a 'stloc' or 'starg' instruction, /// we optimize this to directly store in the target location. /// As optimization this is redundant (does the same as copy propagation), but it'll make us keep the variables named /// after locals instead of keeping the temps as using only the simple copy propagation would do. /// </summary> public static void DirectlyStoreToVariables(SsaForm ssaForm) { foreach (SsaBlock block in ssaForm.Blocks) { block.Instructions.RemoveAll( inst => { if (inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Stloc || inst.Instruction.OpCode == OpCodes.Starg)) { SsaVariable target = inst.Target; SsaVariable temp = inst.Operands[0]; if (target.IsSingleAssignment && temp.IsSingleAssignment && temp.Usage.Count == 1 && temp.IsStackLocation) { temp.Definition.Target = target; return true; } } return false; }); } ssaForm.ComputeVariableUsage(); // update usage after we modified stuff }
public static void SimpleCopyPropagation(SsaForm ssaForm, bool onlyForStackLocations = true) { foreach (SsaBlock block in ssaForm.Blocks) { foreach (SsaInstruction inst in block.Instructions) { if (inst.IsMoveInstruction && inst.Target.IsSingleAssignment && inst.Operands[0].IsSingleAssignment) { if (inst.Target.IsStackLocation || !onlyForStackLocations) { // replace all uses of 'target' with 'operands[0]'. foreach (SsaInstruction useInstruction in inst.Target.Usage) { useInstruction.ReplaceVariableInOperands(inst.Target, inst.Operands[0]); } } } } } ssaForm.ComputeVariableUsage(); // update usage after we modified stuff }
/// <summary> /// When any instructions stores its result in a stack location that's used only once in a 'stloc' or 'starg' instruction, /// we optimize this to directly store in the target location. /// As optimization this is redundant (does the same as copy propagation), but it'll make us keep the variables named /// after locals instead of keeping the temps as using only the simple copy propagation would do. /// </summary> public static void DirectlyStoreToVariables(SsaForm ssaForm) { foreach (SsaBlock block in ssaForm.Blocks) { block.Instructions.RemoveAll( inst => { if (inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Stloc || inst.Instruction.OpCode == OpCodes.Starg)) { SsaVariable target = inst.Target; SsaVariable temp = inst.Operands[0]; if (target.IsSingleAssignment && temp.IsSingleAssignment && temp.Usage.Count == 1 && temp.IsStackLocation) { temp.Definition.Target = target; return(true); } } return(false); }); } ssaForm.ComputeVariableUsage(); // update usage after we modified stuff }
public static bool MakeByRefCallsSimple(SsaForm ssaForm) { SimplifyByRefCalls instance = new SimplifyByRefCalls(ssaForm); foreach (SsaBlock block in ssaForm.Blocks) { for (int i = 0; i < block.Instructions.Count; i++) { SsaInstruction inst = block.Instructions[i]; if (inst.Instruction != null) { switch (inst.Instruction.OpCode.Code) { case Code.Call: case Code.Callvirt: instance.MakeByRefCallSimple(block, ref i, (IMethodSignature)inst.Instruction.Operand); break; case Code.Initobj: instance.MakeInitObjCallSimple(block, ref i); break; case Code.Ldfld: instance.MakeLoadFieldCallSimple(block, ref i); break; } } } } instance.RemoveRedundantInstructions(); if (instance.couldSimplifySomething) { ssaForm.ComputeVariableUsage(); } return(instance.couldSimplifySomething); }
public static void RemoveDeadAssignments(SsaForm ssaForm) { HashSet<SsaVariable> liveVariables = new HashSet<SsaVariable>(); // find variables that are used directly foreach (SsaBlock block in ssaForm.Blocks) { foreach (SsaInstruction inst in block.Instructions) { if (!CanRemoveAsDeadCode(inst)) { if (inst.Target != null) liveVariables.Add(inst.Target); foreach (SsaVariable op in inst.Operands) { liveVariables.Add(op); } } } } Queue<SsaVariable> queue = new Queue<SsaVariable>(liveVariables); // find variables that are used indirectly while (queue.Count > 0) { SsaVariable v = queue.Dequeue(); if (v.IsSingleAssignment) { foreach (SsaVariable op in v.Definition.Operands) { if (liveVariables.Add(op)) queue.Enqueue(op); } } } // remove assignments to all unused variables foreach (SsaBlock block in ssaForm.Blocks) { block.Instructions.RemoveAll( inst => { if (inst.Target != null && !liveVariables.Contains(inst.Target)) { Debug.Assert(inst.Target.IsSingleAssignment); return true; } return false; }); } ssaForm.ComputeVariableUsage(); // update usage after we modified stuff }
public static void SimpleCopyPropagation(SsaForm ssaForm, bool onlyForStackLocations = true) { foreach (SsaBlock block in ssaForm.Blocks) { foreach (SsaInstruction inst in block.Instructions) { if (inst.IsMoveInstruction && inst.Target.IsSingleAssignment && inst.Operands[0].IsSingleAssignment) { if (inst.Target.IsStackLocation || !onlyForStackLocations) { // replace all uses of 'target' with 'operands[0]'. foreach (SsaInstruction useInstruction in inst.Target.Usage) { useInstruction.ReplaceVariableInOperands(inst.Target, inst.Operands[0]); } } } } } ssaForm.ComputeVariableUsage(); // update usage after we modified stuff }