Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/compiler.h" | 5 #include "vm/compiler.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 | 8 |
| 9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
| 10 #include "vm/block_scheduler.h" | 10 #include "vm/block_scheduler.h" |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 407 bool optimized, | 407 bool optimized, |
| 408 intptr_t osr_id) { | 408 intptr_t osr_id) { |
| 409 const Function& function = parsed_function->function(); | 409 const Function& function = parsed_function->function(); |
| 410 if (optimized && !function.IsOptimizable()) { | 410 if (optimized && !function.IsOptimizable()) { |
| 411 return false; | 411 return false; |
| 412 } | 412 } |
| 413 bool is_compiled = false; | 413 bool is_compiled = false; |
| 414 Thread* const thread = Thread::Current(); | 414 Thread* const thread = Thread::Current(); |
| 415 Zone* const zone = thread->zone(); | 415 Zone* const zone = thread->zone(); |
| 416 Isolate* const isolate = thread->isolate(); | 416 Isolate* const isolate = thread->isolate(); |
| 417 TimelineStream* compiler_timeline = isolate->GetCompilerStream(); | |
| 417 CSTAT_TIMER_SCOPE(thread, codegen_timer); | 418 CSTAT_TIMER_SCOPE(thread, codegen_timer); |
| 418 HANDLESCOPE(thread); | 419 HANDLESCOPE(thread); |
| 419 | 420 |
| 420 // Get current generation count so that we can check and ensure that the code | 421 // Get current generation count so that we can check and ensure that the code |
| 421 // was not invalidated while we were compiling in the background. | 422 // was not invalidated while we were compiling in the background. |
| 422 uint32_t cha_invalidation_gen_at_start = isolate->cha_invalidation_gen(); | 423 uint32_t cha_invalidation_gen_at_start = isolate->cha_invalidation_gen(); |
| 423 uint32_t field_invalidation_gen_at_start = isolate->field_invalidation_gen(); | 424 uint32_t field_invalidation_gen_at_start = isolate->field_invalidation_gen(); |
| 424 uint32_t prefix_invalidation_gen_at_start = | 425 uint32_t prefix_invalidation_gen_at_start = |
| 425 isolate->prefix_invalidation_gen(); | 426 isolate->prefix_invalidation_gen(); |
| 426 | 427 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 if (FLAG_print_ic_data_map) { | 469 if (FLAG_print_ic_data_map) { |
| 469 for (intptr_t i = 0; i < ic_data_array->length(); i++) { | 470 for (intptr_t i = 0; i < ic_data_array->length(); i++) { |
| 470 if ((*ic_data_array)[i] != NULL) { | 471 if ((*ic_data_array)[i] != NULL) { |
| 471 THR_Print("%" Pd " ", i); | 472 THR_Print("%" Pd " ", i); |
| 472 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]); | 473 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]); |
| 473 } | 474 } |
| 474 } | 475 } |
| 475 } | 476 } |
| 476 } | 477 } |
| 477 | 478 |
| 479 TimelineDurationScope tds(thread, | |
| 480 compiler_timeline, | |
| 481 "BuildFlowGraph"); | |
| 478 flow_graph = pipeline->BuildFlowGraph(zone, | 482 flow_graph = pipeline->BuildFlowGraph(zone, |
| 479 parsed_function, | 483 parsed_function, |
| 480 *ic_data_array, | 484 *ic_data_array, |
| 481 osr_id); | 485 osr_id); |
| 482 } | 486 } |
| 483 | 487 |
| 484 const bool print_flow_graph = | 488 const bool print_flow_graph = |
| 485 (FLAG_print_flow_graph || | 489 (FLAG_print_flow_graph || |
| 486 (optimized && FLAG_print_flow_graph_optimized)) && | 490 (optimized && FLAG_print_flow_graph_optimized)) && |
| 487 FlowGraphPrinter::ShouldPrint(function); | 491 FlowGraphPrinter::ShouldPrint(function); |
| 488 | 492 |
| 489 if (print_flow_graph) { | 493 if (print_flow_graph) { |
| 490 if (osr_id == Compiler::kNoOSRDeoptId) { | 494 if (osr_id == Compiler::kNoOSRDeoptId) { |
| 491 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); | 495 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); |
| 492 } else { | 496 } else { |
| 493 FlowGraphPrinter::PrintGraph("For OSR", flow_graph); | 497 FlowGraphPrinter::PrintGraph("For OSR", flow_graph); |
| 494 } | 498 } |
| 495 } | 499 } |
| 496 | 500 |
| 497 BlockScheduler block_scheduler(flow_graph); | 501 BlockScheduler block_scheduler(flow_graph); |
| 498 const bool reorder_blocks = | 502 const bool reorder_blocks = |
| 499 FlowGraph::ShouldReorderBlocks(function, optimized); | 503 FlowGraph::ShouldReorderBlocks(function, optimized); |
| 500 if (reorder_blocks) { | 504 if (reorder_blocks) { |
| 505 TimelineDurationScope tds(thread, | |
| 506 compiler_timeline, | |
| 507 "BlockScheduler::AssignEdgeWeights"); | |
| 501 block_scheduler.AssignEdgeWeights(); | 508 block_scheduler.AssignEdgeWeights(); |
| 502 } | 509 } |
| 503 | 510 |
| 504 if (optimized) { | 511 if (optimized) { |
| 512 TimelineDurationScope tds(thread, | |
| 513 compiler_timeline, | |
| 514 "ComputeSSA"); | |
| 505 CSTAT_TIMER_SCOPE(thread, ssa_timer); | 515 CSTAT_TIMER_SCOPE(thread, ssa_timer); |
| 506 // Transform to SSA (virtual register 0 and no inlining arguments). | 516 // Transform to SSA (virtual register 0 and no inlining arguments). |
| 507 flow_graph->ComputeSSA(0, NULL); | 517 flow_graph->ComputeSSA(0, NULL); |
| 508 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 518 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 509 if (print_flow_graph) { | 519 if (print_flow_graph) { |
| 510 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); | 520 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); |
| 511 } | 521 } |
| 512 } | 522 } |
| 513 | 523 |
| 514 // Maps inline_id_to_function[inline_id] -> function. Top scope | 524 // Maps inline_id_to_function[inline_id] -> function. Top scope |
| 515 // function has inline_id 0. The map is populated by the inliner. | 525 // function has inline_id 0. The map is populated by the inliner. |
| 516 GrowableArray<const Function*> inline_id_to_function; | 526 GrowableArray<const Function*> inline_id_to_function; |
| 517 // For a given inlining-id(index) specifies the caller's inlining-id. | 527 // For a given inlining-id(index) specifies the caller's inlining-id. |
| 518 GrowableArray<intptr_t> caller_inline_id; | 528 GrowableArray<intptr_t> caller_inline_id; |
| 519 // Collect all instance fields that are loaded in the graph and | 529 // Collect all instance fields that are loaded in the graph and |
| 520 // have non-generic type feedback attached to them that can | 530 // have non-generic type feedback attached to them that can |
| 521 // potentially affect optimizations. | 531 // potentially affect optimizations. |
| 522 if (optimized) { | 532 if (optimized) { |
| 533 TimelineDurationScope tds(thread, | |
| 534 compiler_timeline, | |
| 535 "OptimizationPasses"); | |
| 523 inline_id_to_function.Add(&function); | 536 inline_id_to_function.Add(&function); |
| 524 // Top scope function has no caller (-1). | 537 // Top scope function has no caller (-1). |
| 525 caller_inline_id.Add(-1); | 538 caller_inline_id.Add(-1); |
| 526 CSTAT_TIMER_SCOPE(thread, graphoptimizer_timer); | 539 CSTAT_TIMER_SCOPE(thread, graphoptimizer_timer); |
| 527 | 540 |
| 528 FlowGraphOptimizer optimizer(flow_graph, | 541 FlowGraphOptimizer optimizer(flow_graph, |
| 529 use_speculative_inlining, | 542 use_speculative_inlining, |
| 530 &inlining_black_list); | 543 &inlining_black_list); |
| 531 if (Compiler::always_optimize()) { | 544 if (Compiler::always_optimize()) { |
| 532 optimizer.PopulateWithICData(); | 545 optimizer.PopulateWithICData(); |
| 533 | 546 |
| 534 optimizer.ApplyClassIds(); | 547 optimizer.ApplyClassIds(); |
| 535 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 548 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 536 | 549 |
| 537 FlowGraphTypePropagator::Propagate(flow_graph); | 550 FlowGraphTypePropagator::Propagate(flow_graph); |
| 538 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 551 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 539 } | 552 } |
| 540 optimizer.ApplyICData(); | 553 optimizer.ApplyICData(); |
| 541 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 554 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 542 | 555 |
| 543 // Optimize (a << b) & c patterns, merge operations. | 556 // Optimize (a << b) & c patterns, merge operations. |
| 544 // Run early in order to have more opportunity to optimize left shifts. | 557 // Run early in order to have more opportunity to optimize left shifts. |
| 545 optimizer.TryOptimizePatterns(); | 558 optimizer.TryOptimizePatterns(); |
| 546 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 559 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 547 | 560 |
| 548 FlowGraphInliner::SetInliningId(flow_graph, 0); | 561 FlowGraphInliner::SetInliningId(flow_graph, 0); |
| 549 | 562 |
| 550 // Inlining (mutates the flow graph) | 563 // Inlining (mutates the flow graph) |
| 551 if (FLAG_use_inlining) { | 564 if (FLAG_use_inlining) { |
| 565 TimelineDurationScope tds2(thread, | |
| 566 compiler_timeline, | |
| 567 "Inlining"); | |
| 552 CSTAT_TIMER_SCOPE(thread, graphinliner_timer); | 568 CSTAT_TIMER_SCOPE(thread, graphinliner_timer); |
| 553 // Propagate types to create more inlining opportunities. | 569 // Propagate types to create more inlining opportunities. |
| 554 FlowGraphTypePropagator::Propagate(flow_graph); | 570 FlowGraphTypePropagator::Propagate(flow_graph); |
| 555 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 571 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 556 | 572 |
| 557 // Use propagated class-ids to create more inlining opportunities. | 573 // Use propagated class-ids to create more inlining opportunities. |
| 558 optimizer.ApplyClassIds(); | 574 optimizer.ApplyClassIds(); |
| 559 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 575 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 560 | 576 |
| 561 FlowGraphInliner inliner(flow_graph, | 577 FlowGraphInliner inliner(flow_graph, |
| 562 &inline_id_to_function, | 578 &inline_id_to_function, |
| 563 &caller_inline_id, | 579 &caller_inline_id, |
| 564 use_speculative_inlining, | 580 use_speculative_inlining, |
| 565 &inlining_black_list); | 581 &inlining_black_list); |
| 566 inliner.Inline(); | 582 inliner.Inline(); |
| 567 // Use lists are maintained and validated by the inliner. | 583 // Use lists are maintained and validated by the inliner. |
| 568 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 584 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 569 } | 585 } |
| 570 | 586 |
| 571 // Propagate types and eliminate more type tests. | 587 // Propagate types and eliminate more type tests. |
| 572 FlowGraphTypePropagator::Propagate(flow_graph); | 588 FlowGraphTypePropagator::Propagate(flow_graph); |
| 573 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 589 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 574 | 590 |
| 575 // Use propagated class-ids to optimize further. | 591 { |
| 576 optimizer.ApplyClassIds(); | 592 TimelineDurationScope tds2(thread, |
| 577 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 593 compiler_timeline, |
| 594 "ApplyClassIds"); | |
| 595 // Use propagated class-ids to optimize further. | |
| 596 optimizer.ApplyClassIds(); | |
| 597 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
| 598 } | |
| 578 | 599 |
| 579 // Propagate types for potentially newly added instructions by | 600 // Propagate types for potentially newly added instructions by |
| 580 // ApplyClassIds(). Must occur before canonicalization. | 601 // ApplyClassIds(). Must occur before canonicalization. |
| 581 FlowGraphTypePropagator::Propagate(flow_graph); | 602 FlowGraphTypePropagator::Propagate(flow_graph); |
| 582 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 603 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 583 | 604 |
| 584 // Do optimizations that depend on the propagated type information. | 605 { |
| 585 if (optimizer.Canonicalize()) { | 606 TimelineDurationScope tds2(thread, |
| 586 // Invoke Canonicalize twice in order to fully canonicalize patterns | 607 compiler_timeline, |
| 587 // like "if (a & const == 0) { }". | 608 "Canonicalize"); |
|
Florian Schneider
2015/12/15 17:15:35
Remove scope for canonicalize.
Cutch
2015/12/15 17:51:56
Done.
| |
| 588 optimizer.Canonicalize(); | 609 // Do optimizations that depend on the propagated type information. |
| 610 if (optimizer.Canonicalize()) { | |
| 611 // Invoke Canonicalize twice in order to fully canonicalize patterns | |
| 612 // like "if (a & const == 0) { }". | |
| 613 optimizer.Canonicalize(); | |
| 614 } | |
| 615 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
| 589 } | 616 } |
| 590 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
| 591 | 617 |
| 592 BranchSimplifier::Simplify(flow_graph); | 618 { |
| 593 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 619 TimelineDurationScope tds2(thread, |
| 620 compiler_timeline, | |
| 621 "BranchSimplifier"); | |
| 622 BranchSimplifier::Simplify(flow_graph); | |
| 623 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
| 594 | 624 |
| 595 IfConverter::Simplify(flow_graph); | 625 IfConverter::Simplify(flow_graph); |
| 596 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 626 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 627 } | |
| 597 | 628 |
| 598 if (FLAG_constant_propagation) { | 629 if (FLAG_constant_propagation) { |
| 630 TimelineDurationScope tds2(thread, | |
| 631 compiler_timeline, | |
| 632 "ConstantPropagation"); | |
| 599 ConstantPropagator::Optimize(flow_graph); | 633 ConstantPropagator::Optimize(flow_graph); |
| 600 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 634 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 601 // A canonicalization pass to remove e.g. smi checks on smi constants. | 635 // A canonicalization pass to remove e.g. smi checks on smi constants. |
| 602 optimizer.Canonicalize(); | 636 optimizer.Canonicalize(); |
| 603 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 637 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 604 // Canonicalization introduced more opportunities for constant | 638 // Canonicalization introduced more opportunities for constant |
| 605 // propagation. | 639 // propagation. |
| 606 ConstantPropagator::Optimize(flow_graph); | 640 ConstantPropagator::Optimize(flow_graph); |
| 607 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 641 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 608 } | 642 } |
| 609 | 643 |
| 610 // Optimistically convert loop phis that have a single non-smi input | 644 // Optimistically convert loop phis that have a single non-smi input |
| 611 // coming from the loop pre-header into smi-phis. | 645 // coming from the loop pre-header into smi-phis. |
| 612 if (FLAG_loop_invariant_code_motion) { | 646 if (FLAG_loop_invariant_code_motion) { |
| 647 TimelineDurationScope tds2(thread, | |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
| |
| 648 compiler_timeline, | |
| 649 "LICM"); | |
| 613 LICM licm(flow_graph); | 650 LICM licm(flow_graph); |
| 614 licm.OptimisticallySpecializeSmiPhis(); | 651 licm.OptimisticallySpecializeSmiPhis(); |
| 615 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 652 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 616 } | 653 } |
| 617 | 654 |
| 618 // Propagate types and eliminate even more type tests. | 655 // Propagate types and eliminate even more type tests. |
| 619 // Recompute types after constant propagation to infer more precise | 656 // Recompute types after constant propagation to infer more precise |
| 620 // types for uses that were previously reached by now eliminated phis. | 657 // types for uses that were previously reached by now eliminated phis. |
| 621 FlowGraphTypePropagator::Propagate(flow_graph); | 658 FlowGraphTypePropagator::Propagate(flow_graph); |
| 622 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 659 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 623 | 660 |
| 624 // Where beneficial convert Smi operations into Int32 operations. | 661 { |
| 625 // Only meanigful for 32bit platforms right now. | 662 TimelineDurationScope tds2(thread, |
| 626 optimizer.WidenSmiToInt32(); | 663 compiler_timeline, |
| 664 "WidenSmiToInt32"); | |
| 665 // Where beneficial convert Smi operations into Int32 operations. | |
| 666 // Only meanigful for 32bit platforms right now. | |
| 667 optimizer.WidenSmiToInt32(); | |
| 668 } | |
| 627 | 669 |
| 628 // Unbox doubles. Performed after constant propagation to minimize | 670 { |
| 629 // interference from phis merging double values and tagged | 671 TimelineDurationScope tds2(thread, |
|
Florian Schneider
2015/12/15 17:15:35
Merge with previous scope.
Cutch
2015/12/15 17:51:56
Done.
| |
| 630 // values coming from dead paths. | 672 compiler_timeline, |
| 631 optimizer.SelectRepresentations(); | 673 "UnboxSelectRepresentations"); |
| 632 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 674 // Unbox doubles. Performed after constant propagation to minimize |
| 675 // interference from phis merging double values and tagged | |
| 676 // values coming from dead paths. | |
| 677 optimizer.SelectRepresentations(); | |
| 678 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
| 679 } | |
| 633 | 680 |
|
Florian Schneider
2015/12/15 17:15:35
ComputeBlockEffects, CSE, LICM in one scope.
Cutch
2015/12/15 17:51:56
Done.
| |
| 634 if (FLAG_common_subexpression_elimination || | 681 if (FLAG_common_subexpression_elimination || |
| 635 FLAG_loop_invariant_code_motion) { | 682 FLAG_loop_invariant_code_motion) { |
| 683 TimelineDurationScope tds2(thread, | |
| 684 compiler_timeline, | |
| 685 "ComputeBlockEffects"); | |
| 636 flow_graph->ComputeBlockEffects(); | 686 flow_graph->ComputeBlockEffects(); |
| 637 } | 687 } |
| 638 | 688 |
| 639 if (FLAG_common_subexpression_elimination) { | 689 if (FLAG_common_subexpression_elimination) { |
| 690 TimelineDurationScope tds2(thread, | |
| 691 compiler_timeline, | |
| 692 "DominatorBasedCSE"); | |
| 640 if (DominatorBasedCSE::Optimize(flow_graph)) { | 693 if (DominatorBasedCSE::Optimize(flow_graph)) { |
| 641 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 694 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 642 optimizer.Canonicalize(); | 695 optimizer.Canonicalize(); |
| 643 // Do another round of CSE to take secondary effects into account: | 696 // Do another round of CSE to take secondary effects into account: |
| 644 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) | 697 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) |
| 645 // TODO(fschneider): Change to a one-pass optimization pass. | 698 // TODO(fschneider): Change to a one-pass optimization pass. |
| 646 if (DominatorBasedCSE::Optimize(flow_graph)) { | 699 if (DominatorBasedCSE::Optimize(flow_graph)) { |
| 647 optimizer.Canonicalize(); | 700 optimizer.Canonicalize(); |
| 648 } | 701 } |
| 649 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 702 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 650 } | 703 } |
| 651 } | 704 } |
| 652 | 705 |
| 653 // Run loop-invariant code motion right after load elimination since it | 706 // Run loop-invariant code motion right after load elimination since it |
| 654 // depends on the numbering of loads from the previous load-elimination. | 707 // depends on the numbering of loads from the previous load-elimination. |
| 655 if (FLAG_loop_invariant_code_motion) { | 708 if (FLAG_loop_invariant_code_motion) { |
| 709 TimelineDurationScope tds2(thread, | |
| 710 compiler_timeline, | |
| 711 "LICM"); | |
| 656 LICM licm(flow_graph); | 712 LICM licm(flow_graph); |
| 657 licm.Optimize(); | 713 licm.Optimize(); |
| 658 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 714 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 659 } | 715 } |
| 660 flow_graph->RemoveRedefinitions(); | 716 flow_graph->RemoveRedefinitions(); |
| 661 | 717 |
| 662 // Optimize (a << b) & c patterns, merge operations. | 718 // Optimize (a << b) & c patterns, merge operations. |
| 663 // Run after CSE in order to have more opportunity to merge | 719 // Run after CSE in order to have more opportunity to merge |
| 664 // instructions that have same inputs. | 720 // instructions that have same inputs. |
| 665 optimizer.TryOptimizePatterns(); | 721 optimizer.TryOptimizePatterns(); |
| 666 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 722 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 667 | 723 |
| 668 DeadStoreElimination::Optimize(flow_graph); | 724 { |
| 725 TimelineDurationScope tds2(thread, | |
| 726 compiler_timeline, | |
| 727 "DeadStoreElimination"); | |
| 728 DeadStoreElimination::Optimize(flow_graph); | |
| 729 } | |
| 669 | 730 |
| 670 if (FLAG_range_analysis) { | 731 if (FLAG_range_analysis) { |
| 732 TimelineDurationScope tds2(thread, | |
| 733 compiler_timeline, | |
| 734 "RangeAnalysis"); | |
| 671 // Propagate types after store-load-forwarding. Some phis may have | 735 // Propagate types after store-load-forwarding. Some phis may have |
| 672 // become smi phis that can be processed by range analysis. | 736 // become smi phis that can be processed by range analysis. |
| 673 FlowGraphTypePropagator::Propagate(flow_graph); | 737 FlowGraphTypePropagator::Propagate(flow_graph); |
| 674 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 738 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 675 | 739 |
| 676 // We have to perform range analysis after LICM because it | 740 // We have to perform range analysis after LICM because it |
| 677 // optimistically moves CheckSmi through phis into loop preheaders | 741 // optimistically moves CheckSmi through phis into loop preheaders |
| 678 // making some phis smi. | 742 // making some phis smi. |
| 679 optimizer.InferIntRanges(); | 743 optimizer.InferIntRanges(); |
| 680 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 744 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 681 } | 745 } |
| 682 | 746 |
| 683 if (FLAG_constant_propagation) { | 747 if (FLAG_constant_propagation) { |
| 748 TimelineDurationScope tds2(thread, | |
| 749 compiler_timeline, | |
| 750 "ConstantPropagator::OptimizeBranches"); | |
| 684 // Constant propagation can use information from range analysis to | 751 // Constant propagation can use information from range analysis to |
| 685 // find unreachable branch targets and eliminate branches that have | 752 // find unreachable branch targets and eliminate branches that have |
| 686 // the same true- and false-target. | 753 // the same true- and false-target. |
| 687 ConstantPropagator::OptimizeBranches(flow_graph); | 754 ConstantPropagator::OptimizeBranches(flow_graph); |
| 688 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 755 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 689 } | 756 } |
| 690 | 757 |
| 691 // Recompute types after code movement was done to ensure correct | 758 // Recompute types after code movement was done to ensure correct |
| 692 // reaching types for hoisted values. | 759 // reaching types for hoisted values. |
| 693 FlowGraphTypePropagator::Propagate(flow_graph); | 760 FlowGraphTypePropagator::Propagate(flow_graph); |
| 694 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 761 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 695 | 762 |
| 696 // Optimize try-blocks. | 763 { |
| 697 TryCatchAnalyzer::Optimize(flow_graph); | 764 TimelineDurationScope tds2(thread, |
| 765 compiler_timeline, | |
| 766 "TryCatchAnalyzer::Optimize"); | |
| 767 // Optimize try-blocks. | |
| 768 TryCatchAnalyzer::Optimize(flow_graph); | |
| 769 } | |
| 698 | 770 |
| 699 // Detach environments from the instructions that can't deoptimize. | 771 { |
| 700 // Do it before we attempt to perform allocation sinking to minimize | 772 // Detach environments from the instructions that can't deoptimize. |
| 701 // amount of materializations it has to perform. | 773 // Do it before we attempt to perform allocation sinking to minimize |
| 702 optimizer.EliminateEnvironments(); | 774 // amount of materializations it has to perform. |
| 775 TimelineDurationScope tds2(thread, | |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
| |
| 776 compiler_timeline, | |
| 777 "EliminateEnvironments"); | |
| 778 optimizer.EliminateEnvironments(); | |
| 779 } | |
| 703 | 780 |
| 704 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 781 { |
| 705 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 782 TimelineDurationScope tds2(thread, |
| 783 compiler_timeline, | |
| 784 "EliminateDeadPhis"); | |
| 785 DeadCodeElimination::EliminateDeadPhis(flow_graph); | |
| 786 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
| 787 } | |
| 706 | 788 |
| 707 if (optimizer.Canonicalize()) { | 789 if (optimizer.Canonicalize()) { |
| 790 TimelineDurationScope tds2(thread, | |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
| |
| 791 compiler_timeline, | |
| 792 "Canonicalize"); | |
| 708 optimizer.Canonicalize(); | 793 optimizer.Canonicalize(); |
| 709 } | 794 } |
| 710 | 795 |
| 711 // Attempt to sink allocations of temporary non-escaping objects to | 796 // Attempt to sink allocations of temporary non-escaping objects to |
| 712 // the deoptimization path. | 797 // the deoptimization path. |
| 713 AllocationSinking* sinking = NULL; | 798 AllocationSinking* sinking = NULL; |
| 714 if (FLAG_allocation_sinking && | 799 if (FLAG_allocation_sinking && |
| 715 (flow_graph->graph_entry()->SuccessorCount() == 1)) { | 800 (flow_graph->graph_entry()->SuccessorCount() == 1)) { |
| 801 TimelineDurationScope tds2(thread, | |
| 802 compiler_timeline, | |
| 803 "AllocationSinking::Optimize"); | |
| 716 // TODO(fschneider): Support allocation sinking with try-catch. | 804 // TODO(fschneider): Support allocation sinking with try-catch. |
| 717 sinking = new AllocationSinking(flow_graph); | 805 sinking = new AllocationSinking(flow_graph); |
| 718 sinking->Optimize(); | 806 sinking->Optimize(); |
| 719 } | 807 } |
| 720 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 808 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 721 | 809 |
| 722 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 810 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
| 723 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 811 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 724 | 812 |
| 725 FlowGraphTypePropagator::Propagate(flow_graph); | 813 FlowGraphTypePropagator::Propagate(flow_graph); |
| 726 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 814 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 727 | 815 |
| 728 // Ensure that all phis inserted by optimization passes have consistent | 816 { |
| 729 // representations. | 817 TimelineDurationScope tds2(thread, |
| 730 optimizer.SelectRepresentations(); | 818 compiler_timeline, |
| 819 "SelectRepresentations"); | |
| 820 // Ensure that all phis inserted by optimization passes have | |
| 821 // consistent representations. | |
| 822 optimizer.SelectRepresentations(); | |
| 823 } | |
| 731 | 824 |
| 732 if (optimizer.Canonicalize()) { | 825 { |
| 733 // To fully remove redundant boxing (e.g. BoxDouble used only in | 826 TimelineDurationScope tds2(thread, |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
| |
| 734 // environments and UnboxDouble instructions) instruction we | 827 compiler_timeline, |
| 735 // first need to replace all their uses and then fold them away. | 828 "Canonicalize"); |
| 736 // For now we just repeat Canonicalize twice to do that. | 829 if (optimizer.Canonicalize()) { |
| 737 // TODO(vegorov): implement a separate representation folding pass. | 830 // To fully remove redundant boxing (e.g. BoxDouble used only in |
| 738 optimizer.Canonicalize(); | 831 // environments and UnboxDouble instructions) instruction we |
| 832 // first need to replace all their uses and then fold them away. | |
| 833 // For now we just repeat Canonicalize twice to do that. | |
| 834 // TODO(vegorov): implement a separate representation folding pass. | |
| 835 optimizer.Canonicalize(); | |
| 836 } | |
| 837 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
| 739 } | 838 } |
| 740 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | |
| 741 | 839 |
| 742 if (sinking != NULL) { | 840 if (sinking != NULL) { |
| 841 TimelineDurationScope tds2( | |
| 842 thread, | |
| 843 compiler_timeline, | |
| 844 "AllocationSinking::DetachMaterializations"); | |
| 743 // Remove all MaterializeObject instructions inserted by allocation | 845 // Remove all MaterializeObject instructions inserted by allocation |
| 744 // sinking from the flow graph and let them float on the side | 846 // sinking from the flow graph and let them float on the side |
| 745 // referenced only from environments. Register allocator will consider | 847 // referenced only from environments. Register allocator will consider |
| 746 // them as part of a deoptimization environment. | 848 // them as part of a deoptimization environment. |
| 747 sinking->DetachMaterializations(); | 849 sinking->DetachMaterializations(); |
| 748 } | 850 } |
| 749 | 851 |
| 750 // Compute and store graph informations (call & instruction counts) | 852 { |
| 751 // to be later used by the inliner. | 853 TimelineDurationScope tds2(thread, |
|
Florian Schneider
2015/12/15 17:15:35
Remove this scope.
Cutch
2015/12/15 17:51:56
Done.
| |
| 752 FlowGraphInliner::CollectGraphInfo(flow_graph, true); | 854 compiler_timeline, |
| 855 "CollectGraphInfo"); | |
| 856 // Compute and store graph informations (call & instruction counts) | |
| 857 // to be later used by the inliner. | |
| 858 FlowGraphInliner::CollectGraphInfo(flow_graph, true); | |
| 859 } | |
| 753 | 860 |
| 754 // Perform register allocation on the SSA graph. | 861 { |
| 755 FlowGraphAllocator allocator(*flow_graph); | 862 TimelineDurationScope tds2(thread, |
| 756 allocator.AllocateRegisters(); | 863 compiler_timeline, |
| 757 if (reorder_blocks) block_scheduler.ReorderBlocks(); | 864 "AllocateRegisters"); |
| 865 // Perform register allocation on the SSA graph. | |
| 866 FlowGraphAllocator allocator(*flow_graph); | |
| 867 allocator.AllocateRegisters(); | |
| 868 } | |
| 869 | |
| 870 if (reorder_blocks) { | |
| 871 TimelineDurationScope tds(thread, | |
| 872 compiler_timeline, | |
| 873 "BlockScheduler::ReorderBlocks"); | |
| 874 block_scheduler.ReorderBlocks(); | |
| 875 } | |
| 758 | 876 |
| 759 if (print_flow_graph) { | 877 if (print_flow_graph) { |
| 760 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); | 878 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); |
| 761 } | 879 } |
| 762 } | 880 } |
| 763 | 881 |
| 764 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); | 882 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); |
| 765 Assembler assembler(use_far_branches); | 883 Assembler assembler(use_far_branches); |
| 766 FlowGraphCompiler graph_compiler(&assembler, flow_graph, | 884 FlowGraphCompiler graph_compiler(&assembler, flow_graph, |
| 767 *parsed_function, optimized, | 885 *parsed_function, optimized, |
| 768 inline_id_to_function, | 886 inline_id_to_function, |
| 769 caller_inline_id); | 887 caller_inline_id); |
| 770 { | 888 { |
| 771 CSTAT_TIMER_SCOPE(thread, graphcompiler_timer); | 889 CSTAT_TIMER_SCOPE(thread, graphcompiler_timer); |
| 890 TimelineDurationScope tds(thread, | |
| 891 compiler_timeline, | |
| 892 "CompileGraph"); | |
| 772 graph_compiler.CompileGraph(); | 893 graph_compiler.CompileGraph(); |
| 773 pipeline->FinalizeCompilation(); | 894 pipeline->FinalizeCompilation(); |
| 774 } | 895 } |
| 775 { | 896 { |
| 897 TimelineDurationScope tds(thread, | |
| 898 compiler_timeline, | |
| 899 "FinalizeCompilation"); | |
| 776 // This part of compilation must be at a safepoint. | 900 // This part of compilation must be at a safepoint. |
| 777 if (!Thread::Current()->IsMutatorThread()) { | 901 if (!Thread::Current()->IsMutatorThread()) { |
| 778 // Stop mutator thread before creating the instruction object and | 902 // Stop mutator thread before creating the instruction object and |
| 779 // installing code. | 903 // installing code. |
| 780 // Mutator thread may not run code while we are creating the | 904 // Mutator thread may not run code while we are creating the |
| 781 // instruction object, since the creation of instruction object | 905 // instruction object, since the creation of instruction object |
| 782 // changes code page access permissions (makes them temporary not | 906 // changes code page access permissions (makes them temporary not |
| 783 // executable). | 907 // executable). |
| 784 isolate->thread_registry()->SafepointThreads(); | 908 isolate->thread_registry()->SafepointThreads(); |
| 785 } | 909 } |
| (...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1888 } | 2012 } |
| 1889 | 2013 |
| 1890 | 2014 |
| 1891 void BackgroundCompiler::EnsureInit(Thread* thread) { | 2015 void BackgroundCompiler::EnsureInit(Thread* thread) { |
| 1892 UNREACHABLE(); | 2016 UNREACHABLE(); |
| 1893 } | 2017 } |
| 1894 | 2018 |
| 1895 #endif // DART_PRECOMPILED | 2019 #endif // DART_PRECOMPILED |
| 1896 | 2020 |
| 1897 } // namespace dart | 2021 } // namespace dart |
| OLD | NEW |