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

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

Issue 14846022: Use the constant pool for all constants, not just null. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 7 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/intermediate_language.h » ('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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 } 299 }
300 } 300 }
301 iterator->RemoveCurrentFromGraph(); 301 iterator->RemoveCurrentFromGraph();
302 } 302 }
303 303
304 304
305 bool FlowGraphOptimizer::Canonicalize() { 305 bool FlowGraphOptimizer::Canonicalize() {
306 bool changed = false; 306 bool changed = false;
307 for (intptr_t i = 0; i < block_order_.length(); ++i) { 307 for (intptr_t i = 0; i < block_order_.length(); ++i) {
308 BlockEntryInstr* entry = block_order_[i]; 308 BlockEntryInstr* entry = block_order_[i];
309 entry->Accept(this);
310 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 309 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
311 Instruction* current = it.Current(); 310 Instruction* current = it.Current();
312 Instruction* replacement = current->Canonicalize(this); 311 Instruction* replacement = current->Canonicalize(flow_graph());
313 if (replacement != current) { 312 if (replacement != current) {
314 // For non-definitions Canonicalize should return either NULL or 313 // For non-definitions Canonicalize should return either NULL or
315 // this. 314 // this.
316 ASSERT((replacement == NULL) || current->IsDefinition()); 315 ASSERT((replacement == NULL) || current->IsDefinition());
317 ReplaceCurrentInstruction(&it, current, replacement, flow_graph_); 316 ReplaceCurrentInstruction(&it, current, replacement, flow_graph_);
318 changed = true; 317 changed = true;
319 } 318 }
320 } 319 }
321 } 320 }
322 return changed; 321 return changed;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 } else if ((from == kTagged) && (to == kUnboxedDouble)) { 355 } else if ((from == kTagged) && (to == kUnboxedDouble)) {
357 ASSERT((deopt_target != NULL) || 356 ASSERT((deopt_target != NULL) ||
358 (use->Type()->ToCid() == kDoubleCid)); 357 (use->Type()->ToCid() == kDoubleCid));
359 const intptr_t deopt_id = (deopt_target != NULL) ? 358 const intptr_t deopt_id = (deopt_target != NULL) ?
360 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 359 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
361 ConstantInstr* constant = use->definition()->AsConstant(); 360 ConstantInstr* constant = use->definition()->AsConstant();
362 if ((constant != NULL) && constant->value().IsSmi()) { 361 if ((constant != NULL) && constant->value().IsSmi()) {
363 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); 362 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue();
364 const Double& dbl_obj = 363 const Double& dbl_obj =
365 Double::ZoneHandle(Double::New(dbl_val, Heap::kOld)); 364 Double::ZoneHandle(Double::New(dbl_val, Heap::kOld));
366 ConstantInstr* double_const = new ConstantInstr(dbl_obj); 365 ConstantInstr* double_const = flow_graph()->GetConstant(dbl_obj);
367 InsertBefore(insert_before, double_const, NULL, Definition::kValue);
368 converted = new UnboxDoubleInstr(new Value(double_const), deopt_id); 366 converted = new UnboxDoubleInstr(new Value(double_const), deopt_id);
369 } else { 367 } else {
370 converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id); 368 converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id);
371 } 369 }
372 } else if ((from == kTagged) && (to == kUnboxedFloat32x4)) { 370 } else if ((from == kTagged) && (to == kUnboxedFloat32x4)) {
373 ASSERT((deopt_target != NULL) || 371 ASSERT((deopt_target != NULL) ||
374 (use->Type()->ToCid() == kFloat32x4Cid)); 372 (use->Type()->ToCid() == kFloat32x4Cid));
375 const intptr_t deopt_id = (deopt_target != NULL) ? 373 const intptr_t deopt_id = (deopt_target != NULL) ?
376 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 374 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
377 converted = new UnboxFloat32x4Instr(use->CopyWithType(), deopt_id); 375 converted = new UnboxFloat32x4Instr(use->CopyWithType(), deopt_id);
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 const intptr_t value = Smi::Cast(obj).Value(); 1122 const intptr_t value = Smi::Cast(obj).Value();
1125 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false; 1123 if ((value <= 0) || !Utils::IsPowerOfTwo(value)) return false;
1126 1124
1127 // Insert smi check and attach a copy of the original environment 1125 // Insert smi check and attach a copy of the original environment
1128 // because the smi operation can still deoptimize. 1126 // because the smi operation can still deoptimize.
1129 InsertBefore(call, 1127 InsertBefore(call,
1130 new CheckSmiInstr(new Value(left), call->deopt_id()), 1128 new CheckSmiInstr(new Value(left), call->deopt_id()),
1131 call->env(), 1129 call->env(),
1132 Definition::kEffect); 1130 Definition::kEffect);
1133 ConstantInstr* constant = 1131 ConstantInstr* constant =
1134 new ConstantInstr(Smi::Handle(Smi::New(value - 1))); 1132 flow_graph()->GetConstant(Smi::Handle(Smi::New(value - 1)));
1135 InsertBefore(call, constant, NULL, Definition::kValue);
1136 BinarySmiOpInstr* bin_op = 1133 BinarySmiOpInstr* bin_op =
1137 new BinarySmiOpInstr(Token::kBIT_AND, call, 1134 new BinarySmiOpInstr(Token::kBIT_AND, call,
1138 new Value(left), 1135 new Value(left),
1139 new Value(constant)); 1136 new Value(constant));
1140 ReplaceCall(call, bin_op); 1137 ReplaceCall(call, bin_op);
1141 } else { 1138 } else {
1142 ASSERT(operands_type == kSmiCid); 1139 ASSERT(operands_type == kSmiCid);
1143 // Insert two smi checks and attach a copy of the original 1140 // Insert two smi checks and attach a copy of the original
1144 // environment because the smi operation can still deoptimize. 1141 // environment because the smi operation can still deoptimize.
1145 AddCheckSmi(left, call->deopt_id(), call->env(), call); 1142 AddCheckSmi(left, call->deopt_id(), call->env(), call);
(...skipping 25 matching lines...) Expand all
1171 Definition::kEffect); 1168 Definition::kEffect);
1172 unary_op = new UnarySmiOpInstr(op_kind, call, new Value(input)); 1169 unary_op = new UnarySmiOpInstr(op_kind, call, new Value(input));
1173 } else if ((op_kind == Token::kBIT_NOT) && 1170 } else if ((op_kind == Token::kBIT_NOT) &&
1174 HasOnlySmiOrMint(*call->ic_data()) && 1171 HasOnlySmiOrMint(*call->ic_data()) &&
1175 FlowGraphCompiler::SupportsUnboxedMints()) { 1172 FlowGraphCompiler::SupportsUnboxedMints()) {
1176 unary_op = new UnaryMintOpInstr(op_kind, new Value(input), call); 1173 unary_op = new UnaryMintOpInstr(op_kind, new Value(input), call);
1177 } else if (HasOnlyOneDouble(*call->ic_data()) && 1174 } else if (HasOnlyOneDouble(*call->ic_data()) &&
1178 (op_kind == Token::kNEGATE)) { 1175 (op_kind == Token::kNEGATE)) {
1179 AddReceiverCheck(call); 1176 AddReceiverCheck(call);
1180 ConstantInstr* minus_one = 1177 ConstantInstr* minus_one =
1181 new ConstantInstr(Double::ZoneHandle(Double::NewCanonical(-1))); 1178 flow_graph()->GetConstant(Double::ZoneHandle(Double::NewCanonical(-1)));
1182 InsertBefore(call, minus_one, NULL, Definition::kValue);
1183 unary_op = new BinaryDoubleOpInstr(Token::kMUL, 1179 unary_op = new BinaryDoubleOpInstr(Token::kMUL,
1184 new Value(input), 1180 new Value(input),
1185 new Value(minus_one), 1181 new Value(minus_one),
1186 call); 1182 call);
1187 } 1183 }
1188 if (unary_op == NULL) return false; 1184 if (unary_op == NULL) return false;
1189 1185
1190 ReplaceCall(call, unary_op); 1186 ReplaceCall(call, unary_op);
1191 return true; 1187 return true;
1192 } 1188 }
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 ReplaceCall(call, load); 1361 ReplaceCall(call, load);
1366 } 1362 }
1367 1363
1368 1364
1369 void FlowGraphOptimizer::InlineStringIsEmptyGetter(InstanceCallInstr* call) { 1365 void FlowGraphOptimizer::InlineStringIsEmptyGetter(InstanceCallInstr* call) {
1370 AddReceiverCheck(call); 1366 AddReceiverCheck(call);
1371 1367
1372 LoadFieldInstr* load = BuildLoadStringLength(call->ArgumentAt(0)); 1368 LoadFieldInstr* load = BuildLoadStringLength(call->ArgumentAt(0));
1373 InsertBefore(call, load, NULL, Definition::kValue); 1369 InsertBefore(call, load, NULL, Definition::kValue);
1374 1370
1375 ConstantInstr* zero = new ConstantInstr(Smi::Handle(Smi::New(0))); 1371 ConstantInstr* zero = flow_graph()->GetConstant(Smi::Handle(Smi::New(0)));
1376 InsertBefore(call, zero, NULL, Definition::kValue);
1377
1378 StrictCompareInstr* compare = 1372 StrictCompareInstr* compare =
1379 new StrictCompareInstr(Token::kEQ_STRICT, 1373 new StrictCompareInstr(Token::kEQ_STRICT,
1380 new Value(load), 1374 new Value(load),
1381 new Value(zero)); 1375 new Value(zero));
1382 ReplaceCall(call, compare); 1376 ReplaceCall(call, compare);
1383 } 1377 }
1384 1378
1385 1379
1386 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) { 1380 static intptr_t OffsetForLengthGetter(MethodRecognizer::Kind kind) {
1387 switch (kind) { 1381 switch (kind) {
(...skipping 630 matching lines...) Expand 10 before | Expand all | Expand 10 after
2018 Type::ZoneHandle(Type::SmiType()), 2012 Type::ZoneHandle(Type::SmiType()),
2019 is_immutable); 2013 is_immutable);
2020 length->set_result_cid(kSmiCid); 2014 length->set_result_cid(kSmiCid);
2021 length->set_recognized_kind( 2015 length->set_recognized_kind(
2022 LoadFieldInstr::RecognizedKindFromArrayCid(receiver_cid)); 2016 LoadFieldInstr::RecognizedKindFromArrayCid(receiver_cid));
2023 InsertBefore(call, length, NULL, Definition::kValue); 2017 InsertBefore(call, length, NULL, Definition::kValue);
2024 2018
2025 // len_in_bytes = length * kBytesPerElement(receiver) 2019 // len_in_bytes = length * kBytesPerElement(receiver)
2026 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid); 2020 intptr_t element_size = FlowGraphCompiler::ElementSizeFor(receiver_cid);
2027 ConstantInstr* bytes_per_element = 2021 ConstantInstr* bytes_per_element =
2028 new ConstantInstr(Smi::Handle(Smi::New(element_size))); 2022 flow_graph()->GetConstant(Smi::Handle(Smi::New(element_size)));
2029 InsertBefore(call, bytes_per_element, NULL, Definition::kValue);
2030 BinarySmiOpInstr* len_in_bytes = 2023 BinarySmiOpInstr* len_in_bytes =
2031 new BinarySmiOpInstr(Token::kMUL, 2024 new BinarySmiOpInstr(Token::kMUL,
2032 call, 2025 call,
2033 new Value(length), 2026 new Value(length),
2034 new Value(bytes_per_element)); 2027 new Value(bytes_per_element));
2035 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue); 2028 InsertBefore(call, len_in_bytes, call->env(), Definition::kValue);
2036 2029
2037 // Check byte_index < len_in_bytes. 2030 // Check byte_index < len_in_bytes.
2038 InsertBefore(call, 2031 InsertBefore(call,
2039 new CheckArrayBoundInstr(new Value(len_in_bytes), 2032 new CheckArrayBoundInstr(new Value(len_in_bytes),
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2106 Bool::Cast(call->ArgumentAt(4)->AsConstant()->value()).value(); 2099 Bool::Cast(call->ArgumentAt(4)->AsConstant()->value()).value();
2107 const ICData& unary_checks = 2100 const ICData& unary_checks =
2108 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks()); 2101 ICData::ZoneHandle(call->ic_data()->AsUnaryClassChecks());
2109 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) { 2102 if (unary_checks.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
2110 Bool& as_bool = Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type)); 2103 Bool& as_bool = Bool::ZoneHandle(InstanceOfAsBool(unary_checks, type));
2111 if (!as_bool.IsNull()) { 2104 if (!as_bool.IsNull()) {
2112 AddReceiverCheck(call); 2105 AddReceiverCheck(call);
2113 if (negate) { 2106 if (negate) {
2114 as_bool = Bool::Get(!as_bool.value()); 2107 as_bool = Bool::Get(!as_bool.value());
2115 } 2108 }
2116 ConstantInstr* bool_const = new ConstantInstr(as_bool); 2109 ConstantInstr* bool_const = flow_graph()->GetConstant(as_bool);
2117 ReplaceCall(call, bool_const); 2110 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2111 PushArgumentInstr* push = call->PushArgumentAt(i);
2112 push->ReplaceUsesWith(push->value()->definition());
2113 push->RemoveFromGraph();
2114 }
2115 call->ReplaceUsesWith(bool_const);
2116 ASSERT(current_iterator()->Current() == call);
2117 current_iterator()->RemoveCurrentFromGraph();
2118 return; 2118 return;
2119 } 2119 }
2120 } 2120 }
2121 InstanceOfInstr* instance_of = 2121 InstanceOfInstr* instance_of =
2122 new InstanceOfInstr(call->token_pos(), 2122 new InstanceOfInstr(call->token_pos(),
2123 new Value(left), 2123 new Value(left),
2124 new Value(instantiator), 2124 new Value(instantiator),
2125 new Value(type_args), 2125 new Value(type_args),
2126 type, 2126 type,
2127 negate, 2127 negate,
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after
2672 2672
2673 void RangeAnalysis::Analyze() { 2673 void RangeAnalysis::Analyze() {
2674 CollectSmiValues(); 2674 CollectSmiValues();
2675 InsertConstraints(); 2675 InsertConstraints();
2676 InferRanges(); 2676 InferRanges();
2677 RemoveConstraints(); 2677 RemoveConstraints();
2678 } 2678 }
2679 2679
2680 2680
2681 void RangeAnalysis::CollectSmiValues() { 2681 void RangeAnalysis::CollectSmiValues() {
2682 const GrowableArray<Definition*>& initial =
2683 *flow_graph_->graph_entry()->initial_definitions();
2684 for (intptr_t i = 0; i < initial.length(); ++i) {
2685 Definition* current = initial[i];
2686 if (current->Type()->ToCid() == kSmiCid) {
2687 smi_values_.Add(current);
2688 }
2689 }
2690
2682 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 2691 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
2683 !block_it.Done(); 2692 !block_it.Done();
2684 block_it.Advance()) { 2693 block_it.Advance()) {
2685 BlockEntryInstr* block = block_it.Current(); 2694 BlockEntryInstr* block = block_it.Current();
2686 for (ForwardInstructionIterator instr_it(block); 2695 for (ForwardInstructionIterator instr_it(block);
2687 !instr_it.Done(); 2696 !instr_it.Done();
2688 instr_it.Advance()) { 2697 instr_it.Advance()) {
2689 Instruction* current = instr_it.Current(); 2698 Instruction* current = instr_it.Current();
2690 Definition* defn = current->AsDefinition(); 2699 Definition* defn = current->AsDefinition();
2691 if (defn != NULL) { 2700 if (defn != NULL) {
2692 if ((defn->Type()->ToCid() == kSmiCid) && 2701 if ((defn->Type()->ToCid() == kSmiCid) &&
2693 (defn->ssa_temp_index() != -1)) { 2702 (defn->ssa_temp_index() != -1)) {
2694 smi_values_.Add(defn); 2703 smi_values_.Add(defn);
2695 } 2704 }
2696 } else if (current->IsCheckSmi()) { 2705 } else if (current->IsCheckSmi()) {
2697 smi_checks_.Add(current->AsCheckSmi()); 2706 smi_checks_.Add(current->AsCheckSmi());
2698 } 2707 }
2699 } 2708 }
2700 2709
2701 JoinEntryInstr* join = block->AsJoinEntry(); 2710 JoinEntryInstr* join = block->AsJoinEntry();
2702 if (join != NULL) { 2711 if (join != NULL) {
2703 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) { 2712 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
2704 PhiInstr* current = phi_it.Current(); 2713 PhiInstr* current = phi_it.Current();
2705 if ((current->Type()->ToCid() == kSmiCid)) { 2714 if (current->Type()->ToCid() == kSmiCid) {
2706 smi_values_.Add(current); 2715 smi_values_.Add(current);
2707 } 2716 }
2708 } 2717 }
2709 } 2718 }
2710 } 2719 }
2711 } 2720 }
2712 2721
2713 2722
2714 // Returns true if use is dominated by the given instruction. 2723 // Returns true if use is dominated by the given instruction.
2715 // Note: uses that occur at instruction itself are not dominated by it. 2724 // Note: uses that occur at instruction itself are not dominated by it.
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
3099 // Initialize bitvector for quick filtering of smi values. 3108 // Initialize bitvector for quick filtering of smi values.
3100 smi_definitions_ = new BitVector(flow_graph_->current_ssa_temp_index()); 3109 smi_definitions_ = new BitVector(flow_graph_->current_ssa_temp_index());
3101 for (intptr_t i = 0; i < smi_values_.length(); i++) { 3110 for (intptr_t i = 0; i < smi_values_.length(); i++) {
3102 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); 3111 smi_definitions_->Add(smi_values_[i]->ssa_temp_index());
3103 } 3112 }
3104 for (intptr_t i = 0; i < constraints_.length(); i++) { 3113 for (intptr_t i = 0; i < constraints_.length(); i++) {
3105 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); 3114 smi_definitions_->Add(constraints_[i]->ssa_temp_index());
3106 } 3115 }
3107 3116
3108 // Infer initial values of ranges. 3117 // Infer initial values of ranges.
3118 const GrowableArray<Definition*>& initial =
3119 *flow_graph_->graph_entry()->initial_definitions();
3120 for (intptr_t i = 0; i < initial.length(); ++i) {
3121 Definition* definition = initial[i];
3122 if (smi_definitions_->Contains(definition->ssa_temp_index())) {
3123 definition->InferRange();
3124 }
3125 }
3109 InferRangesRecursive(flow_graph_->graph_entry()); 3126 InferRangesRecursive(flow_graph_->graph_entry());
3110 3127
3111 if (FLAG_trace_range_analysis) { 3128 if (FLAG_trace_range_analysis) {
3112 OS::Print("---- after range analysis -------\n"); 3129 OS::Print("---- after range analysis -------\n");
3113 FlowGraphPrinter printer(*flow_graph_); 3130 FlowGraphPrinter printer(*flow_graph_);
3114 printer.PrintBlocks(); 3131 printer.PrintBlocks();
3115 } 3132 }
3116 } 3133 }
3117 3134
3118 3135
(...skipping 2233 matching lines...) Expand 10 before | Expand all | Expand 10 after
5352 !defn->IsPushArgument() && 5369 !defn->IsPushArgument() &&
5353 !defn->IsStoreIndexed() && 5370 !defn->IsStoreIndexed() &&
5354 !defn->IsStoreInstanceField() && 5371 !defn->IsStoreInstanceField() &&
5355 !defn->IsStoreStaticField() && 5372 !defn->IsStoreStaticField() &&
5356 !defn->IsStoreVMField()) { 5373 !defn->IsStoreVMField()) {
5357 if (FLAG_trace_constant_propagation) { 5374 if (FLAG_trace_constant_propagation) {
5358 OS::Print("Constant v%"Pd" = %s\n", 5375 OS::Print("Constant v%"Pd" = %s\n",
5359 defn->ssa_temp_index(), 5376 defn->ssa_temp_index(),
5360 defn->constant_value().ToCString()); 5377 defn->constant_value().ToCString());
5361 } 5378 }
5362 defn->ReplaceWith(new ConstantInstr(defn->constant_value()), &i); 5379 ConstantInstr* constant = graph_->GetConstant(defn->constant_value());
5380 defn->ReplaceUsesWith(constant);
5381 i.RemoveCurrentFromGraph();
5363 } 5382 }
5364 } 5383 }
5365 5384
5366 // Replace branches where one target is unreachable with jumps. 5385 // Replace branches where one target is unreachable with jumps.
5367 BranchInstr* branch = block->last_instruction()->AsBranch(); 5386 BranchInstr* branch = block->last_instruction()->AsBranch();
5368 if (branch != NULL) { 5387 if (branch != NULL) {
5369 TargetEntryInstr* if_true = branch->true_successor(); 5388 TargetEntryInstr* if_true = branch->true_successor();
5370 TargetEntryInstr* if_false = branch->false_successor(); 5389 TargetEntryInstr* if_false = branch->false_successor();
5371 JoinEntryInstr* join = NULL; 5390 JoinEntryInstr* join = NULL;
5372 Instruction* next = NULL; 5391 Instruction* next = NULL;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
5442 } 5461 }
5443 5462
5444 5463
5445 bool BranchSimplifier::Match(JoinEntryInstr* block) { 5464 bool BranchSimplifier::Match(JoinEntryInstr* block) {
5446 // Match the pattern of a branch on a comparison whose left operand is a 5465 // Match the pattern of a branch on a comparison whose left operand is a
5447 // phi from the same block, and whose right operand is a constant. 5466 // phi from the same block, and whose right operand is a constant.
5448 // 5467 //
5449 // Branch(Comparison(kind, Phi, Constant)) 5468 // Branch(Comparison(kind, Phi, Constant))
5450 // 5469 //
5451 // These are the branches produced by inlining in a test context. Also, 5470 // These are the branches produced by inlining in a test context. Also,
5452 // the phi and the constant have no other uses so they can simply be 5471 // the phi has no other uses so they can simply be eliminated. The block
5453 // eliminated. The block has no other phis and no instructions 5472 // has no other phis and no instructions intervening between the phi and
5454 // intervening between the phi, constant, and branch so the block can 5473 // branch so the block can simply be eliminated.
5455 // simply be eliminated.
5456 BranchInstr* branch = block->last_instruction()->AsBranch(); 5474 BranchInstr* branch = block->last_instruction()->AsBranch();
5457 ASSERT(branch != NULL); 5475 ASSERT(branch != NULL);
5458 ComparisonInstr* comparison = branch->comparison(); 5476 ComparisonInstr* comparison = branch->comparison();
5459 Value* left = comparison->left(); 5477 Value* left = comparison->left();
5460 PhiInstr* phi = left->definition()->AsPhi(); 5478 PhiInstr* phi = left->definition()->AsPhi();
5461 Value* right = comparison->right(); 5479 Value* right = comparison->right();
5462 ConstantInstr* constant = right->definition()->AsConstant(); 5480 ConstantInstr* constant = right->definition()->AsConstant();
5463 return (phi != NULL) && 5481 return (phi != NULL) &&
5464 (constant != NULL) && 5482 (constant != NULL) &&
5465 (phi->GetBlock() == block) && 5483 (phi->GetBlock() == block) &&
5466 PhiHasSingleUse(phi, left) && 5484 PhiHasSingleUse(phi, left) &&
5467 constant->HasOnlyUse(right) && 5485 (block->next() == branch) &&
5468 (block->next() == constant) &&
5469 (constant->next() == branch) &&
5470 (block->phis()->length() == 1); 5486 (block->phis()->length() == 1);
5471 } 5487 }
5472 5488
5473 5489
5474 JoinEntryInstr* BranchSimplifier::ToJoinEntry(TargetEntryInstr* target) { 5490 JoinEntryInstr* BranchSimplifier::ToJoinEntry(TargetEntryInstr* target) {
5475 // Convert a target block into a join block. Branches will be duplicated 5491 // Convert a target block into a join block. Branches will be duplicated
5476 // so the former true and false targets become joins of the control flows 5492 // so the former true and false targets become joins of the control flows
5477 // from all the duplicated branches. 5493 // from all the duplicated branches.
5478 JoinEntryInstr* join = 5494 JoinEntryInstr* join =
5479 new JoinEntryInstr(target->block_id(), target->try_index()); 5495 new JoinEntryInstr(target->block_id(), target->try_index());
5480 join->InheritDeoptTarget(target); 5496 join->InheritDeoptTarget(target);
5481 join->LinkTo(target->next()); 5497 join->LinkTo(target->next());
5482 join->set_last_instruction(target->last_instruction()); 5498 join->set_last_instruction(target->last_instruction());
5483 target->UnuseAllInputs(); 5499 target->UnuseAllInputs();
5484 return join; 5500 return join;
5485 } 5501 }
5486 5502
5487 5503
5488 ConstantInstr* BranchSimplifier::CloneConstant(FlowGraph* flow_graph,
5489 ConstantInstr* constant) {
5490 ConstantInstr* new_constant = new ConstantInstr(constant->value());
5491 new_constant->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index());
5492 return new_constant;
5493 }
5494
5495
5496 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch, 5504 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch,
5497 Value* left, 5505 Value* left,
5498 Value* right) { 5506 Value* right) {
5499 ComparisonInstr* comparison = branch->comparison(); 5507 ComparisonInstr* comparison = branch->comparison();
5500 ComparisonInstr* new_comparison = NULL; 5508 ComparisonInstr* new_comparison = NULL;
5501 if (comparison->IsStrictCompare()) { 5509 if (comparison->IsStrictCompare()) {
5502 new_comparison = new StrictCompareInstr(comparison->kind(), left, right); 5510 new_comparison = new StrictCompareInstr(comparison->kind(), left, right);
5503 } else if (comparison->IsEqualityCompare()) { 5511 } else if (comparison->IsEqualityCompare()) {
5504 EqualityCompareInstr* equality_compare = comparison->AsEqualityCompare(); 5512 EqualityCompareInstr* equality_compare = comparison->AsEqualityCompare();
5505 EqualityCompareInstr* new_equality_compare = 5513 EqualityCompareInstr* new_equality_compare =
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
5571 ComparisonInstr* comparison = branch->comparison(); 5579 ComparisonInstr* comparison = branch->comparison();
5572 PhiInstr* phi = comparison->left()->definition()->AsPhi(); 5580 PhiInstr* phi = comparison->left()->definition()->AsPhi();
5573 ConstantInstr* constant = comparison->right()->definition()->AsConstant(); 5581 ConstantInstr* constant = comparison->right()->definition()->AsConstant();
5574 ASSERT(constant != NULL); 5582 ASSERT(constant != NULL);
5575 // Copy the constant and branch and push it to all the predecessors. 5583 // Copy the constant and branch and push it to all the predecessors.
5576 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) { 5584 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) {
5577 GotoInstr* old_goto = 5585 GotoInstr* old_goto =
5578 block->PredecessorAt(i)->last_instruction()->AsGoto(); 5586 block->PredecessorAt(i)->last_instruction()->AsGoto();
5579 ASSERT(old_goto != NULL); 5587 ASSERT(old_goto != NULL);
5580 5588
5581 // Insert a copy of the constant in all the predecessors.
5582 ConstantInstr* new_constant = CloneConstant(flow_graph, constant);
5583 new_constant->InsertBefore(old_goto);
5584
5585 // Replace the goto in each predecessor with a rewritten branch, 5589 // Replace the goto in each predecessor with a rewritten branch,
5586 // rewritten to use the corresponding phi input instead of the phi. 5590 // rewritten to use the corresponding phi input instead of the phi.
5587 Value* new_left = phi->InputAt(i)->Copy(); 5591 Value* new_left = phi->InputAt(i)->Copy();
5588 Value* new_right = new Value(new_constant); 5592 Value* new_right = new Value(constant);
5589 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right); 5593 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right);
5590 if (branch->env() == NULL) { 5594 if (branch->env() == NULL) {
5591 new_branch->InheritDeoptTarget(old_goto); 5595 new_branch->InheritDeoptTarget(old_goto);
5592 } else { 5596 } else {
5593 // Take the environment from the branch if it has one. 5597 // Take the environment from the branch if it has one.
5594 new_branch->InheritDeoptTarget(branch); 5598 new_branch->InheritDeoptTarget(branch);
5595 // InheritDeoptTarget gave the new branch's comparison the same 5599 // InheritDeoptTarget gave the new branch's comparison the same
5596 // deopt id that it gave the new branch. The id should be the 5600 // deopt id that it gave the new branch. The id should be the
5597 // deopt id of the original comparison. 5601 // deopt id of the original comparison.
5598 new_branch->comparison()->SetDeoptId(comparison->GetDeoptId()); 5602 new_branch->comparison()->SetDeoptId(comparison->GetDeoptId());
5599 // The phi and constant can be used in the branch's environment. 5603 // The phi can be used in the branch's environment. Rename such
5600 // Rename such uses. 5604 // uses.
5601 for (Environment::DeepIterator it(new_branch->env()); 5605 for (Environment::DeepIterator it(new_branch->env());
5602 !it.Done(); 5606 !it.Done();
5603 it.Advance()) { 5607 it.Advance()) {
5604 Value* use = it.CurrentValue(); 5608 Value* use = it.CurrentValue();
5605 Definition* replacement = NULL;
5606 if (use->definition() == phi) { 5609 if (use->definition() == phi) {
5607 replacement = phi->InputAt(i)->definition(); 5610 Definition* replacement = phi->InputAt(i)->definition();
5608 } else if (use->definition() == constant) {
5609 replacement = new_constant;
5610 }
5611 if (replacement != NULL) {
5612 use->RemoveFromUseList(); 5611 use->RemoveFromUseList();
5613 use->set_definition(replacement); 5612 use->set_definition(replacement);
5614 replacement->AddEnvUse(use); 5613 replacement->AddEnvUse(use);
5615 } 5614 }
5616 } 5615 }
5617 } 5616 }
5618 5617
5619 new_branch->InsertBefore(old_goto); 5618 new_branch->InsertBefore(old_goto);
5620 new_branch->set_next(NULL); // Detaching the goto from the graph. 5619 new_branch->set_next(NULL); // Detaching the goto from the graph.
5621 old_goto->UnuseAllInputs(); 5620 old_goto->UnuseAllInputs();
(...skipping 25 matching lines...) Expand all
5647 goto_false->InheritDeoptTarget(join_false); 5646 goto_false->InheritDeoptTarget(join_false);
5648 false_target->LinkTo(goto_false); 5647 false_target->LinkTo(goto_false);
5649 false_target->set_last_instruction(goto_false); 5648 false_target->set_last_instruction(goto_false);
5650 } 5649 }
5651 // When all predecessors have been rewritten, the original block is 5650 // When all predecessors have been rewritten, the original block is
5652 // unreachable from the graph. 5651 // unreachable from the graph.
5653 phi->UnuseAllInputs(); 5652 phi->UnuseAllInputs();
5654 branch->UnuseAllInputs(); 5653 branch->UnuseAllInputs();
5655 block->UnuseAllInputs(); 5654 block->UnuseAllInputs();
5656 ASSERT(!phi->HasUses()); 5655 ASSERT(!phi->HasUses());
5657 ASSERT(!constant->HasUses());
5658 } 5656 }
5659 } 5657 }
5660 5658
5661 if (changed) { 5659 if (changed) {
5662 // We may have changed the block order and the dominator tree. 5660 // We may have changed the block order and the dominator tree.
5663 flow_graph->DiscoverBlocks(); 5661 flow_graph->DiscoverBlocks();
5664 GrowableArray<BitVector*> dominance_frontier; 5662 GrowableArray<BitVector*> dominance_frontier;
5665 flow_graph->ComputeDominators(&dominance_frontier); 5663 flow_graph->ComputeDominators(&dominance_frontier);
5666 } 5664 }
5667 } 5665 }
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
5790 if (changed) { 5788 if (changed) {
5791 // We may have changed the block order and the dominator tree. 5789 // We may have changed the block order and the dominator tree.
5792 flow_graph->DiscoverBlocks(); 5790 flow_graph->DiscoverBlocks();
5793 GrowableArray<BitVector*> dominance_frontier; 5791 GrowableArray<BitVector*> dominance_frontier;
5794 flow_graph->ComputeDominators(&dominance_frontier); 5792 flow_graph->ComputeDominators(&dominance_frontier);
5795 } 5793 }
5796 } 5794 }
5797 5795
5798 5796
5799 } // namespace dart 5797 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698