private void OptimizeLocalVariables(ref int localVarNumber)
        {
            List <List <VariableLifetimeCycle> > localVariablesLifeCycles = new List <List <VariableLifetimeCycle> >(localVarNumber);

            for (int i = 0; i < localVarNumber; i++)
            {
                localVariablesLifeCycles.Add(new List <VariableLifetimeCycle>());
            }

            for (int i = 0; i < IlInstructions.Count; i++)
            {
                if (IlInstructions[i].OpCode == OpCodes.Stloc)
                {
                    localVariablesLifeCycles[(int)IlInstructions[i].Arg].Add(new VariableLifetimeCycle(i, i));
                }
                else if (IlInstructions[i].OpCode == OpCodes.Ldloc)
                {
                    var cycles = localVariablesLifeCycles[(int)IlInstructions[i].Arg];
                    cycles[cycles.Count - 1] = new VariableLifetimeCycle(cycles[cycles.Count - 1].BeginInd, i);
                }
            }

            for (int i = 1; i < localVariablesLifeCycles.Count; i++)
            {
                for (int k = 0; k < i; k++)
                {
                    for (int j = 0; j < localVariablesLifeCycles[i].Count; j++)
                    {
                        if (!IsIntersect(localVariablesLifeCycles[i][j], localVariablesLifeCycles[k]))
                        {
                            IlInstructions[localVariablesLifeCycles[i][j].BeginInd] = new OpCodeArg(OpCodes.Stloc, k);
                            for (int l = localVariablesLifeCycles[i][j].BeginInd + 1; l <= localVariablesLifeCycles[i][j].EndInd; l++)
                            {
                                if (IlInstructions[l].OpCode == OpCodes.Ldloc && (int)IlInstructions[l].Arg == i)
                                {
                                    IlInstructions[l] = new OpCodeArg(OpCodes.Ldloc, k);
                                }
                            }

                            localVariablesLifeCycles[k].Add(localVariablesLifeCycles[i][j]);
                            localVariablesLifeCycles[i].RemoveAt(j);
                        }
                    }
                }
            }

            for (int i = localVariablesLifeCycles.Count - 1; i >= 0; i--)
            {
                if (localVariablesLifeCycles[i].Count == 0)
                {
                    localVariablesLifeCycles.RemoveAt(i);
                }
                else
                {
                    break;
                }
            }

            localVarNumber = localVariablesLifeCycles.Count;
        }
 private static void EmitInstruction(ILProcessor ilProcessor, OpCodeArg instr, bool staticFunc)
 {
     if (instr.Arg == null)
     {
         ilProcessor.Emit(instr.OpCode);
     }
     else if (instr.Arg is int)
     {
         if (instr.OpCode == OpCodes.Ldarg)
         {
             EmitArgLoad(ilProcessor, (int)instr.Arg + (staticFunc ? 0 : 1));
         }
         else if (instr.OpCode == OpCodes.Ldloc)
         {
             EmitLocalLoad(ilProcessor, (int)instr.Arg);
         }
         else if (instr.OpCode == OpCodes.Stloc)
         {
             EmitLocalSave(ilProcessor, (int)instr.Arg);
         }
         else
         {
             ilProcessor.Emit(instr.OpCode, (int)instr.Arg);
         }
     }
     else if (instr.Arg is double)
     {
         ilProcessor.Emit(instr.OpCode, (double)instr.Arg);
     }
     else if (instr.Arg is float)
     {
         ilProcessor.Emit(instr.OpCode, (float)instr.Arg);
     }
     else if (instr.Arg is string)
     {
         ilProcessor.Emit(instr.OpCode, (string)instr.Arg);
     }
     else if (instr.Arg is byte)
     {
         ilProcessor.Emit(instr.OpCode, (byte)instr.Arg);
     }
     else if (instr.Arg is sbyte)
     {
         ilProcessor.Emit(instr.OpCode, (sbyte)instr.Arg);
     }
     else if (instr.Arg is CallSite)
     {
         ilProcessor.Emit(instr.OpCode, (CallSite)instr.Arg);
     }
     else if (instr.Arg is FieldReference)
     {
         ilProcessor.Emit(instr.OpCode, (FieldReference)instr.Arg);
     }
     else if (instr.Arg is Instruction)
     {
         ilProcessor.Emit(instr.OpCode, (Instruction)instr.Arg);
     }
     else if (instr.Arg is Instruction[])
     {
         ilProcessor.Emit(instr.OpCode, (Instruction[])instr.Arg);
     }
     else if (instr.Arg is MethodReference)
     {
         ilProcessor.Emit(instr.OpCode, (MethodReference)instr.Arg);
     }
     else if (instr.Arg is ParameterDefinition)
     {
         ilProcessor.Emit(instr.OpCode, (ParameterDefinition)instr.Arg);
     }
     else if (instr.Arg is TypeReference)
     {
         ilProcessor.Emit(instr.OpCode, (TypeReference)instr.Arg);
     }
     else if (instr.Arg is VariableDefinition)
     {
         ilProcessor.Emit(instr.OpCode, (VariableDefinition)instr.Arg);
     }
 }
        private void OptimizeInstructions()
        {
            int i = 0;

            while (i < IlInstructions.Count)
            {
                if (i < IlInstructions.Count - 1)
                {
                    var firstOpCode = IlInstructions[i].OpCode;

                    if ((firstOpCode == OpCodes.Ldarg || firstOpCode == OpCodes.Ldc_R8) && IlInstructions[i + 1].OpCode == OpCodes.Stloc)
                    {
                        var locNumber = (int)IlInstructions[i + 1].Arg;

                        for (int j = i + 2; j < IlInstructions.Count; j++)
                        {
                            if ((IlInstructions[j].OpCode == OpCodes.Stloc) && (int)IlInstructions[j].Arg == locNumber)
                            {
                                break;
                            }

                            if ((IlInstructions[j].OpCode == OpCodes.Ldloc) && (int)IlInstructions[j].Arg == locNumber)
                            {
                                IlInstructions[j] = new OpCodeArg(firstOpCode, IlInstructions[i].Arg);
                            }
                        }

                        IlInstructions.RemoveRange(i, 2);
                        continue;
                    }

                    if (firstOpCode == OpCodes.Ldloc && IlInstructions[i + 1].OpCode == OpCodes.Stloc)
                    {
                        if ((int)IlInstructions[i].Arg == (int)IlInstructions[i + 1].Arg)
                        {
                            IlInstructions.RemoveRange(i, 2);
                            continue;
                        }
                        else
                        {
                            var locNumber1 = (int)IlInstructions[i].Arg;
                            var locNumber2 = (int)IlInstructions[i + 1].Arg;

                            bool arg2IsUsed = false;
                            for (int j = i + 2; j < IlInstructions.Count; j++)
                            {
                                if ((IlInstructions[j].OpCode == OpCodes.Stloc) && (int)IlInstructions[j].Arg == locNumber1)
                                {
                                    break;
                                }

                                if ((IlInstructions[j].OpCode == OpCodes.Stloc) && (int)IlInstructions[j].Arg == locNumber2)
                                {
                                    break;
                                }

                                if ((IlInstructions[j].OpCode == OpCodes.Ldloc) && (int)IlInstructions[j].Arg == locNumber2)
                                {
                                    IlInstructions[j] = new OpCodeArg(OpCodes.Ldloc, locNumber1);
                                    arg2IsUsed        = true;
                                }
                            }

                            if (arg2IsUsed)
                            {
                                IlInstructions.RemoveRange(i, 2);
                                continue;
                            }
                        }
                    }

                    if (firstOpCode == OpCodes.Stloc && IlInstructions[i + 1].OpCode == OpCodes.Ldloc &&
                        (int)IlInstructions[i].Arg == (int)IlInstructions[i + 1].Arg)
                    {
                        var locNumber = (int)IlInstructions[i].Arg;

                        bool remove = true;
                        for (int j = i + 2; j < IlInstructions.Count; j++)
                        {
                            if ((IlInstructions[j].OpCode == OpCodes.Ldloc) && (int)IlInstructions[j].Arg == locNumber)
                            {
                                remove = false;
                                break;
                            }
                        }

                        if (remove)
                        {
                            IlInstructions.RemoveRange(i, 2);
                            continue;
                        }
                    }
                }

                i++;
            }
        }
		private static void EmitInstruction(ILProcessor ilProcessor, OpCodeArg instr, bool staticFunc)
		{
			if (instr.Arg == null)
				ilProcessor.Emit(instr.OpCode);
			else if (instr.Arg is int)
			{
				if (instr.OpCode == OpCodes.Ldarg)
					EmitArgLoad(ilProcessor, (int)instr.Arg + (staticFunc ? 0 : 1));
				else if (instr.OpCode == OpCodes.Ldloc)
					EmitLocalLoad(ilProcessor, (int)instr.Arg);
				else if (instr.OpCode == OpCodes.Stloc)
					EmitLocalSave(ilProcessor, (int)instr.Arg);
				else
					ilProcessor.Emit(instr.OpCode, (int)instr.Arg);
			}
			else if (instr.Arg is double)
				ilProcessor.Emit(instr.OpCode, (double)instr.Arg);
			else if (instr.Arg is float)
				ilProcessor.Emit(instr.OpCode, (float)instr.Arg);
			else if (instr.Arg is string)
				ilProcessor.Emit(instr.OpCode, (string)instr.Arg);
			else if (instr.Arg is byte)
				ilProcessor.Emit(instr.OpCode, (byte)instr.Arg);
			else if (instr.Arg is sbyte)
				ilProcessor.Emit(instr.OpCode, (sbyte)instr.Arg);
			else if (instr.Arg is CallSite)
				ilProcessor.Emit(instr.OpCode, (CallSite)instr.Arg);
			else if (instr.Arg is FieldReference)
				ilProcessor.Emit(instr.OpCode, (FieldReference)instr.Arg);
			else if (instr.Arg is Instruction)
				ilProcessor.Emit(instr.OpCode, (Instruction)instr.Arg);
			else if (instr.Arg is Instruction[])
				ilProcessor.Emit(instr.OpCode, (Instruction[])instr.Arg);
			else if (instr.Arg is MethodReference)
				ilProcessor.Emit(instr.OpCode, (MethodReference)instr.Arg);
			else if (instr.Arg is ParameterDefinition)
				ilProcessor.Emit(instr.OpCode, (ParameterDefinition)instr.Arg);
			else if (instr.Arg is TypeReference)
				ilProcessor.Emit(instr.OpCode, (TypeReference)instr.Arg);
			else if (instr.Arg is VariableDefinition)
				ilProcessor.Emit(instr.OpCode, (VariableDefinition)instr.Arg);
		}
		private void OptimizeInstructions()
		{
			int i = 0;
			while (i < IlInstructions.Count)
			{
				if (i < IlInstructions.Count - 1)
				{
					var firstOpCode = IlInstructions[i].OpCode;

					if ((firstOpCode == OpCodes.Ldarg || firstOpCode == OpCodes.Ldc_R8) && IlInstructions[i + 1].OpCode == OpCodes.Stloc)
					{
						var locNumber = (int)IlInstructions[i + 1].Arg;

						for (int j = i + 2; j < IlInstructions.Count; j++)
						{
							if ((IlInstructions[j].OpCode == OpCodes.Stloc) && (int)IlInstructions[j].Arg == locNumber)
								break;

							if ((IlInstructions[j].OpCode == OpCodes.Ldloc) && (int)IlInstructions[j].Arg == locNumber)
								IlInstructions[j] = new OpCodeArg(firstOpCode, IlInstructions[i].Arg);
						}

						IlInstructions.RemoveRange(i, 2);
						continue;
					}

					if (firstOpCode == OpCodes.Ldloc && IlInstructions[i + 1].OpCode == OpCodes.Stloc)
					{
						if ((int)IlInstructions[i].Arg == (int)IlInstructions[i + 1].Arg)
						{
							IlInstructions.RemoveRange(i, 2);
							continue;
						}
						else
						{
							var locNumber1 = (int)IlInstructions[i].Arg;
							var locNumber2 = (int)IlInstructions[i + 1].Arg;

							bool arg2IsUsed = false;
							for (int j = i + 2; j < IlInstructions.Count; j++)
							{
								if ((IlInstructions[j].OpCode == OpCodes.Stloc) && (int)IlInstructions[j].Arg == locNumber1)
									break;

								if ((IlInstructions[j].OpCode == OpCodes.Stloc) && (int)IlInstructions[j].Arg == locNumber2)
									break;

								if ((IlInstructions[j].OpCode == OpCodes.Ldloc) && (int)IlInstructions[j].Arg == locNumber2)
								{
									IlInstructions[j] = new OpCodeArg(OpCodes.Ldloc, locNumber1);
									arg2IsUsed = true;
								}
							}

							if (arg2IsUsed)
							{
								IlInstructions.RemoveRange(i, 2);
								continue;
							}
						}
					}

					if (firstOpCode == OpCodes.Stloc && IlInstructions[i + 1].OpCode == OpCodes.Ldloc &&
						(int)IlInstructions[i].Arg == (int)IlInstructions[i + 1].Arg)
					{
						var locNumber = (int)IlInstructions[i].Arg;

						bool remove = true;
						for (int j = i + 2; j < IlInstructions.Count; j++)
							if ((IlInstructions[j].OpCode == OpCodes.Ldloc) && (int)IlInstructions[j].Arg == locNumber)
							{
								remove = false;
								break;
							}

						if (remove)
						{
							IlInstructions.RemoveRange(i, 2);
							continue;
						}
					}
				}

				i++;
			}
		}
		private void OptimizeLocalVariables(ref int localVarNumber)
		{
			List<List<VariableLifetimeCycle>> localVariablesLifeCycles = new List<List<VariableLifetimeCycle>>(localVarNumber);
			for (int i = 0; i < localVarNumber; i++)
				localVariablesLifeCycles.Add(new List<VariableLifetimeCycle>());

			for (int i = 0; i < IlInstructions.Count; i++)
				if (IlInstructions[i].OpCode == OpCodes.Stloc)
					localVariablesLifeCycles[(int)IlInstructions[i].Arg].Add(new VariableLifetimeCycle(i, i));
				else if (IlInstructions[i].OpCode == OpCodes.Ldloc)
				{
					var cycles = localVariablesLifeCycles[(int)IlInstructions[i].Arg];
					cycles[cycles.Count - 1] = new VariableLifetimeCycle(cycles[cycles.Count - 1].BeginInd, i);
				}

			for (int i = 1; i < localVariablesLifeCycles.Count; i++)
				for (int k = 0; k < i; k++)
					for (int j = 0; j < localVariablesLifeCycles[i].Count; j++)
						if (!IsIntersect(localVariablesLifeCycles[i][j], localVariablesLifeCycles[k]))
						{
							IlInstructions[localVariablesLifeCycles[i][j].BeginInd] = new OpCodeArg(OpCodes.Stloc, k);
							for (int l = localVariablesLifeCycles[i][j].BeginInd + 1; l <= localVariablesLifeCycles[i][j].EndInd; l++)
								if (IlInstructions[l].OpCode == OpCodes.Ldloc && (int)IlInstructions[l].Arg == i)
									IlInstructions[l] = new OpCodeArg(OpCodes.Ldloc, k);

							localVariablesLifeCycles[k].Add(localVariablesLifeCycles[i][j]);
							localVariablesLifeCycles[i].RemoveAt(j);
						}

			for (int i = localVariablesLifeCycles.Count - 1; i >= 0; i--)
				if (localVariablesLifeCycles[i].Count == 0)
					localVariablesLifeCycles.RemoveAt(i);
				else
					break;

			localVarNumber = localVariablesLifeCycles.Count;
		}