protected override void Run() { MethodData.CompileCount++; var callSites = new List <InstructionNode>(); var methodCalls = new List <MosaMethod>(); // find all call sites foreach (var block in BasicBlocks) { for (var node = block.AfterFirst; !node.IsBlockEndInstruction; node = node.Next) { if (node.IsEmpty) { continue; } if (node.Instruction != IRInstruction.CallStatic) { continue; } if (!node.Operand1.IsSymbol) { continue; } var invokedMethod = node.Operand1.Method; if (invokedMethod == null) { continue; } callSites.Add(node); if (methodCalls.Contains(invokedMethod)) { continue; } methodCalls.Add(invokedMethod); var invoked = MethodCompiler.Compiler.CompilerData.GetMethodData(invokedMethod); invoked.AddCalledBy(MethodCompiler.Method); } } if (callSites.Count == 0) { return; } var trace = CreateTraceLog("Inlined"); int callSiteCount = 0; foreach (var callSiteNode in callSites) { var invokedMethod = callSiteNode.Operand1.Method; var callee = MethodCompiler.Compiler.CompilerData.GetMethodData(invokedMethod); if (!callee.Inlined) { continue; } // don't inline self if (callee.Method == MethodCompiler.Method) { continue; } var inlineBlocks = callee.BasicBlocks; if (inlineBlocks == null) { continue; } trace?.Log(callee.Method.FullName); Inline(callSiteNode, inlineBlocks); callSiteCount++; //if (!BasicBlocks.RuntimeValidation()) //{ // throw new CompilerException($"InlineStage: Block Validation after inlining: {invokedMethod} into {Method}"); //} } // Captures point in time - immediately after inlined blocks were used MethodData.InlineTimestamp = MethodScheduler.GetTimestamp(); InlinedMethodsCount.Set(1); InlinedCallSitesCount.Set(callSiteCount); }
protected override void Run() { var trace = CreateTraceLog("Inline"); bool firstCompile = (MethodData.CompileCount == 0); var currentInlineStatus = MethodData.Inlined; MethodData.IsCompiled = true; MethodData.HasProtectedRegions = HasProtectedRegions; MethodData.IsLinkerGenerated = Method.IsCompilerGenerated; MethodData.IsCILDecoded = MethodCompiler.IsCILDecodeRequired || (!Method.IsCompilerGenerated && Method.HasImplementation); MethodData.HasLoops = false; MethodData.IsMethodImplementationReplaced = MethodCompiler.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; bool inline = CanInline(MethodData); MethodData.Inlined = inline; bool triggerReschedules = inline || (currentInlineStatus && !inline); var timestamp = 0; if (inline) { MethodData.BasicBlocks = CopyInstructions(); } if (triggerReschedules) { timestamp = MethodScheduler.GetTimestamp(); MethodScheduler.AddToInlineQueueByCallee(MethodData, timestamp); } trace?.Log($"Inlined: {MethodData.Inlined}"); trace?.Log($"DoNotInline: {MethodData.DoNotInline}"); trace?.Log($"IsVirtual: {MethodData.IsVirtual}"); trace?.Log($"IsDevirtualized: {MethodData.IsDevirtualized}"); trace?.Log($"HasLoops: {MethodData.HasLoops}"); trace?.Log($"HasProtectedRegions: {MethodData.HasProtectedRegions}"); trace?.Log($"IRInstructionCount: {MethodData.IRInstructionCount}"); trace?.Log($"IRStackParameterInstructionCount: {MethodData.IRStackParameterInstructionCount}"); trace?.Log($"InlinedIRMaximum: {CompilerOptions.InlinedIRMaximum}"); trace?.Log($"NonIRInstructionCount: {MethodData.NonIRInstructionCount}"); trace?.Log($"HasDoNotInlineAttribute: {MethodData.HasDoNotInlineAttribute}"); trace?.Log($"HasAggressiveInliningAttribute: {MethodData.HasAggressiveInliningAttribute}"); trace?.Log($"IsPlugged: {MethodData.IsMethodImplementationReplaced}"); trace?.Log($"HasAddressOfInstruction: {MethodData.HasAddressOfInstruction}"); trace?.Log($"CompileCount: {MethodData.CompileCount}"); InlinedMethodsCount.Set(inline); ReversedInlinedMethodsCount.Set(MethodData.CompileCount >= MaximumCompileCount); }