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

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

Issue 734093002: When constant folding x == y take reachability of blocks into account. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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_optimizer.h ('k') | no next file » | 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_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 7507 matching lines...) Expand 10 before | Expand all | Expand 10 after
7518 7518
7519 ConstantPropagator::ConstantPropagator( 7519 ConstantPropagator::ConstantPropagator(
7520 FlowGraph* graph, 7520 FlowGraph* graph,
7521 const GrowableArray<BlockEntryInstr*>& ignored) 7521 const GrowableArray<BlockEntryInstr*>& ignored)
7522 : FlowGraphVisitor(ignored), 7522 : FlowGraphVisitor(ignored),
7523 graph_(graph), 7523 graph_(graph),
7524 unknown_(Object::unknown_constant()), 7524 unknown_(Object::unknown_constant()),
7525 non_constant_(Object::non_constant()), 7525 non_constant_(Object::non_constant()),
7526 reachable_(new(graph->isolate()) BitVector( 7526 reachable_(new(graph->isolate()) BitVector(
7527 graph->isolate(), graph->preorder().length())), 7527 graph->isolate(), graph->preorder().length())),
7528 definition_marks_(new(graph->isolate()) BitVector( 7528 marked_phis_(new(graph->isolate()) BitVector(
7529 graph->isolate(), graph->max_virtual_register_number())), 7529 graph->isolate(), graph->max_virtual_register_number())),
7530 block_worklist_(), 7530 block_worklist_(),
7531 definition_worklist_() {} 7531 definition_worklist_(graph, 10) {}
7532 7532
7533 7533
7534 void ConstantPropagator::Optimize(FlowGraph* graph) { 7534 void ConstantPropagator::Optimize(FlowGraph* graph) {
7535 GrowableArray<BlockEntryInstr*> ignored; 7535 GrowableArray<BlockEntryInstr*> ignored;
7536 ConstantPropagator cp(graph, ignored); 7536 ConstantPropagator cp(graph, ignored);
7537 cp.Analyze(); 7537 cp.Analyze();
7538 cp.Transform(); 7538 cp.Transform();
7539 } 7539 }
7540 7540
7541 7541
7542 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) { 7542 void ConstantPropagator::OptimizeBranches(FlowGraph* graph) {
7543 GrowableArray<BlockEntryInstr*> ignored; 7543 GrowableArray<BlockEntryInstr*> ignored;
7544 ConstantPropagator cp(graph, ignored); 7544 ConstantPropagator cp(graph, ignored);
7545 cp.Analyze(); 7545 cp.Analyze();
7546 cp.Transform(); 7546 cp.Transform();
7547 cp.EliminateRedundantBranches(); 7547 cp.EliminateRedundantBranches();
7548 } 7548 }
7549 7549
7550 7550
7551 void ConstantPropagator::SetReachable(BlockEntryInstr* block) { 7551 void ConstantPropagator::SetReachable(BlockEntryInstr* block) {
7552 if (!reachable_->Contains(block->preorder_number())) { 7552 if (!reachable_->Contains(block->preorder_number())) {
7553 reachable_->Add(block->preorder_number()); 7553 reachable_->Add(block->preorder_number());
7554 block_worklist_.Add(block); 7554 block_worklist_.Add(block);
7555 } 7555 }
7556 } 7556 }
7557 7557
7558 7558
7559 void ConstantPropagator::SetValue(Definition* definition, const Object& value) { 7559 bool ConstantPropagator::SetValue(Definition* definition, const Object& value) {
7560 // We would like to assert we only go up (toward non-constant) in the lattice. 7560 // We would like to assert we only go up (toward non-constant) in the lattice.
7561 // 7561 //
7562 // ASSERT(IsUnknown(definition->constant_value()) || 7562 // ASSERT(IsUnknown(definition->constant_value()) ||
7563 // IsNonConstant(value) || 7563 // IsNonConstant(value) ||
7564 // (definition->constant_value().raw() == value.raw())); 7564 // (definition->constant_value().raw() == value.raw()));
7565 // 7565 //
7566 // But the final disjunct is not true (e.g., mint or double constants are 7566 // But the final disjunct is not true (e.g., mint or double constants are
7567 // heap-allocated and so not necessarily pointer-equal on each iteration). 7567 // heap-allocated and so not necessarily pointer-equal on each iteration).
7568 if (definition->constant_value().raw() != value.raw()) { 7568 if (definition->constant_value().raw() != value.raw()) {
7569 definition->constant_value() = value.raw(); 7569 definition->constant_value() = value.raw();
7570 if (definition->input_use_list() != NULL) { 7570 if (definition->input_use_list() != NULL) {
7571 ASSERT(definition->HasSSATemp()); 7571 definition_worklist_.Add(definition);
7572 if (!definition_marks_->Contains(definition->ssa_temp_index())) {
7573 definition_worklist_.Add(definition);
7574 definition_marks_->Add(definition->ssa_temp_index());
7575 }
7576 } 7572 }
7573 return true;
7577 } 7574 }
7575 return false;
7578 } 7576 }
7579 7577
7580 7578
7581 // Compute the join of two values in the lattice, assign it to the first. 7579 // Compute the join of two values in the lattice, assign it to the first.
7582 void ConstantPropagator::Join(Object* left, const Object& right) { 7580 void ConstantPropagator::Join(Object* left, const Object& right) {
7583 // Join(non-constant, X) = non-constant 7581 // Join(non-constant, X) = non-constant
7584 // Join(X, unknown) = X 7582 // Join(X, unknown) = X
7585 if (IsNonConstant(*left) || IsUnknown(right)) return; 7583 if (IsNonConstant(*left) || IsUnknown(right)) return;
7586 7584
7587 // Join(unknown, X) = X 7585 // Join(unknown, X) = X
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
7733 7731
7734 7732
7735 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { } 7733 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) { }
7736 7734
7737 7735
7738 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) { 7736 void ConstantPropagator::VisitDeoptimize(DeoptimizeInstr* instr) {
7739 // TODO(vegorov) remove all code after DeoptimizeInstr as dead. 7737 // TODO(vegorov) remove all code after DeoptimizeInstr as dead.
7740 } 7738 }
7741 7739
7742 7740
7741 Definition* ConstantPropagator::UnwrapPhi(Definition* defn) {
7742 if (defn->IsPhi()) {
7743 JoinEntryInstr* block = defn->AsPhi()->block();
7744
7745 Definition* input = NULL;
7746 for (intptr_t i = 0; i < defn->InputCount(); ++i) {
7747 if (reachable_->Contains(block->PredecessorAt(i)->preorder_number())) {
7748 if (input == NULL) {
7749 input = defn->InputAt(i)->definition();
7750 } else {
7751 return defn;
7752 }
7753 }
7754 }
7755
7756 return input;
7757 }
7758
7759 return defn;
7760 }
7761
7762
7763 void ConstantPropagator::MarkPhi(Definition* phi) {
7764 ASSERT(phi->IsPhi());
7765 marked_phis_->Add(phi->ssa_temp_index());
7766 }
7767
7768
7743 // -------------------------------------------------------------------------- 7769 // --------------------------------------------------------------------------
7744 // Analysis of definitions. Compute the constant value. If it has changed 7770 // Analysis of definitions. Compute the constant value. If it has changed
7745 // and the definition has input uses, add the definition to the definition 7771 // and the definition has input uses, add the definition to the definition
7746 // worklist so that the used can be processed. 7772 // worklist so that the used can be processed.
7747 void ConstantPropagator::VisitPhi(PhiInstr* instr) { 7773 void ConstantPropagator::VisitPhi(PhiInstr* instr) {
7748 // Compute the join over all the reachable predecessor values. 7774 // Compute the join over all the reachable predecessor values.
7749 JoinEntryInstr* block = instr->block(); 7775 JoinEntryInstr* block = instr->block();
7750 Object& value = Object::ZoneHandle(I, Unknown()); 7776 Object& value = Object::ZoneHandle(I, Unknown());
7751 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) { 7777 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) {
7752 if (reachable_->Contains( 7778 if (reachable_->Contains(
7753 block->PredecessorAt(pred_idx)->preorder_number())) { 7779 block->PredecessorAt(pred_idx)->preorder_number())) {
7754 Join(&value, 7780 Join(&value,
7755 instr->InputAt(pred_idx)->definition()->constant_value()); 7781 instr->InputAt(pred_idx)->definition()->constant_value());
7756 } 7782 }
7757 } 7783 }
7758 SetValue(instr, value); 7784 if (!SetValue(instr, value) &&
7785 marked_phis_->Contains(instr->ssa_temp_index())) {
7786 marked_phis_->Remove(instr->ssa_temp_index());
7787 definition_worklist_.Add(instr);
7788 }
7759 } 7789 }
7760 7790
7761 7791
7762 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) { 7792 void ConstantPropagator::VisitRedefinition(RedefinitionInstr* instr) {
7763 SetValue(instr, instr->value()->definition()->constant_value()); 7793 SetValue(instr, instr->value()->definition()->constant_value());
7764 } 7794 }
7765 7795
7766 7796
7767 void ConstantPropagator::VisitParameter(ParameterInstr* instr) { 7797 void ConstantPropagator::VisitParameter(ParameterInstr* instr) {
7768 SetValue(instr, non_constant_); 7798 SetValue(instr, non_constant_);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
7864 ASSERT(value.IsBool()); 7894 ASSERT(value.IsBool());
7865 bool result = Bool::Cast(value).value(); 7895 bool result = Bool::Cast(value).value();
7866 SetValue(instr, 7896 SetValue(instr,
7867 Smi::Handle(I, Smi::New( 7897 Smi::Handle(I, Smi::New(
7868 result ? instr->if_true() : instr->if_false()))); 7898 result ? instr->if_true() : instr->if_false())));
7869 } 7899 }
7870 } 7900 }
7871 7901
7872 7902
7873 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { 7903 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) {
7874 const Object& left = instr->left()->definition()->constant_value(); 7904 Definition* left_defn = instr->left()->definition();
7875 const Object& right = instr->right()->definition()->constant_value(); 7905 Definition* right_defn = instr->right()->definition();
7876 7906
7877 if (instr->left()->definition() == instr->right()->definition()) { 7907 Definition* unwrapped_left_defn = UnwrapPhi(left_defn);
7908 Definition* unwrapped_right_defn = UnwrapPhi(right_defn);
7909 if (unwrapped_left_defn == unwrapped_right_defn) {
7878 // Fold x === x, and x !== x to true/false. 7910 // Fold x === x, and x !== x to true/false.
7879 SetValue(instr, Bool::Get(instr->kind() == Token::kEQ_STRICT)); 7911 SetValue(instr, Bool::Get(instr->kind() == Token::kEQ_STRICT));
7912 if (unwrapped_left_defn != left_defn) {
7913 MarkPhi(left_defn);
7914 }
7915 if (unwrapped_right_defn != right_defn) {
7916 MarkPhi(right_defn);
7917 }
7880 return; 7918 return;
7881 } 7919 }
7882 7920
7921 const Object& left = left_defn->constant_value();
7922 const Object& right = right_defn->constant_value();
7883 if (IsNonConstant(left) || IsNonConstant(right)) { 7923 if (IsNonConstant(left) || IsNonConstant(right)) {
7884 // TODO(vegorov): incorporate nullability information into the lattice. 7924 // TODO(vegorov): incorporate nullability information into the lattice.
7885 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) || 7925 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) ||
7886 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) { 7926 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) {
7887 bool result = left.IsNull() ? instr->right()->Type()->IsNull() 7927 bool result = left.IsNull() ? instr->right()->Type()->IsNull()
7888 : instr->left()->Type()->IsNull(); 7928 : instr->left()->Type()->IsNull();
7889 if (instr->kind() == Token::kNE_STRICT) { 7929 if (instr->kind() == Token::kNE_STRICT) {
7890 result = !result; 7930 result = !result;
7891 } 7931 }
7892 SetValue(instr, Bool::Get(result)); 7932 SetValue(instr, Bool::Get(result));
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
7950 } 7990 }
7951 } 7991 }
7952 7992
7953 7993
7954 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) { 7994 void ConstantPropagator::VisitTestCids(TestCidsInstr* instr) {
7955 SetValue(instr, non_constant_); 7995 SetValue(instr, non_constant_);
7956 } 7996 }
7957 7997
7958 7998
7959 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) { 7999 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) {
7960 const Object& left = instr->left()->definition()->constant_value(); 8000 Definition* left_defn = instr->left()->definition();
7961 const Object& right = instr->right()->definition()->constant_value(); 8001 Definition* right_defn = instr->right()->definition();
7962 8002
7963 if (instr->left()->definition() == instr->right()->definition()) { 8003 if (RawObject::IsIntegerClassId(instr->operation_cid())) {
7964 // Fold x == x, and x != x to true/false for numbers comparisons. 8004 // Fold x == x, and x != x to true/false for numbers comparisons.
7965 if (RawObject::IsIntegerClassId(instr->operation_cid())) { 8005 Definition* unwrapped_left_defn = UnwrapPhi(left_defn);
7966 return SetValue(instr, Bool::Get(instr->kind() == Token::kEQ)); 8006 Definition* unwrapped_right_defn = UnwrapPhi(right_defn);
8007 if (unwrapped_left_defn == unwrapped_right_defn) {
8008 // Fold x === x, and x !== x to true/false.
8009 SetValue(instr, Bool::Get(instr->kind() == Token::kEQ));
8010 if (unwrapped_left_defn != left_defn) {
8011 MarkPhi(left_defn);
8012 }
8013 if (unwrapped_right_defn != right_defn) {
8014 MarkPhi(right_defn);
8015 }
8016 return;
7967 } 8017 }
7968 } 8018 }
7969 8019
8020 const Object& left = left_defn->constant_value();
8021 const Object& right = right_defn->constant_value();
7970 if (IsNonConstant(left) || IsNonConstant(right)) { 8022 if (IsNonConstant(left) || IsNonConstant(right)) {
7971 SetValue(instr, non_constant_); 8023 SetValue(instr, non_constant_);
7972 } else if (IsConstant(left) && IsConstant(right)) { 8024 } else if (IsConstant(left) && IsConstant(right)) {
7973 if (left.IsInteger() && right.IsInteger()) { 8025 if (left.IsInteger() && right.IsInteger()) {
7974 const bool result = CompareIntegers(instr->kind(), 8026 const bool result = CompareIntegers(instr->kind(),
7975 Integer::Cast(left), 8027 Integer::Cast(left),
7976 Integer::Cast(right)); 8028 Integer::Cast(right));
7977 SetValue(instr, Bool::Get(result)); 8029 SetValue(instr, Bool::Get(result));
7978 } else if (left.IsString() && right.IsString()) { 8030 } else if (left.IsString() && right.IsString()) {
7979 const bool result = String::Cast(left).Equals(String::Cast(right)); 8031 const bool result = String::Cast(left).Equals(String::Cast(right));
(...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after
8788 } 8840 }
8789 8841
8790 8842
8791 void ConstantPropagator::Analyze() { 8843 void ConstantPropagator::Analyze() {
8792 GraphEntryInstr* entry = graph_->graph_entry(); 8844 GraphEntryInstr* entry = graph_->graph_entry();
8793 reachable_->Add(entry->preorder_number()); 8845 reachable_->Add(entry->preorder_number());
8794 block_worklist_.Add(entry); 8846 block_worklist_.Add(entry);
8795 8847
8796 while (true) { 8848 while (true) {
8797 if (block_worklist_.is_empty()) { 8849 if (block_worklist_.is_empty()) {
8798 if (definition_worklist_.is_empty()) break; 8850 if (definition_worklist_.IsEmpty()) break;
8799 Definition* definition = definition_worklist_.RemoveLast(); 8851 Definition* definition = definition_worklist_.RemoveLast();
8800 definition_marks_->Remove(definition->ssa_temp_index());
8801 Value* use = definition->input_use_list(); 8852 Value* use = definition->input_use_list();
8802 while (use != NULL) { 8853 while (use != NULL) {
8803 use->instruction()->Accept(this); 8854 use->instruction()->Accept(this);
8804 use = use->next_use(); 8855 use = use->next_use();
8805 } 8856 }
8806 } else { 8857 } else {
8807 BlockEntryInstr* block = block_worklist_.RemoveLast(); 8858 BlockEntryInstr* block = block_worklist_.RemoveLast();
8808 block->Accept(this); 8859 block->Accept(this);
8809 } 8860 }
8810 } 8861 }
(...skipping 1202 matching lines...) Expand 10 before | Expand all | Expand 10 after
10013 10064
10014 // Insert materializations at environment uses. 10065 // Insert materializations at environment uses.
10015 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { 10066 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
10016 CreateMaterializationAt( 10067 CreateMaterializationAt(
10017 exits_collector_.exits()[i], alloc, *slots); 10068 exits_collector_.exits()[i], alloc, *slots);
10018 } 10069 }
10019 } 10070 }
10020 10071
10021 10072
10022 } // namespace dart 10073 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698