protected override void Setup() { foreach (var type in TypeSystem.AllTypes) { // If type has an interface - don't consider either type for de-virtualization // FUTURE: be more specific and check each method if (HasInterface(type)) { continue; } foreach (var method in type.Methods) { if (method.IsStatic || !method.IsVirtual) { continue; } if (!method.HasImplementation && method.IsAbstract) { continue; } if (TypeLayout.IsMethodOverridden(method)) { continue; } var methodData = Compiler.GetMethodData(method); methodData.IsDevirtualized = true; DevirtualizedMethodsCount++; } } }
private void CallVirtual(InstructionNode node) { var call = node.Operand1; var method = call.Method; if (TypeLayout.IsMethodOverridden(method)) { return; } if (!method.HasImplementation && method.IsAbstract) { return; } var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var operands = node.GetOperands(); operands.RemoveAt(0); trace?.Log($"De-virtualize: {method}"); DevirtualizedCount++; node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, operands); MethodScanner.MethodInvoked(method, Method); }
private void CallVirtual(InstructionNode node) { var call = node.Operand1; var method = call.Method; if (TypeLayout.IsMethodOverridden(method)) { return; } var symbol = Operand.CreateSymbolFromMethod(method, TypeSystem); var operands = node.GetOperands(); operands.RemoveAt(0); if (trace.Active) { trace.Log("De-virtualize: " + method); } DevirtualizedCount++; node.SetInstruction(IRInstruction.CallStatic, node.Result, symbol, operands); }
protected override void Run() { var method = MethodCompiler.Method; var trace = CreateTraceLog("Inline"); bool firstCompile = (MethodData.CompileCount == 0); MethodData.BasicBlocks = null; MethodData.IsCompiled = true; MethodData.HasProtectedRegions = HasProtectedRegions; MethodData.IsLinkerGenerated = method.IsLinkerGenerated; MethodData.IsCILDecoded = (!method.IsLinkerGenerated && method.Code.Count > 0); MethodData.HasLoops = false; MethodData.IsMethodImplementationReplaced = IsMethodPlugged; MethodData.HasDoNotInlineAttribute = MethodCompiler.Method.IsNoInlining; MethodData.HasAggressiveInliningAttribute = MethodCompiler.Method.IsAggressiveInlining; MethodData.HasAddressOfInstruction = false; MethodData.IsVirtual = method.IsVirtual; MethodData.IsDevirtualized = (method.IsVirtual && !TypeLayout.IsMethodOverridden(method)); int totalIRCount = 0; int totalNonIRCount = 0; int totalStackParameterInstruction = 0; if (!MethodCompiler.Method.IsNoInlining) { foreach (var block in BasicBlocks) { for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } if (node.Instruction is BaseIRInstruction) { totalIRCount++; } else { totalNonIRCount++; } if (node.Instruction == IRInstruction.AddressOf) { MethodData.HasAddressOfInstruction = true; } if (node.Instruction == IRInstruction.SetReturn32 || node.Instruction == IRInstruction.SetReturn64 || node.Instruction == IRInstruction.SetReturnR4 || node.Instruction == IRInstruction.SetReturnR8 || node.Instruction == IRInstruction.LoadParamCompound || node.Instruction == IRInstruction.LoadParamInt32 || node.Instruction == IRInstruction.LoadParamInt64 || node.Instruction == IRInstruction.LoadParamFloatR4 || node.Instruction == IRInstruction.LoadParamFloatR4 || node.Instruction == IRInstruction.LoadParamSignExtend16x32 || node.Instruction == IRInstruction.LoadParamSignExtend16x64 || node.Instruction == IRInstruction.LoadParamSignExtend32x64 || node.Instruction == IRInstruction.LoadParamSignExtend8x32 || node.Instruction == IRInstruction.LoadParamSignExtend8x64 || node.Instruction == IRInstruction.LoadParamZeroExtend16x32 || node.Instruction == IRInstruction.LoadParamZeroExtend16x64 || node.Instruction == IRInstruction.LoadParamZeroExtend32x64 || node.Instruction == IRInstruction.LoadParamZeroExtend8x32 || node.Instruction == IRInstruction.LoadParamZeroExtend8x64 //|| node.Instruction == IRInstruction.Epilogue //|| node.Instruction == IRInstruction.Prologue || node.Block.IsEpilogue || node.Block.IsPrologue ) { totalStackParameterInstruction++; } } if (block.PreviousBlocks.Count > 1) { MethodData.HasLoops = true; } } } MethodData.IRInstructionCount = totalIRCount; MethodData.NonIRInstructionCount = totalNonIRCount; MethodData.IRStackParameterInstructionCount = totalStackParameterInstruction; MethodData.CanInline = CanInline(MethodData); if (MethodData.CanInline) { MethodData.BasicBlocks = CopyInstructions(); if (MethodData.CompileCount < MaximumCompileCount) { MethodCompiler.Compiler.CompilationScheduler.AddToInlineQueue(MethodData); } } //lock (compilerMethod) //{ // foreach (var called in compilerMethod.CalledBy) // { // var calledMethod = MethodCompiler.Compiler.CompilerData.GetCompilerMethodData(called); // if (calledMethod.CompileCount < MaximumCompileCount) // { // MethodCompiler.Compiler.CompilationScheduler.Schedule(called); // } // } //} trace.Log("CanInline: " + MethodData.CanInline.ToString()); trace.Log("IsVirtual: " + MethodData.IsVirtual.ToString()); trace.Log("IsDevirtualized: " + MethodData.IsDevirtualized.ToString()); trace.Log("HasLoops: " + MethodData.HasLoops.ToString()); trace.Log("HasProtectedRegions: " + MethodData.HasProtectedRegions.ToString()); trace.Log("IRInstructionCount: " + MethodData.IRInstructionCount.ToString()); trace.Log("IRStackParameterInstructionCount: " + MethodData.IRStackParameterInstructionCount.ToString()); trace.Log("InlinedIRMaximum: " + CompilerOptions.InlinedIRMaximum.ToString()); trace.Log("NonIRInstructionCount: " + MethodData.NonIRInstructionCount.ToString()); trace.Log("HasDoNotInlineAttribute: " + MethodData.HasDoNotInlineAttribute.ToString()); trace.Log("HasAggressiveInliningAttribute: " + MethodData.HasAggressiveInliningAttribute.ToString()); trace.Log("IsPlugged: " + MethodData.IsMethodImplementationReplaced.ToString()); trace.Log("HasAddressOfInstruction: " + MethodData.HasAddressOfInstruction.ToString()); MethodCount.Set(1); GeneratedBlocksCount.Set(MethodData.CanInline); }
protected override void Run() { var method = MethodCompiler.Method; var trace = CreateTraceLog("Inline"); bool firstCompile = (MethodData.CompileCount == 0); MethodData.BasicBlocks = null; MethodData.IsCompiled = true; MethodData.HasProtectedRegions = HasProtectedRegions; MethodData.IsLinkerGenerated = method.IsLinkerGenerated; MethodData.IsCILDecoded = (!method.IsLinkerGenerated && method.Code.Count > 0); MethodData.HasLoops = false; MethodData.IsPlugged = IsPlugged; MethodData.HasDoNotInlineAttribute = false; MethodData.HasAddressOfInstruction = false; MethodData.IsVirtual = method.IsVirtual; MethodData.IsDevirtualized = (method.IsVirtual && !TypeLayout.IsMethodOverridden(method)); int totalIRCount = 0; int totalNonIRCount = 0; foreach (var block in BasicBlocks) { for (var node = block.First.Next; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } if (node.Instruction is BaseIRInstruction) { totalIRCount++; } else { totalNonIRCount++; } if (node.Instruction == IRInstruction.AddressOf) { MethodData.HasAddressOfInstruction = true; } } if (block.PreviousBlocks.Count > 1) { MethodData.HasLoops = true; } } MethodData.IRInstructionCount = totalIRCount; MethodData.NonIRInstructionCount = totalNonIRCount; MethodData.HasDoNotInlineAttribute = MethodCompiler.Method.IsNoInlining; //if (!compilerMethod.HasDoNotInlineAttribute) //{ // // check attribute // // BUG: does not find the attribute // var methodAttribute = method.FindCustomAttribute(InlineMethodAttribute); // //TODO: check for specific attribute: System.Runtime.CompilerServices.MethodImplOptions.NoInlining // if (methodAttribute != null) // { // compilerMethod.HasDoNotInlineAttribute = true; // } //} MethodData.CanInline = CanInline(MethodData); if (MethodData.CanInline) { MethodData.BasicBlocks = CopyInstructions(); if (MethodData.CompileCount < MaximumCompileCount) { MethodCompiler.Compiler.CompilationScheduler.AddToInlineQueue(MethodData); } } //lock (compilerMethod) //{ // foreach (var called in compilerMethod.CalledBy) // { // var calledMethod = MethodCompiler.Compiler.CompilerData.GetCompilerMethodData(called); // if (calledMethod.CompileCount < MaximumCompileCount) // { // MethodCompiler.Compiler.CompilationScheduler.Schedule(called); // } // } //} trace.Log("CanInline: " + MethodData.CanInline.ToString()); trace.Log("IsVirtual: " + MethodData.IsVirtual.ToString()); trace.Log("IsDevirtualized: " + MethodData.IsDevirtualized.ToString()); trace.Log("HasLoops: " + MethodData.HasLoops.ToString()); trace.Log("HasProtectedRegions: " + MethodData.HasProtectedRegions.ToString()); trace.Log("IRInstructionCount: " + MethodData.IRInstructionCount.ToString()); trace.Log("NonIRInstructionCount: " + MethodData.NonIRInstructionCount.ToString()); trace.Log("HasDoNotInlineAttribute: " + MethodData.HasDoNotInlineAttribute.ToString()); UpdateCounter("InlineMethodEvaluationStage.MethodCount", 1); if (MethodData.CanInline) { UpdateCounter("InlineMethodEvaluationStage.CanInline", 1); } }
protected override void Run() { var trace = CreateTraceLog(); MethodData.IsCompiled = false; MethodData.BasicBlocks = null; MethodData.HasProtectedRegions = HasProtectedRegions; MethodData.IsLinkerGenerated = Method.IsCompilerGenerated; MethodData.IsMethodImplementationReplaced = MethodCompiler.IsMethodPlugged; MethodData.HasDoNotInlineAttribute = Method.IsNoInlining; MethodData.HasAggressiveInliningAttribute = Method.IsAggressiveInlining; MethodData.HasAddressOfInstruction = false; MethodData.HasLoops = false; MethodData.IsVirtual = Method.IsVirtual; MethodData.IsDevirtualized = Method.IsVirtual && !TypeLayout.IsMethodOverridden(Method); trace?.Log($"DoNotInline: {MethodData.DoNotInline}"); trace?.Log($"IsVirtual: {MethodData.IsVirtual}"); trace?.Log($"IsDevirtualized: {MethodData.IsDevirtualized}"); trace?.Log($"HasProtectedRegions: {MethodData.HasProtectedRegions}"); trace?.Log($"HasDoNotInlineAttribute: {MethodData.HasDoNotInlineAttribute}"); trace?.Log($"HasAggressiveInliningAttribute: {MethodData.HasAggressiveInliningAttribute}"); trace?.Log($"IsMethodImplementationReplaced (Plugged): {MethodData.IsMethodImplementationReplaced}"); trace?.Log($"CompileCount: {MethodData.CompileCount}"); if (StaticCanNotInline(MethodData, Method)) { trace?.Log($"** Staticly Evaluated"); trace?.Log($"Inlined: {MethodData.Inlined}"); return; } var currentInlineStatus = MethodData.Inlined; int totalIRCount = 0; int totalNonIRCount = 0; int totalStackParameterInstruction = 0; if (!Method.IsNoInlining) { foreach (var block in BasicBlocks) { for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } if (node.Instruction is BaseIRInstruction) { totalIRCount++; } else { totalNonIRCount++; } if (node.Instruction == IRInstruction.AddressOf) { MethodData.HasAddressOfInstruction = true; } if (node.Instruction == IRInstruction.SetReturn32 || node.Instruction == IRInstruction.SetReturn64 || node.Instruction == IRInstruction.SetReturnR4 || node.Instruction == IRInstruction.SetReturnR8 || node.Instruction == IRInstruction.LoadParamCompound || node.Instruction == IRInstruction.LoadParamInt32 || node.Instruction == IRInstruction.LoadParamInt64 || node.Instruction == IRInstruction.LoadParamFloatR4 || node.Instruction == IRInstruction.LoadParamFloatR4 || node.Instruction == IRInstruction.LoadParamSignExtend16x32 || node.Instruction == IRInstruction.LoadParamSignExtend16x64 || node.Instruction == IRInstruction.LoadParamSignExtend32x64 || node.Instruction == IRInstruction.LoadParamSignExtend8x32 || node.Instruction == IRInstruction.LoadParamSignExtend8x64 || node.Instruction == IRInstruction.LoadParamZeroExtend16x32 || node.Instruction == IRInstruction.LoadParamZeroExtend16x64 || node.Instruction == IRInstruction.LoadParamZeroExtend32x64 || node.Instruction == IRInstruction.LoadParamZeroExtend8x32 || node.Instruction == IRInstruction.LoadParamZeroExtend8x64 //|| node.Instruction == IRInstruction.Epilogue //|| node.Instruction == IRInstruction.Prologue || node.Block.IsEpilogue || node.Block.IsPrologue ) { totalStackParameterInstruction++; } } if (block.PreviousBlocks.Count > 1) { MethodData.HasLoops = true; } } } MethodData.IRInstructionCount = totalIRCount; MethodData.NonIRInstructionCount = totalNonIRCount; MethodData.IRStackParameterInstructionCount = totalStackParameterInstruction; bool inline = CanInline(MethodData, Method); MethodData.Inlined = inline; MethodCompiler.IsMethodInlined = inline; bool triggerReschedules = inline || (currentInlineStatus && !inline); if (inline) { MethodData.BasicBlocks = CopyInstructions(); } if (triggerReschedules) { MethodScheduler.AddToInlineQueueByCallee(MethodData); } trace?.Log($"IRInstructionCount: {MethodData.IRInstructionCount}"); trace?.Log($"IRStackParameterInstructionCount: {MethodData.IRStackParameterInstructionCount}"); trace?.Log($"InlinedIRMaximum: {CompilerOptions.InlinedIRMaximum}"); trace?.Log($"NonIRInstructionCount: {MethodData.NonIRInstructionCount}"); trace?.Log($"HasAddressOfInstruction: {MethodData.HasAddressOfInstruction}"); trace?.Log($"HasLoops: {MethodData.HasLoops}"); trace?.Log($"** Dynamically Evaluated"); trace?.Log($"Inlined: {MethodData.Inlined}"); InlinedMethodsCount.Set(inline); ReversedInlinedMethodsCount.Set(MethodData.CompileCount >= MaximumCompileCount); }