Chromium Code Reviews| Index: runtime/vm/compiler.cc |
| diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc |
| index 493cc0e67e0152d076e0aa67fc2c6cffbba69723..30d1c68babee06a8c63782ce126d3bf5ef4117c0 100644 |
| --- a/runtime/vm/compiler.cc |
| +++ b/runtime/vm/compiler.cc |
| @@ -414,6 +414,7 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| Thread* const thread = Thread::Current(); |
| Zone* const zone = thread->zone(); |
| Isolate* const isolate = thread->isolate(); |
| + TimelineStream* compiler_timeline = isolate->GetCompilerStream(); |
| CSTAT_TIMER_SCOPE(thread, codegen_timer); |
| HANDLESCOPE(thread); |
| @@ -475,6 +476,9 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| } |
| } |
| + TimelineDurationScope tds(thread, |
| + compiler_timeline, |
| + "BuildFlowGraph"); |
| flow_graph = pipeline->BuildFlowGraph(zone, |
| parsed_function, |
| *ic_data_array, |
| @@ -498,10 +502,16 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| const bool reorder_blocks = |
| FlowGraph::ShouldReorderBlocks(function, optimized); |
| if (reorder_blocks) { |
| + TimelineDurationScope tds(thread, |
| + compiler_timeline, |
| + "BlockScheduler::AssignEdgeWeights"); |
| block_scheduler.AssignEdgeWeights(); |
| } |
| if (optimized) { |
| + TimelineDurationScope tds(thread, |
| + compiler_timeline, |
| + "ComputeSSA"); |
| CSTAT_TIMER_SCOPE(thread, ssa_timer); |
| // Transform to SSA (virtual register 0 and no inlining arguments). |
| flow_graph->ComputeSSA(0, NULL); |
| @@ -520,6 +530,9 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| // have non-generic type feedback attached to them that can |
| // potentially affect optimizations. |
| if (optimized) { |
| + TimelineDurationScope tds(thread, |
| + compiler_timeline, |
| + "OptimizationPasses"); |
| inline_id_to_function.Add(&function); |
| // Top scope function has no caller (-1). |
| caller_inline_id.Add(-1); |
| @@ -549,6 +562,9 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| // Inlining (mutates the flow graph) |
| if (FLAG_use_inlining) { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "Inlining"); |
| CSTAT_TIMER_SCOPE(thread, graphinliner_timer); |
| // Propagate types to create more inlining opportunities. |
| FlowGraphTypePropagator::Propagate(flow_graph); |
| @@ -572,30 +588,48 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| FlowGraphTypePropagator::Propagate(flow_graph); |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| - // Use propagated class-ids to optimize further. |
| - optimizer.ApplyClassIds(); |
| - DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| + { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "ApplyClassIds"); |
| + // Use propagated class-ids to optimize further. |
| + optimizer.ApplyClassIds(); |
| + DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| + } |
| // Propagate types for potentially newly added instructions by |
| // ApplyClassIds(). Must occur before canonicalization. |
| FlowGraphTypePropagator::Propagate(flow_graph); |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| - // Do optimizations that depend on the propagated type information. |
| - if (optimizer.Canonicalize()) { |
| - // Invoke Canonicalize twice in order to fully canonicalize patterns |
| - // like "if (a & const == 0) { }". |
| - optimizer.Canonicalize(); |
| + { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "Canonicalize"); |
|
Florian Schneider
2015/12/15 17:15:35
Remove scope for canonicalize.
Cutch
2015/12/15 17:51:56
Done.
|
| + // Do optimizations that depend on the propagated type information. |
| + if (optimizer.Canonicalize()) { |
| + // Invoke Canonicalize twice in order to fully canonicalize patterns |
| + // like "if (a & const == 0) { }". |
| + optimizer.Canonicalize(); |
| + } |
| + DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| } |
| - DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| - BranchSimplifier::Simplify(flow_graph); |
| - DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| + { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "BranchSimplifier"); |
| + BranchSimplifier::Simplify(flow_graph); |
| + DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| - IfConverter::Simplify(flow_graph); |
| - DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| + IfConverter::Simplify(flow_graph); |
| + DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| + } |
| if (FLAG_constant_propagation) { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "ConstantPropagation"); |
| ConstantPropagator::Optimize(flow_graph); |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| // A canonicalization pass to remove e.g. smi checks on smi constants. |
| @@ -610,6 +644,9 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| // Optimistically convert loop phis that have a single non-smi input |
| // coming from the loop pre-header into smi-phis. |
| if (FLAG_loop_invariant_code_motion) { |
| + TimelineDurationScope tds2(thread, |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
|
| + compiler_timeline, |
| + "LICM"); |
| LICM licm(flow_graph); |
| licm.OptimisticallySpecializeSmiPhis(); |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| @@ -621,22 +658,38 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| FlowGraphTypePropagator::Propagate(flow_graph); |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| - // Where beneficial convert Smi operations into Int32 operations. |
| - // Only meanigful for 32bit platforms right now. |
| - optimizer.WidenSmiToInt32(); |
| + { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "WidenSmiToInt32"); |
| + // Where beneficial convert Smi operations into Int32 operations. |
| + // Only meanigful for 32bit platforms right now. |
| + optimizer.WidenSmiToInt32(); |
| + } |
| - // Unbox doubles. Performed after constant propagation to minimize |
| - // interference from phis merging double values and tagged |
| - // values coming from dead paths. |
| - optimizer.SelectRepresentations(); |
| - DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| + { |
| + TimelineDurationScope tds2(thread, |
|
Florian Schneider
2015/12/15 17:15:35
Merge with previous scope.
Cutch
2015/12/15 17:51:56
Done.
|
| + compiler_timeline, |
| + "UnboxSelectRepresentations"); |
| + // Unbox doubles. Performed after constant propagation to minimize |
| + // interference from phis merging double values and tagged |
| + // values coming from dead paths. |
| + optimizer.SelectRepresentations(); |
| + DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| + } |
|
Florian Schneider
2015/12/15 17:15:35
ComputeBlockEffects, CSE, LICM in one scope.
Cutch
2015/12/15 17:51:56
Done.
|
| if (FLAG_common_subexpression_elimination || |
| FLAG_loop_invariant_code_motion) { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "ComputeBlockEffects"); |
| flow_graph->ComputeBlockEffects(); |
| } |
| if (FLAG_common_subexpression_elimination) { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "DominatorBasedCSE"); |
| if (DominatorBasedCSE::Optimize(flow_graph)) { |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| optimizer.Canonicalize(); |
| @@ -653,6 +706,9 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| // Run loop-invariant code motion right after load elimination since it |
| // depends on the numbering of loads from the previous load-elimination. |
| if (FLAG_loop_invariant_code_motion) { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "LICM"); |
| LICM licm(flow_graph); |
| licm.Optimize(); |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| @@ -665,9 +721,17 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| optimizer.TryOptimizePatterns(); |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| - DeadStoreElimination::Optimize(flow_graph); |
| + { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "DeadStoreElimination"); |
| + DeadStoreElimination::Optimize(flow_graph); |
| + } |
| if (FLAG_range_analysis) { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "RangeAnalysis"); |
| // Propagate types after store-load-forwarding. Some phis may have |
| // become smi phis that can be processed by range analysis. |
| FlowGraphTypePropagator::Propagate(flow_graph); |
| @@ -681,6 +745,9 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| } |
| if (FLAG_constant_propagation) { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "ConstantPropagator::OptimizeBranches"); |
| // Constant propagation can use information from range analysis to |
| // find unreachable branch targets and eliminate branches that have |
| // the same true- and false-target. |
| @@ -693,18 +760,36 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| FlowGraphTypePropagator::Propagate(flow_graph); |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| - // Optimize try-blocks. |
| - TryCatchAnalyzer::Optimize(flow_graph); |
| + { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "TryCatchAnalyzer::Optimize"); |
| + // Optimize try-blocks. |
| + TryCatchAnalyzer::Optimize(flow_graph); |
| + } |
| - // Detach environments from the instructions that can't deoptimize. |
| - // Do it before we attempt to perform allocation sinking to minimize |
| - // amount of materializations it has to perform. |
| - optimizer.EliminateEnvironments(); |
| + { |
| + // Detach environments from the instructions that can't deoptimize. |
| + // Do it before we attempt to perform allocation sinking to minimize |
| + // amount of materializations it has to perform. |
| + TimelineDurationScope tds2(thread, |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
|
| + compiler_timeline, |
| + "EliminateEnvironments"); |
| + optimizer.EliminateEnvironments(); |
| + } |
| - DeadCodeElimination::EliminateDeadPhis(flow_graph); |
| - DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| + { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "EliminateDeadPhis"); |
| + DeadCodeElimination::EliminateDeadPhis(flow_graph); |
| + DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| + } |
| if (optimizer.Canonicalize()) { |
| + TimelineDurationScope tds2(thread, |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
|
| + compiler_timeline, |
| + "Canonicalize"); |
| optimizer.Canonicalize(); |
| } |
| @@ -713,6 +798,9 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| AllocationSinking* sinking = NULL; |
| if (FLAG_allocation_sinking && |
| (flow_graph->graph_entry()->SuccessorCount() == 1)) { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "AllocationSinking::Optimize"); |
| // TODO(fschneider): Support allocation sinking with try-catch. |
| sinking = new AllocationSinking(flow_graph); |
| sinking->Optimize(); |
| @@ -725,21 +813,35 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| FlowGraphTypePropagator::Propagate(flow_graph); |
| DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| - // Ensure that all phis inserted by optimization passes have consistent |
| - // representations. |
| - optimizer.SelectRepresentations(); |
| + { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "SelectRepresentations"); |
| + // Ensure that all phis inserted by optimization passes have |
| + // consistent representations. |
| + optimizer.SelectRepresentations(); |
| + } |
| - if (optimizer.Canonicalize()) { |
| - // To fully remove redundant boxing (e.g. BoxDouble used only in |
| - // environments and UnboxDouble instructions) instruction we |
| - // first need to replace all their uses and then fold them away. |
| - // For now we just repeat Canonicalize twice to do that. |
| - // TODO(vegorov): implement a separate representation folding pass. |
| - optimizer.Canonicalize(); |
| + { |
| + TimelineDurationScope tds2(thread, |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
|
| + compiler_timeline, |
| + "Canonicalize"); |
| + if (optimizer.Canonicalize()) { |
| + // To fully remove redundant boxing (e.g. BoxDouble used only in |
| + // environments and UnboxDouble instructions) instruction we |
| + // first need to replace all their uses and then fold them away. |
| + // For now we just repeat Canonicalize twice to do that. |
| + // TODO(vegorov): implement a separate representation folding pass. |
| + optimizer.Canonicalize(); |
| + } |
| + DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| } |
| - DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| if (sinking != NULL) { |
| + TimelineDurationScope tds2( |
| + thread, |
| + compiler_timeline, |
| + "AllocationSinking::DetachMaterializations"); |
| // Remove all MaterializeObject instructions inserted by allocation |
| // sinking from the flow graph and let them float on the side |
| // referenced only from environments. Register allocator will consider |
| @@ -747,14 +849,30 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| sinking->DetachMaterializations(); |
| } |
| - // Compute and store graph informations (call & instruction counts) |
| - // to be later used by the inliner. |
| - FlowGraphInliner::CollectGraphInfo(flow_graph, true); |
| + { |
| + TimelineDurationScope tds2(thread, |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
|
| + compiler_timeline, |
| + "CollectGraphInfo"); |
| + // Compute and store graph informations (call & instruction counts) |
| + // to be later used by the inliner. |
| + FlowGraphInliner::CollectGraphInfo(flow_graph, true); |
| + } |
| + |
| + { |
| + TimelineDurationScope tds2(thread, |
| + compiler_timeline, |
| + "AllocateRegisters"); |
| + // Perform register allocation on the SSA graph. |
| + FlowGraphAllocator allocator(*flow_graph); |
| + allocator.AllocateRegisters(); |
| + } |
| - // Perform register allocation on the SSA graph. |
| - FlowGraphAllocator allocator(*flow_graph); |
| - allocator.AllocateRegisters(); |
| - if (reorder_blocks) block_scheduler.ReorderBlocks(); |
| + if (reorder_blocks) { |
| + TimelineDurationScope tds(thread, |
| + compiler_timeline, |
| + "BlockScheduler::ReorderBlocks"); |
| + block_scheduler.ReorderBlocks(); |
| + } |
| if (print_flow_graph) { |
| FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); |
| @@ -769,10 +887,16 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
| caller_inline_id); |
| { |
| CSTAT_TIMER_SCOPE(thread, graphcompiler_timer); |
| + TimelineDurationScope tds(thread, |
| + compiler_timeline, |
| + "CompileGraph"); |
| graph_compiler.CompileGraph(); |
| pipeline->FinalizeCompilation(); |
| } |
| { |
| + TimelineDurationScope tds(thread, |
| + compiler_timeline, |
| + "FinalizeCompilation"); |
| // This part of compilation must be at a safepoint. |
| if (!Thread::Current()->IsMutatorThread()) { |
| // Stop mutator thread before creating the instruction object and |