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

Side by Side Diff: runtime/vm/flow_graph_inliner.cc

Issue 11975061: Removed loop depth info tracking at graph build time. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 11 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/flow_graph_optimizer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/flow_graph_inliner.h" 5 #include "vm/flow_graph_inliner.h"
6 6
7 #include "vm/compiler.h" 7 #include "vm/compiler.h"
8 #include "vm/flags.h" 8 #include "vm/flags.h"
9 #include "vm/flow_graph.h" 9 #include "vm/flow_graph.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
11 #include "vm/flow_graph_optimizer.h" 11 #include "vm/flow_graph_optimizer.h"
12 #include "vm/il_printer.h" 12 #include "vm/il_printer.h"
13 #include "vm/intrinsifier.h" 13 #include "vm/intrinsifier.h"
14 #include "vm/longjump.h" 14 #include "vm/longjump.h"
15 #include "vm/object.h" 15 #include "vm/object.h"
16 #include "vm/object_store.h" 16 #include "vm/object_store.h"
17 #include "vm/timer.h" 17 #include "vm/timer.h"
18 18
19 namespace dart { 19 namespace dart {
20 20
21 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining"); 21 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining");
22 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function"); 22 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function");
23 23
24 // Flags for inlining heuristics. 24 // Flags for inlining heuristics.
25 DEFINE_FLAG(int, inlining_depth_threshold, 3, 25 DEFINE_FLAG(int, inlining_depth_threshold, 3,
26 "Inline function calls up to threshold nesting depth"); 26 "Inline function calls up to threshold nesting depth");
27 DEFINE_FLAG(int, inlining_size_threshold, 20, 27 DEFINE_FLAG(int, inlining_size_threshold, 20,
28 "Always inline functions that have threshold or fewer instructions"); 28 "Always inline functions that have threshold or fewer instructions");
29 DEFINE_FLAG(int, inlining_in_loop_size_threshold, 80,
30 "Inline functions in loops that have threshold or fewer instructions");
31 DEFINE_FLAG(int, inlining_callee_call_sites_threshold, 1, 29 DEFINE_FLAG(int, inlining_callee_call_sites_threshold, 1,
32 "Always inline functions containing threshold or fewer calls."); 30 "Always inline functions containing threshold or fewer calls.");
33 DEFINE_FLAG(int, inlining_constant_arguments_count, 1, 31 DEFINE_FLAG(int, inlining_constant_arguments_count, 1,
34 "Inline function calls with sufficient constant arguments " 32 "Inline function calls with sufficient constant arguments "
35 "and up to the increased threshold on instructions"); 33 "and up to the increased threshold on instructions");
36 DEFINE_FLAG(int, inlining_constant_arguments_size_threshold, 60, 34 DEFINE_FLAG(int, inlining_constant_arguments_size_threshold, 60,
37 "Inline function calls with sufficient constant arguments " 35 "Inline function calls with sufficient constant arguments "
38 "and up to the increased threshold on instructions"); 36 "and up to the increased threshold on instructions");
39 DEFINE_FLAG(int, inlining_hotness, 10, 37 DEFINE_FLAG(int, inlining_hotness, 10,
40 "Inline only hotter calls, in percents (0 .. 100); " 38 "Inline only hotter calls, in percents (0 .. 100); "
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 : caller_graph_(flow_graph), 294 : caller_graph_(flow_graph),
297 inlined_(false), 295 inlined_(false),
298 initial_size_(flow_graph->InstructionCount()), 296 initial_size_(flow_graph->InstructionCount()),
299 inlined_size_(0), 297 inlined_size_(0),
300 inlining_depth_(1), 298 inlining_depth_(1),
301 collected_call_sites_(NULL), 299 collected_call_sites_(NULL),
302 inlining_call_sites_(NULL), 300 inlining_call_sites_(NULL),
303 function_cache_() { } 301 function_cache_() { }
304 302
305 // Inlining heuristics based on Cooper et al. 2008. 303 // Inlining heuristics based on Cooper et al. 2008.
306 bool ShouldWeInline(intptr_t loop_depth, 304 bool ShouldWeInline(intptr_t instr_count,
307 intptr_t instr_count,
308 intptr_t call_site_count, 305 intptr_t call_site_count,
309 intptr_t const_arg_count) { 306 intptr_t const_arg_count) {
310 if (instr_count <= FLAG_inlining_size_threshold) { 307 if (instr_count <= FLAG_inlining_size_threshold) {
311 return true; 308 return true;
312 } 309 }
313 if (call_site_count <= FLAG_inlining_callee_call_sites_threshold) { 310 if (call_site_count <= FLAG_inlining_callee_call_sites_threshold) {
314 return true; 311 return true;
315 } 312 }
316 if ((loop_depth > 0) &&
317 (instr_count <= FLAG_inlining_in_loop_size_threshold)) {
318 return true;
319 }
320 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && 313 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) &&
321 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { 314 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) {
322 return true; 315 return true;
323 } 316 }
324 return false; 317 return false;
325 } 318 }
326 319
327 // TODO(srdjan): Handle large 'skip_static_call_deopt_ids'. Currently 320 // TODO(srdjan): Handle large 'skip_static_call_deopt_ids'. Currently
328 // max. size observed is 11 (dart2js). 321 // max. size observed is 11 (dart2js).
329 void InlineCalls() { 322 void InlineCalls() {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 } 371 }
379 372
380 // Abort if this function has deoptimized too much. 373 // Abort if this function has deoptimized too much.
381 if (function.deoptimization_counter() >= 374 if (function.deoptimization_counter() >=
382 FLAG_deoptimization_counter_threshold) { 375 FLAG_deoptimization_counter_threshold) {
383 function.set_is_inlinable(false); 376 function.set_is_inlinable(false);
384 TRACE_INLINING(OS::Print(" Bailout: deoptimization threshold\n")); 377 TRACE_INLINING(OS::Print(" Bailout: deoptimization threshold\n"));
385 return false; 378 return false;
386 } 379 }
387 380
388 const intptr_t loop_depth = call->GetBlock()->loop_depth();
389 const intptr_t constant_arguments = CountConstants(*arguments); 381 const intptr_t constant_arguments = CountConstants(*arguments);
390 if (!ShouldWeInline(loop_depth, 382 if (!ShouldWeInline(function.optimized_instruction_count(),
391 function.optimized_instruction_count(),
392 function.optimized_call_site_count(), 383 function.optimized_call_site_count(),
393 constant_arguments)) { 384 constant_arguments)) {
394 TRACE_INLINING(OS::Print(" Bailout: early heuristics with " 385 TRACE_INLINING(OS::Print(" Bailout: early heuristics with "
395 "loop depth: %"Pd", "
396 "code size: %"Pd", " 386 "code size: %"Pd", "
397 "call sites: %"Pd", " 387 "call sites: %"Pd", "
398 "const args: %"Pd"\n", 388 "const args: %"Pd"\n",
399 loop_depth,
400 function.optimized_instruction_count(), 389 function.optimized_instruction_count(),
401 function.optimized_call_site_count(), 390 function.optimized_call_site_count(),
402 constant_arguments)); 391 constant_arguments));
403 return false; 392 return false;
404 } 393 }
405 394
406 // Abort if this is a recursive occurrence. 395 // Abort if this is a recursive occurrence.
407 if (IsCallRecursive(function, call)) { 396 if (IsCallRecursive(function, call)) {
408 function.set_is_inlinable(false); 397 function.set_is_inlinable(false);
409 TRACE_INLINING(OS::Print(" Bailout: recursive function\n")); 398 TRACE_INLINING(OS::Print(" Bailout: recursive function\n"));
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 437
449 // Build the callee graph. 438 // Build the callee graph.
450 ValueInliningContext* inlining_context = new ValueInliningContext(); 439 ValueInliningContext* inlining_context = new ValueInliningContext();
451 FlowGraphBuilder builder(*parsed_function, inlining_context); 440 FlowGraphBuilder builder(*parsed_function, inlining_context);
452 builder.SetInitialBlockId(caller_graph_->max_block_id()); 441 builder.SetInitialBlockId(caller_graph_->max_block_id());
453 FlowGraph* callee_graph; 442 FlowGraph* callee_graph;
454 { 443 {
455 TimerScope timer(FLAG_compiler_stats, 444 TimerScope timer(FLAG_compiler_stats,
456 &CompilerStats::graphinliner_build_timer, 445 &CompilerStats::graphinliner_build_timer,
457 isolate); 446 isolate);
458 callee_graph = builder.BuildGraph(loop_depth); 447 callee_graph = builder.BuildGraph();
459 } 448 }
460 449
461 // The parameter stubs are a copy of the actual arguments providing 450 // The parameter stubs are a copy of the actual arguments providing
462 // concrete information about the values, for example constant values, 451 // concrete information about the values, for example constant values,
463 // without linking between the caller and callee graphs. 452 // without linking between the caller and callee graphs.
464 // TODO(zerny): Put more information in the stubs, eg, type information. 453 // TODO(zerny): Put more information in the stubs, eg, type information.
465 GrowableArray<Definition*> param_stubs(function.NumParameters()); 454 GrowableArray<Definition*> param_stubs(function.NumParameters());
466 455
467 // Create a parameter stub for each fixed positional parameter. 456 // Create a parameter stub for each fixed positional parameter.
468 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { 457 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 if (param_stubs[i]->IsConstant()) ++constants_count; 519 if (param_stubs[i]->IsConstant()) ++constants_count;
531 } 520 }
532 GraphInfoCollector info; 521 GraphInfoCollector info;
533 info.Collect(*callee_graph); 522 info.Collect(*callee_graph);
534 const intptr_t size = info.instruction_count(); 523 const intptr_t size = info.instruction_count();
535 524
536 function.set_optimized_instruction_count(size); 525 function.set_optimized_instruction_count(size);
537 function.set_optimized_call_site_count(info.call_site_count()); 526 function.set_optimized_call_site_count(info.call_site_count());
538 527
539 // Use heuristics do decide if this call should be inlined. 528 // Use heuristics do decide if this call should be inlined.
540 if (!ShouldWeInline(loop_depth, 529 if (!ShouldWeInline(size,
541 size,
542 info.call_site_count(), 530 info.call_site_count(),
543 constants_count)) { 531 constants_count)) {
544 // If size is larger than all thresholds, don't consider it again. 532 // If size is larger than all thresholds, don't consider it again.
545 if ((size > FLAG_inlining_size_threshold) && 533 if ((size > FLAG_inlining_size_threshold) &&
546 (size > FLAG_inlining_in_loop_size_threshold) &&
547 (size > FLAG_inlining_callee_call_sites_threshold) && 534 (size > FLAG_inlining_callee_call_sites_threshold) &&
548 (size > FLAG_inlining_constant_arguments_size_threshold)) { 535 (size > FLAG_inlining_constant_arguments_size_threshold)) {
549 function.set_is_inlinable(false); 536 function.set_is_inlinable(false);
550 } 537 }
551 isolate->set_long_jump_base(base); 538 isolate->set_long_jump_base(base);
552 isolate->set_deopt_id(prev_deopt_id); 539 isolate->set_deopt_id(prev_deopt_id);
553 isolate->set_ic_data_array(prev_ic_data.raw()); 540 isolate->set_ic_data_array(prev_ic_data.raw());
554 TRACE_INLINING(OS::Print(" Bailout: heuristics with " 541 TRACE_INLINING(OS::Print(" Bailout: heuristics with "
555 "loop depth: %"Pd", "
556 "code size: %"Pd", " 542 "code size: %"Pd", "
557 "call sites: %"Pd", " 543 "call sites: %"Pd", "
558 "const args: %"Pd"\n", 544 "const args: %"Pd"\n",
559 loop_depth,
560 size, 545 size,
561 info.call_site_count(), 546 info.call_site_count(),
562 constants_count)); 547 constants_count));
563 return false; 548 return false;
564 } 549 }
565 550
566 // If depth is less or equal to threshold recursively add call sites. 551 // If depth is less or equal to threshold recursively add call sites.
567 if (inlining_depth_ < FLAG_inlining_depth_threshold) { 552 if (inlining_depth_ < FLAG_inlining_depth_threshold) {
568 collected_call_sites_->FindCallSites(callee_graph); 553 collected_call_sites_->FindCallSites(callee_graph);
569 } 554 }
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 OS::Print("After Inlining of %s\n", flow_graph_-> 868 OS::Print("After Inlining of %s\n", flow_graph_->
884 parsed_function().function().ToFullyQualifiedCString()); 869 parsed_function().function().ToFullyQualifiedCString());
885 FlowGraphPrinter printer(*flow_graph_); 870 FlowGraphPrinter printer(*flow_graph_);
886 printer.PrintBlocks(); 871 printer.PrintBlocks();
887 } 872 }
888 } 873 }
889 } 874 }
890 } 875 }
891 876
892 } // namespace dart 877 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/flow_graph_optimizer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698