Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(583)

Unified Diff: runtime/vm/flow_graph_inliner.cc

Issue 211873003: Incremental tuning/cleanup of inlining: --print-inline-tree changed to --print-inlining-tree. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/flow_graph_inliner.h ('k') | runtime/vm/il_printer.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_inliner.cc
===================================================================
--- runtime/vm/flow_graph_inliner.cc (revision 34449)
+++ runtime/vm/flow_graph_inliner.cc (working copy)
@@ -47,7 +47,7 @@
"default 10%: calls above-equal 10% of max-count are inlined.");
DEFINE_FLAG(bool, inline_recursive, true,
"Inline recursive calls.");
-DEFINE_FLAG(bool, print_inline_tree, false, "Print inlining tree");
+DEFINE_FLAG(bool, print_inlining_tree, false, "Print inlining tree");
DECLARE_FLAG(bool, print_flow_graph);
DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -136,7 +136,7 @@
// parameters was fixed.
// TODO(fschneider): Determine new heuristic parameters that avoid
// these checks entirely.
- if (!call->HasRecognizedTarget() &&
+ if (!call->HasSingleRecognizedTarget() &&
(call->instance_call()->token_kind() != Token::kEQ)) {
++call_site_count_;
}
@@ -154,6 +154,26 @@
};
+// Structure for collecting inline data needed to print inlining tree.
+struct InlinedInfo {
+ const Function* caller;
+ const Function* inlined;
+ intptr_t inlined_depth;
+ const Definition* call_instr;
+ const char* bailout_reason;
+ InlinedInfo(const Function* caller_function,
+ const Function* inlined_function,
+ const intptr_t depth,
+ const Definition* call,
+ const char* reason = NULL)
+ : caller(caller_function),
+ inlined(inlined_function),
+ inlined_depth(depth),
+ call_instr(call),
+ bailout_reason(reason) {}
+};
+
+
// A collection of call sites to consider for inlining.
class CallSites : public ValueObject {
public:
@@ -254,14 +274,16 @@
}
}
- void FindCallSites(FlowGraph* graph, intptr_t depth) {
+ void FindCallSites(FlowGraph* graph,
+ intptr_t depth,
+ GrowableArray<InlinedInfo>* inlined_info) {
ASSERT(graph != NULL);
- // If depth is less than the threshold recursively add call sites.
+
if (depth > FLAG_inlining_depth_threshold) return;
// Recognized methods are not treated as normal calls. They don't have
// calls in themselves, so we keep adding those even when at the threshold.
- const bool only_recognized_methods =
+ const bool inline_only_recognized_methods =
(depth == FLAG_inlining_depth_threshold);
const intptr_t instance_call_start_ix = instance_calls_.length();
@@ -273,31 +295,45 @@
!it.Done();
it.Advance()) {
Instruction* current = it.Current();
- if (only_recognized_methods) {
+ if (current->IsPolymorphicInstanceCall()) {
PolymorphicInstanceCallInstr* instance_call =
current->AsPolymorphicInstanceCall();
- if ((instance_call != NULL) && instance_call->HasRecognizedTarget()) {
+ if (!inline_only_recognized_methods ||
+ instance_call->HasSingleRecognizedTarget()) {
instance_calls_.Add(InstanceCallInfo(instance_call, graph));
+ } else {
+ // Method not inlined because inlining too deep and method
+ // not recognized.
+ if (FLAG_print_inlining_tree) {
+ const Function* caller = &graph->parsed_function().function();
+ const Function* target =
+ &Function::ZoneHandle(
+ instance_call->ic_data().GetTargetAt(0));
+ inlined_info->Add(InlinedInfo(
+ caller, target, depth, instance_call, "Too deep"));
+ }
}
- continue;
+ } else if (current->IsStaticCall()) {
+ StaticCallInstr* static_call = current->AsStaticCall();
+ if (!inline_only_recognized_methods ||
+ static_call->function().is_recognized()) {
+ static_calls_.Add(StaticCallInfo(static_call, graph));
+ } else {
+ // Method not inlined because inlining too deep and method
+ // not recognized.
+ if (FLAG_print_inlining_tree) {
+ const Function* caller = &graph->parsed_function().function();
+ const Function* target = &static_call->function();
+ inlined_info->Add(InlinedInfo(
+ caller, target, depth, static_call, "Too deep"));
+ }
+ }
+ } else if (current->IsClosureCall()) {
+ if (!inline_only_recognized_methods) {
+ ClosureCallInstr* closure_call = current->AsClosureCall();
+ closure_calls_.Add(ClosureCallInfo(closure_call, graph));
+ }
}
- // Collect all call sites (!only_recognized_methods).
- ClosureCallInstr* closure_call = current->AsClosureCall();
- if (closure_call != NULL) {
- closure_calls_.Add(ClosureCallInfo(closure_call, graph));
- continue;
- }
- StaticCallInstr* static_call = current->AsStaticCall();
- if (static_call != NULL) {
- static_calls_.Add(StaticCallInfo(static_call, graph));
- continue;
- }
- PolymorphicInstanceCallInstr* instance_call =
- current->AsPolymorphicInstanceCall();
- if (instance_call != NULL) {
- instance_calls_.Add(InstanceCallInfo(instance_call, graph));
- continue;
- }
}
}
ComputeCallSiteRatio(static_call_start_ix, instance_call_start_ix);
@@ -321,34 +357,17 @@
callee_graph(NULL),
parameter_stubs(NULL),
exit_collector(NULL),
- caller_(caller) { }
+ caller(caller) { }
Definition* call;
GrowableArray<Value*>* arguments;
FlowGraph* callee_graph;
ZoneGrowableArray<Definition*>* parameter_stubs;
InlineExitCollector* exit_collector;
- const Function& caller_;
+ const Function& caller;
};
-// Structure for collecting inline data needed to print inlining tree.
-struct InlinedInfo {
- const Function* caller;
- const Function* inlined;
- intptr_t inlined_depth;
- const Definition* call_instr;
- InlinedInfo(const Function* caller_function,
- const Function* inlined_function,
- const intptr_t depth,
- const Definition* call)
- : caller(caller_function),
- inlined(inlined_function),
- inlined_depth(depth),
- call_instr(call) {}
-};
-
-
class CallSiteInliner;
class PolymorphicInliner : public ValueObject {
@@ -437,7 +456,9 @@
collected_call_sites_ = &sites1;
inlining_call_sites_ = &sites2;
// Collect initial call sites.
- collected_call_sites_->FindCallSites(caller_graph_, inlining_depth_);
+ collected_call_sites_->FindCallSites(caller_graph_,
+ inlining_depth_,
+ &inlined_info_);
while (collected_call_sites_->HasCalls()) {
TRACE_INLINING(OS::Print(" Depth %" Pd " ----------\n",
inlining_depth_));
@@ -475,6 +496,11 @@
if (call_data->call->GetBlock()->try_index() !=
CatchClauseNode::kInvalidTryIndex) {
TRACE_INLINING(OS::Print(" Bailout: inside try-block\n"));
+ if (FLAG_print_inlining_tree) {
+ inlined_info_.Add(InlinedInfo(
+ &call_data->caller, &function, inlining_depth_, call_data->call,
+ "Inside try-block"));
+ }
return false;
}
@@ -484,6 +510,11 @@
// Abort if the inlinable bit on the function is low.
if (!function.IsInlineable()) {
TRACE_INLINING(OS::Print(" Bailout: not inlinable\n"));
+ if (FLAG_print_inlining_tree) {
+ inlined_info_.Add(InlinedInfo(
+ &call_data->caller, &function, inlining_depth_, call_data->call,
+ "Not inlinable"));
+ }
return false;
}
@@ -492,6 +523,11 @@
FLAG_deoptimization_counter_threshold) {
function.set_is_inlinable(false);
TRACE_INLINING(OS::Print(" Bailout: deoptimization threshold\n"));
+ if (FLAG_print_inlining_tree) {
+ inlined_info_.Add(InlinedInfo(
+ &call_data->caller, &function, inlining_depth_, call_data->call,
+ "Deoptimization threshold exceeded"));
+ }
return false;
}
@@ -508,6 +544,11 @@
function.optimized_instruction_count(),
function.optimized_call_site_count(),
constant_arguments));
+ if (FLAG_print_inlining_tree) {
+ inlined_info_.Add(InlinedInfo(
+ &call_data->caller, &function, inlining_depth_, call_data->call,
+ "Early heuristic"));
+ }
return false;
}
@@ -634,11 +675,11 @@
for (intptr_t i = 0; i < param_stubs->length(); ++i) {
if ((*param_stubs)[i]->IsConstant()) ++constants_count;
}
- GraphInfoCollector info;
- info.Collect(*callee_graph);
- const intptr_t size = info.instruction_count();
- const intptr_t call_site_count = info.call_site_count();
+ FlowGraphInliner::CollectGraphInfo(callee_graph);
+ const intptr_t size = function.optimized_instruction_count();
+ const intptr_t call_site_count = function.optimized_call_site_count();
+
function.set_optimized_instruction_count(size);
function.set_optimized_call_site_count(call_site_count);
@@ -658,10 +699,17 @@
size,
call_site_count,
constants_count));
+ if (FLAG_print_inlining_tree) {
+ inlined_info_.Add(InlinedInfo(
+ &call_data->caller, &function, inlining_depth_, call_data->call,
+ "Heuristic fail"));
+ }
return false;
}
- collected_call_sites_->FindCallSites(callee_graph, inlining_depth_);
+ collected_call_sites_->FindCallSites(callee_graph,
+ inlining_depth_,
+ &inlined_info_);
// Add the function to the cache.
if (!in_cache) {
@@ -688,9 +736,9 @@
// disconnected from its function during the rest of compilation.
Code::ZoneHandle(unoptimized_code.raw());
TRACE_INLINING(OS::Print(" Success\n"));
- if (FLAG_print_inline_tree) {
+ if (FLAG_print_inlining_tree) {
inlined_info_.Add(
- InlinedInfo(&call_data->caller_, &function, inlining_depth_, call));
+ InlinedInfo(&call_data->caller, &function, inlining_depth_, call));
}
return true;
} else {
@@ -704,16 +752,24 @@
}
void PrintInlinedInfo(const Function& top) {
- OS::Print("Inlining into: %s\n", top.ToFullyQualifiedCString());
- PrintInlinedInfoFor(top, 1);
+ if (inlined_info_.length() > 0) {
+ OS::Print("Inlining into: '%s' growth: %f (%"Pd" -> %"Pd")\n",
+ top.ToFullyQualifiedCString(),
+ GrowthFactor(),
+ initial_size_,
+ inlined_size_);
+ PrintInlinedInfoFor(top, 1);
+ }
}
private:
friend class PolymorphicInliner;
void PrintInlinedInfoFor(const Function& caller, intptr_t depth) {
+ // Print those that were inlined.
for (intptr_t i = 0; i < inlined_info_.length(); i++) {
const InlinedInfo& info = inlined_info_[i];
+ if (info.bailout_reason != NULL) continue;
if ((info.inlined_depth == depth) &&
(info.caller->raw() == caller.raw())) {
for (int t = 0; t < depth; t++) {
@@ -725,6 +781,21 @@
PrintInlinedInfoFor(*info.inlined, depth + 1);
}
}
+ // Print those that were not inlined.
+ for (intptr_t i = 0; i < inlined_info_.length(); i++) {
+ const InlinedInfo& info = inlined_info_[i];
+ if (info.bailout_reason == NULL) continue;
+ if ((info.inlined_depth == depth) &&
+ (info.caller->raw() == caller.raw())) {
+ for (int t = 0; t < depth; t++) {
+ OS::Print(" ");
+ }
+ OS::Print("NO %" Pd " %s - %s\n",
+ info.call_instr->GetDeoptId(),
+ info.inlined->ToQualifiedCString(),
+ info.bailout_reason);
+ }
+ }
}
void InlineCall(InlinedCallData* call_data) {
@@ -843,6 +914,14 @@
target.ToCString(),
target.deoptimization_counter(),
call_info[call_idx].ratio));
+ if (FLAG_print_inlining_tree) {
+ inlined_info_.Add(InlinedInfo(
+ call_info[call_idx].caller,
+ &call->function(),
+ inlining_depth_,
+ call,
+ "Too cold"));
+ }
continue;
}
GrowableArray<Value*> arguments(call->ArgumentCount());
@@ -912,6 +991,14 @@
target.ToCString(),
target.deoptimization_counter(),
call_info[call_idx].ratio));
+ if (FLAG_print_inlining_tree) {
+ inlined_info_.Add(InlinedInfo(
+ call_info[call_idx].caller,
+ &target,
+ inlining_depth_,
+ call,
+ "Too cold"));
+ }
continue;
}
GrowableArray<Value*> arguments(call->ArgumentCount());
@@ -1021,7 +1108,7 @@
FlowGraph* caller_graph_;
bool inlined_;
- intptr_t initial_size_;
+ const intptr_t initial_size_;
intptr_t inlined_size_;
intptr_t inlining_depth_;
CallSites* collected_call_sites_;
@@ -1496,13 +1583,16 @@
}
-void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph) {
- GraphInfoCollector info;
- info.Collect(*flow_graph);
+void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph, bool force) {
const Function& function = flow_graph->parsed_function().function();
- function.set_optimized_instruction_count(
- ClampUint16(info.instruction_count()));
- function.set_optimized_call_site_count(ClampUint16(info.call_site_count()));
+ if (force || (function.optimized_instruction_count() == 0)) {
+ GraphInfoCollector info;
+ info.Collect(*flow_graph);
+
+ function.set_optimized_instruction_count(
+ ClampUint16(info.instruction_count()));
+ function.set_optimized_call_site_count(ClampUint16(info.call_site_count()));
+ }
}
@@ -1541,7 +1631,7 @@
CallSiteInliner inliner(flow_graph_);
inliner.InlineCalls();
- if (FLAG_print_inline_tree) {
+ if (FLAG_print_inlining_tree) {
inliner.PrintInlinedInfo(top);
}
« no previous file with comments | « runtime/vm/flow_graph_inliner.h ('k') | runtime/vm/il_printer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698