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

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

Issue 14057004: Convert diamond shaped control flow into a single conditional instruction. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address Florian's comments Created 7 years, 8 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_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.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_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/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 3912 matching lines...) Expand 10 before | Expand all | Expand 10 after
3923 UNREACHABLE(); 3923 UNREACHABLE();
3924 } 3924 }
3925 3925
3926 3926
3927 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { 3927 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) {
3928 // Instruction is eliminated when translating to SSA. 3928 // Instruction is eliminated when translating to SSA.
3929 UNREACHABLE(); 3929 UNREACHABLE();
3930 } 3930 }
3931 3931
3932 3932
3933 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) {
3934 ASSERT(Token::IsEqualityOperator(instr->kind()));
3935
3936 const Object& left = instr->left()->definition()->constant_value();
3937 const Object& right = instr->right()->definition()->constant_value();
3938
3939 if (IsNonConstant(left) || IsNonConstant(right)) {
3940 // TODO(vegorov): incorporate nullability information into the lattice.
3941 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) ||
3942 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) {
3943 bool result = left.IsNull() ? instr->right()->Type()->IsNull()
3944 : instr->left()->Type()->IsNull();
3945 if (instr->kind() == Token::kNE_STRICT ||
3946 instr->kind() == Token::kNE) {
3947 result = !result;
3948 }
3949 SetValue(instr, Smi::Handle(
3950 Smi::New(result ? instr->if_true() : instr->if_false())));
3951 } else {
3952 SetValue(instr, non_constant_);
3953 }
3954 } else if (IsConstant(left) && IsConstant(right)) {
3955 bool result = (left.raw() == right.raw());
srdjan 2013/04/10 21:47:30 Since equality can be overridden, I do not think t
Vyacheslav Egorov (Google) 2013/04/10 21:51:28 Agreed, this is fragile. The plan is to remove t
3956 if (instr->kind() == Token::kNE_STRICT ||
3957 instr->kind() == Token::kNE) {
3958 result = !result;
3959 }
3960 SetValue(instr, Smi::Handle(
3961 Smi::New(result ? instr->if_true() : instr->if_false())));
3962 }
3963 }
3964
3965
3933 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { 3966 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) {
3934 const Object& left = instr->left()->definition()->constant_value(); 3967 const Object& left = instr->left()->definition()->constant_value();
3935 const Object& right = instr->right()->definition()->constant_value(); 3968 const Object& right = instr->right()->definition()->constant_value();
3936 3969
3937 if (IsNonConstant(left) || IsNonConstant(right)) { 3970 if (IsNonConstant(left) || IsNonConstant(right)) {
3938 // TODO(vegorov): incorporate nullability information into the lattice. 3971 // TODO(vegorov): incorporate nullability information into the lattice.
3939 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) || 3972 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) ||
3940 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) { 3973 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) {
3941 bool result = left.IsNull() ? instr->right()->Type()->IsNull() 3974 bool result = left.IsNull() ? instr->right()->Type()->IsNull()
3942 : instr->left()->Type()->IsNull(); 3975 : instr->left()->Type()->IsNull();
(...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after
4742 4775
4743 if (changed) { 4776 if (changed) {
4744 // We may have changed the block order and the dominator tree. 4777 // We may have changed the block order and the dominator tree.
4745 flow_graph->DiscoverBlocks(); 4778 flow_graph->DiscoverBlocks();
4746 GrowableArray<BitVector*> dominance_frontier; 4779 GrowableArray<BitVector*> dominance_frontier;
4747 flow_graph->ComputeDominators(&dominance_frontier); 4780 flow_graph->ComputeDominators(&dominance_frontier);
4748 } 4781 }
4749 } 4782 }
4750 4783
4751 4784
4785 static bool IsTrivialBlock(BlockEntryInstr* block, Definition* defn) {
4786 return (block->IsTargetEntry() && (block->PredecessorCount() == 1)) &&
4787 ((block->next() == block->last_instruction()) ||
4788 ((block->next() == defn) && (defn->next() == block->last_instruction())));
4789 }
4790
4791
4792 static void EliminateTrivialBlock(BlockEntryInstr* block,
4793 Definition* instr,
4794 IfThenElseInstr* before) {
4795 block->UnuseAllInputs();
4796 block->last_instruction()->UnuseAllInputs();
4797
4798 if ((block->next() == instr) &&
4799 (instr->next() == block->last_instruction())) {
4800 before->previous()->LinkTo(instr);
4801 instr->LinkTo(before);
4802 }
4803 }
4804
4805
4806 void IfConverter::Simplify(FlowGraph* flow_graph) {
4807 if (!IfThenElseInstr::IsSupported()) {
4808 return;
4809 }
4810
4811 bool changed = false;
4812
4813 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder();
4814 for (BlockIterator it(postorder); !it.Done(); it.Advance()) {
4815 BlockEntryInstr* block = it.Current();
4816 JoinEntryInstr* join = block->AsJoinEntry();
4817
4818 // Detect diamond control flow pattern which materializes a value depending
4819 // on the result of the comparison:
4820 //
4821 // B_pred:
4822 // ...
4823 // Branch if COMP goto (B_pred1, B_pred2)
4824 // B_pred1: -- trivial block that contains at most one definition
4825 // v1 = Constant(...)
4826 // goto B_block
4827 // B_pred2: -- trivial block that contains at most one definition
4828 // v2 = Constant(...)
4829 // goto B_block
4830 // B_block:
4831 // v3 = phi(v1, v2) -- single phi
4832 //
4833 // and replace it with
4834 //
4835 // Ba:
4836 // v3 = IfThenElse(COMP ? v1 : v2)
4837 //
4838 if ((join != NULL) &&
4839 (join->phis() != NULL) &&
4840 (join->phis()->length() == 1) &&
4841 (block->PredecessorCount() == 2)) {
4842 BlockEntryInstr* pred1 = block->PredecessorAt(0);
4843 BlockEntryInstr* pred2 = block->PredecessorAt(1);
4844
4845 PhiInstr* phi = (*join->phis())[0];
4846 Value* v1 = phi->InputAt(0);
4847 Value* v2 = phi->InputAt(1);
4848
4849 if (IsTrivialBlock(pred1, v1->definition()) &&
4850 IsTrivialBlock(pred2, v2->definition()) &&
4851 (pred1->PredecessorAt(0) == pred2->PredecessorAt(0))) {
4852 BlockEntryInstr* pred = pred1->PredecessorAt(0);
4853 BranchInstr* branch = pred->last_instruction()->AsBranch();
4854 ComparisonInstr* comparison = branch->comparison();
4855
4856 // Check if the platform supports efficient branchless IfThenElseInstr
4857 // for the given combination of comparison and values flowing from
4858 // false and true paths.
4859 if (IfThenElseInstr::Supports(comparison, v1, v2)) {
4860 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2;
4861 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2;
4862
4863 IfThenElseInstr* if_then_else = new IfThenElseInstr(
4864 comparison->kind(),
4865 comparison->InputAt(0)->Copy(),
4866 comparison->InputAt(1)->Copy(),
4867 if_true->Copy(),
4868 if_false->Copy());
4869 flow_graph->InsertBefore(branch,
4870 if_then_else,
4871 NULL,
4872 Definition::kValue);
4873
4874 phi->ReplaceUsesWith(if_then_else);
4875
4876 // Connect IfThenElseInstr to the first instruction in the merge block
4877 // effectively eliminating diamond control flow.
4878 // Current block as well as pred1 and pred2 blocks are no longer in
4879 // the graph at this point.
4880 if_then_else->LinkTo(join->next());
4881 pred->set_last_instruction(join->last_instruction());
4882
4883 // Resulting block must inherit block id from the eliminated current
4884 // block to guarantee that ordering of phi operands in its successor
4885 // stays consistent.
4886 pred->set_block_id(block->block_id());
4887
4888 // If v1 and v2 were defined inside eliminated blocks pred1/pred2
4889 // move them out to the place before inserted IfThenElse instruction.
4890 EliminateTrivialBlock(pred1, v1->definition(), if_then_else);
4891 EliminateTrivialBlock(pred2, v2->definition(), if_then_else);
4892
4893 // Update use lists to reflect changes in the graph.
4894 phi->UnuseAllInputs();
4895 branch->UnuseAllInputs();
4896
4897 // The graph has changed. Recompute dominators and block orders after
4898 // this pass is finished.
4899 changed = true;
4900 }
4901 }
4902 }
4903 }
4904
4905 if (changed) {
4906 // We may have changed the block order and the dominator tree.
4907 flow_graph->DiscoverBlocks();
4908 GrowableArray<BitVector*> dominance_frontier;
4909 flow_graph->ComputeDominators(&dominance_frontier);
4910 }
4911 }
4912
4913
4752 } // namespace dart 4914 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/flow_graph_type_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698