void MakeByRefCallSimple(SsaBlock block, ref int instructionIndexInBlock, IMethodSignature targetMethod) { SsaInstruction inst = block.Instructions[instructionIndexInBlock]; for (int i = 0; i < inst.Operands.Length; i++) { SsaVariable operand = inst.Operands[i]; if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) { // address is used for this method call only Instruction loadAddressInstruction = operand.Definition.Instruction; // find target parameter type: bool isOut; if (i == 0 && targetMethod.HasThis) { isOut = false; } else { ParameterDefinition parameter = targetMethod.Parameters[i - (targetMethod.HasThis ? 1 : 0)]; isOut = parameter.IsOut; } SsaVariable addressTakenOf = GetVariableFromLoadAddressInstruction(loadAddressInstruction); // insert "Prepare" instruction on front SpecialOpCode loadOpCode = isOut ? SpecialOpCode.PrepareByOutCall : SpecialOpCode.PrepareByRefCall; block.Instructions.Insert(instructionIndexInBlock++, new SsaInstruction( block, null, operand, new SsaVariable[] { addressTakenOf }, specialOpCode: loadOpCode)); // insert "WriteAfterByRefOrOutCall" instruction after call block.Instructions.Insert(instructionIndexInBlock + 1, new SsaInstruction( block, null, addressTakenOf, new SsaVariable[] { operand }, specialOpCode: SpecialOpCode.WriteAfterByRefOrOutCall)); couldSimplifySomething = true; // remove the loadAddressInstruction later // (later because it might be defined in the current block and we don't want instructionIndex to become invalid) redundantLoadAddressInstructions.Add(operand.Definition); } } }
void MakeLoadFieldCallSimple(SsaBlock block, ref int instructionIndexInBlock) { SsaInstruction inst = block.Instructions[instructionIndexInBlock]; Debug.Assert(inst.Operands.Length == 1); SsaVariable operand = inst.Operands[0]; if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) { // insert special "PrepareForFieldAccess" instruction in front block.Instructions.Insert(instructionIndexInBlock++, new SsaInstruction( inst.ParentBlock, null, operand, new SsaVariable[] { GetVariableFromLoadAddressInstruction(operand.Definition.Instruction) }, specialOpCode: SpecialOpCode.PrepareForFieldAccess)); couldSimplifySomething = true; // remove the loadAddressInstruction later redundantLoadAddressInstructions.Add(operand.Definition); } }
void MakeInitObjCallSimple(SsaBlock block, ref int instructionIndexInBlock) { SsaInstruction inst = block.Instructions[instructionIndexInBlock]; Debug.Assert(inst.Operands.Length == 1); SsaVariable operand = inst.Operands[0]; if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) { // replace instruction with special "InitObj" instruction block.Instructions[instructionIndexInBlock] = new SsaInstruction( inst.ParentBlock, null, GetVariableFromLoadAddressInstruction(operand.Definition.Instruction), null, specialOpCode: SpecialOpCode.InitObj, typeOperand: (TypeReference)inst.Instruction.Operand); couldSimplifySomething = true; // remove the loadAddressInstruction later redundantLoadAddressInstructions.Add(operand.Definition); } }
static bool CanRemoveAsDeadCode(SsaInstruction inst) { if (inst.Target != null && !inst.Target.IsSingleAssignment) { return(false); } switch (inst.SpecialOpCode) { case SpecialOpCode.Phi: case SpecialOpCode.Exception: case SpecialOpCode.Parameter: case SpecialOpCode.Uninitialized: return(true); case SpecialOpCode.None: return(inst.IsMoveInstruction); default: return(false); } }
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); }
static bool CanRemoveAsDeadCode(SsaInstruction inst) { if (inst.Target != null && !inst.Target.IsSingleAssignment) return false; switch (inst.SpecialOpCode) { case SpecialOpCode.Phi: case SpecialOpCode.Exception: case SpecialOpCode.Parameter: case SpecialOpCode.Uninitialized: return true; case SpecialOpCode.None: return inst.IsMoveInstruction; default: return false; } }
static bool IsLoadAddress(SsaInstruction inst) { return(inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Ldloca || inst.Instruction.OpCode == OpCodes.Ldarga)); }
static bool IsLoadAddress(SsaInstruction inst) { return inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Ldloca || inst.Instruction.OpCode == OpCodes.Ldarga); }