Index: runtime/vm/compiler.cc |
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc |
index 493cc0e67e0152d076e0aa67fc2c6cffbba69723..66e0eef88acb40bd95f15cffa0cbae4d1b1b6594 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,9 +588,14 @@ 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. |
@@ -589,13 +610,21 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
} |
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. |
@@ -621,43 +650,54 @@ 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(); |
- |
- // 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()); |
- |
- if (FLAG_common_subexpression_elimination || |
- FLAG_loop_invariant_code_motion) { |
- flow_graph->ComputeBlockEffects(); |
+ { |
+ TimelineDurationScope tds2(thread, |
+ compiler_timeline, |
+ "SelectRepresentations"); |
+ // 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()); |
} |
- if (FLAG_common_subexpression_elimination) { |
- if (DominatorBasedCSE::Optimize(flow_graph)) { |
- DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
- optimizer.Canonicalize(); |
- // Do another round of CSE to take secondary effects into account: |
- // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) |
- // TODO(fschneider): Change to a one-pass optimization pass. |
+ { |
+ TimelineDurationScope tds2(thread, |
+ compiler_timeline, |
+ "CommonSubexpressionElinination"); |
+ if (FLAG_common_subexpression_elimination || |
+ FLAG_loop_invariant_code_motion) { |
+ flow_graph->ComputeBlockEffects(); |
+ } |
+ |
+ if (FLAG_common_subexpression_elimination) { |
if (DominatorBasedCSE::Optimize(flow_graph)) { |
+ DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
optimizer.Canonicalize(); |
+ // Do another round of CSE to take secondary effects into account: |
+ // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) |
+ // TODO(fschneider): Change to a one-pass optimization pass. |
+ if (DominatorBasedCSE::Optimize(flow_graph)) { |
+ optimizer.Canonicalize(); |
+ } |
+ DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
} |
- DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
} |
- } |
- // 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) { |
- LICM licm(flow_graph); |
- licm.Optimize(); |
- DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
+ // 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) { |
+ LICM licm(flow_graph); |
+ licm.Optimize(); |
+ DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
+ } |
+ flow_graph->RemoveRedefinitions(); |
} |
- flow_graph->RemoveRedefinitions(); |
// Optimize (a << b) & c patterns, merge operations. |
// Run after CSE in order to have more opportunity to merge |
@@ -665,9 +705,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 +729,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,16 +744,26 @@ 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(); |
- 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()) { |
optimizer.Canonicalize(); |
@@ -713,6 +774,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,9 +789,14 @@ 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 |
@@ -740,6 +809,10 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
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 |
@@ -751,10 +824,21 @@ static bool CompileParsedFunctionHelper(CompilationPipeline* pipeline, |
// to be later used by the inliner. |
FlowGraphInliner::CollectGraphInfo(flow_graph, true); |
- // Perform register allocation on the SSA graph. |
- FlowGraphAllocator allocator(*flow_graph); |
- allocator.AllocateRegisters(); |
- if (reorder_blocks) block_scheduler.ReorderBlocks(); |
+ { |
+ TimelineDurationScope tds2(thread, |
+ compiler_timeline, |
+ "AllocateRegisters"); |
+ // Perform register allocation on the SSA graph. |
+ FlowGraphAllocator allocator(*flow_graph); |
+ allocator.AllocateRegisters(); |
+ } |
+ |
+ 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 +853,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 |