| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |