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

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

Issue 12335063: Add functions for setting an environment and rebinding a use. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased and incorportated review comments. Created 7 years, 9 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 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 replacement_defn->ssa_temp_index()); 283 replacement_defn->ssa_temp_index());
284 } 284 }
285 } else if (FLAG_trace_optimization) { 285 } else if (FLAG_trace_optimization) {
286 if (current_defn == NULL) { 286 if (current_defn == NULL) {
287 OS::Print("Removing %s\n", current->DebugName()); 287 OS::Print("Removing %s\n", current->DebugName());
288 } else { 288 } else {
289 ASSERT(!current_defn->HasUses()); 289 ASSERT(!current_defn->HasUses());
290 OS::Print("Removing v%"Pd".\n", current_defn->ssa_temp_index()); 290 OS::Print("Removing v%"Pd".\n", current_defn->ssa_temp_index());
291 } 291 }
292 } 292 }
293 current->UnuseAllInputs();
294 iterator->RemoveCurrentFromGraph(); 293 iterator->RemoveCurrentFromGraph();
295 } 294 }
296 295
297 296
298 void FlowGraphOptimizer::Canonicalize() { 297 void FlowGraphOptimizer::Canonicalize() {
299 for (intptr_t i = 0; i < block_order_.length(); ++i) { 298 for (intptr_t i = 0; i < block_order_.length(); ++i) {
300 BlockEntryInstr* entry = block_order_[i]; 299 BlockEntryInstr* entry = block_order_[i];
301 entry->Accept(this); 300 entry->Accept(this);
302 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 301 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
303 Instruction* current = it.Current(); 302 Instruction* current = it.Current();
(...skipping 22 matching lines...) Expand all
326 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 325 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
327 converted = new UnboxIntegerInstr(use->CopyWithType(), deopt_id); 326 converted = new UnboxIntegerInstr(use->CopyWithType(), deopt_id);
328 327
329 } else if ((from == kUnboxedMint) && (to == kTagged)) { 328 } else if ((from == kUnboxedMint) && (to == kTagged)) {
330 converted = new BoxIntegerInstr(use->CopyWithType()); 329 converted = new BoxIntegerInstr(use->CopyWithType());
331 330
332 } else if (from == kUnboxedMint && to == kUnboxedDouble) { 331 } else if (from == kUnboxedMint && to == kUnboxedDouble) {
333 // Convert by boxing/unboxing. 332 // Convert by boxing/unboxing.
334 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. 333 // TODO(fschneider): Implement direct unboxed mint-to-double conversion.
335 BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType()); 334 BoxIntegerInstr* boxed = new BoxIntegerInstr(use->CopyWithType());
336 use->RemoveFromUseList(); 335 use->BindTo(boxed);
337 use->set_definition(boxed);
338 boxed->AddInputUse(use);
339 InsertBefore(insert_before, boxed, NULL, Definition::kValue); 336 InsertBefore(insert_before, boxed, NULL, Definition::kValue);
340 337
341 const intptr_t deopt_id = (deopt_target != NULL) ? 338 const intptr_t deopt_id = (deopt_target != NULL) ?
342 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 339 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
343 converted = new UnboxDoubleInstr(new Value(boxed), deopt_id); 340 converted = new UnboxDoubleInstr(new Value(boxed), deopt_id);
344 341
345 } else if ((from == kUnboxedDouble) && (to == kTagged)) { 342 } else if ((from == kUnboxedDouble) && (to == kTagged)) {
346 converted = new BoxDoubleInstr(use->CopyWithType(), NULL); 343 converted = new BoxDoubleInstr(use->CopyWithType(), NULL);
347 344
348 } else if ((from == kTagged) && (to == kUnboxedDouble)) { 345 } else if ((from == kTagged) && (to == kUnboxedDouble)) {
349 ASSERT((deopt_target != NULL) || 346 ASSERT((deopt_target != NULL) ||
350 (use->Type()->ToCid() == kDoubleCid)); 347 (use->Type()->ToCid() == kDoubleCid));
351 const intptr_t deopt_id = (deopt_target != NULL) ? 348 const intptr_t deopt_id = (deopt_target != NULL) ?
352 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; 349 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId;
353 ConstantInstr* constant = use->definition()->AsConstant(); 350 ConstantInstr* constant = use->definition()->AsConstant();
354 if ((constant != NULL) && constant->value().IsSmi()) { 351 if ((constant != NULL) && constant->value().IsSmi()) {
355 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue(); 352 const double dbl_val = Smi::Cast(constant->value()).AsDoubleValue();
356 const Double& dbl_obj = 353 const Double& dbl_obj =
357 Double::ZoneHandle(Double::New(dbl_val, Heap::kOld)); 354 Double::ZoneHandle(Double::New(dbl_val, Heap::kOld));
358 ConstantInstr* double_const = new ConstantInstr(dbl_obj); 355 ConstantInstr* double_const = new ConstantInstr(dbl_obj);
359 InsertBefore(insert_before, double_const, NULL, Definition::kValue); 356 InsertBefore(insert_before, double_const, NULL, Definition::kValue);
360 converted = new UnboxDoubleInstr(new Value(double_const), deopt_id); 357 converted = new UnboxDoubleInstr(new Value(double_const), deopt_id);
361 } else { 358 } else {
362 converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id); 359 converted = new UnboxDoubleInstr(use->CopyWithType(), deopt_id);
363 } 360 }
364 } 361 }
365 ASSERT(converted != NULL); 362 ASSERT(converted != NULL);
366 use->RemoveFromUseList(); 363 use->BindTo(converted);
367 use->set_definition(converted);
368 converted->AddInputUse(use);
369 InsertBefore(insert_before, converted, use->instruction()->env(), 364 InsertBefore(insert_before, converted, use->instruction()->env(),
370 Definition::kValue); 365 Definition::kValue);
371 } 366 }
372 367
373 368
374 void FlowGraphOptimizer::InsertConversionsFor(Definition* def) { 369 void FlowGraphOptimizer::InsertConversionsFor(Definition* def) {
375 const Representation from_rep = def->representation(); 370 const Representation from_rep = def->representation();
376 371
377 for (Value::Iterator it(def->input_use_list()); 372 for (Value::Iterator it(def->input_use_list());
378 !it.Done(); 373 !it.Done();
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids); 553 return ICDataHasOnlyReceiverArgumentClassIds(ic_data, class_ids, class_ids);
559 } 554 }
560 555
561 556
562 void FlowGraphOptimizer::ReplaceCall(Definition* call, 557 void FlowGraphOptimizer::ReplaceCall(Definition* call,
563 Definition* replacement) { 558 Definition* replacement) {
564 // Remove the original push arguments. 559 // Remove the original push arguments.
565 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 560 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
566 PushArgumentInstr* push = call->PushArgumentAt(i); 561 PushArgumentInstr* push = call->PushArgumentAt(i);
567 push->ReplaceUsesWith(push->value()->definition()); 562 push->ReplaceUsesWith(push->value()->definition());
568 push->UnuseAllInputs();
569 push->RemoveFromGraph(); 563 push->RemoveFromGraph();
570 } 564 }
571 call->ReplaceWith(replacement, current_iterator()); 565 call->ReplaceWith(replacement, current_iterator());
572 } 566 }
573 567
574 568
575 static intptr_t ReceiverClassId(InstanceCallInstr* call) { 569 static intptr_t ReceiverClassId(InstanceCallInstr* call) {
576 if (!call->HasICData()) return kIllegalCid; 570 if (!call->HasICData()) return kIllegalCid;
577 571
578 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); 572 const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks());
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 ASSERT(!field.IsNull()); 1227 ASSERT(!field.IsNull());
1234 1228
1235 if (InstanceCallNeedsClassCheck(call)) { 1229 if (InstanceCallNeedsClassCheck(call)) {
1236 AddReceiverCheck(call); 1230 AddReceiverCheck(call);
1237 } 1231 }
1238 LoadFieldInstr* load = new LoadFieldInstr( 1232 LoadFieldInstr* load = new LoadFieldInstr(
1239 new Value(call->ArgumentAt(0)), 1233 new Value(call->ArgumentAt(0)),
1240 field.Offset(), 1234 field.Offset(),
1241 AbstractType::ZoneHandle(field.type()), 1235 AbstractType::ZoneHandle(field.type()),
1242 field.is_final()); 1236 field.is_final());
1243 // Detach environment from the original instruction because it can't 1237 // Discard the environment from the original instruction because the load
1244 // deoptimize. 1238 // can't deoptimize.
1245 for (Environment::DeepIterator it(call->env()); !it.Done(); it.Advance()) { 1239 call->RemoveEnvironment();
1246 it.CurrentValue()->RemoveFromUseList();
1247 }
1248 call->set_env(NULL);
1249 ReplaceCall(call, load); 1240 ReplaceCall(call, load);
1250 } 1241 }
1251 1242
1252 1243
1253 void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call, 1244 void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call,
1254 intptr_t length_offset, 1245 intptr_t length_offset,
1255 bool is_immutable, 1246 bool is_immutable,
1256 MethodRecognizer::Kind kind) { 1247 MethodRecognizer::Kind kind) {
1257 AddReceiverCheck(call); 1248 AddReceiverCheck(call);
1258 1249
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after
1913 instr->deopt_id()), 1904 instr->deopt_id()),
1914 instr->env(), 1905 instr->env(),
1915 Definition::kEffect); 1906 Definition::kEffect);
1916 needs_store_barrier = false; 1907 needs_store_barrier = false;
1917 } 1908 }
1918 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( 1909 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr(
1919 field, 1910 field,
1920 new Value(instr->ArgumentAt(0)), 1911 new Value(instr->ArgumentAt(0)),
1921 new Value(instr->ArgumentAt(1)), 1912 new Value(instr->ArgumentAt(1)),
1922 needs_store_barrier); 1913 needs_store_barrier);
1923 // Detach environment from the original instruction because it can't 1914 // Discard the environment from the original instruction because the store
1924 // deoptimize. 1915 // can't deoptimize.
1925 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) { 1916 instr->RemoveEnvironment();
1926 it.CurrentValue()->RemoveFromUseList();
1927 }
1928 instr->set_env(NULL);
1929 ReplaceCall(instr, store); 1917 ReplaceCall(instr, store);
1930 return true; 1918 return true;
1931 } 1919 }
1932 1920
1933 1921
1934 void FlowGraphOptimizer::HandleRelationalOp(RelationalOpInstr* comp) { 1922 void FlowGraphOptimizer::HandleRelationalOp(RelationalOpInstr* comp) {
1935 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) { 1923 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) {
1936 return; 1924 return;
1937 } 1925 }
1938 const ICData& ic_data = *comp->ic_data(); 1926 const ICData& ic_data = *comp->ic_data();
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
2264 for (Value::Iterator it(def->input_use_list()); 2252 for (Value::Iterator it(def->input_use_list());
2265 !it.Done(); 2253 !it.Done();
2266 it.Advance()) { 2254 it.Advance()) {
2267 Value* use = it.Current(); 2255 Value* use = it.Current();
2268 2256
2269 // Skip dead phis. 2257 // Skip dead phis.
2270 PhiInstr* phi = use->instruction()->AsPhi(); 2258 PhiInstr* phi = use->instruction()->AsPhi();
2271 if ((phi != NULL) && !phi->is_alive()) continue; 2259 if ((phi != NULL) && !phi->is_alive()) continue;
2272 2260
2273 if (IsDominatedUse(dom, use)) { 2261 if (IsDominatedUse(dom, use)) {
2274 use->RemoveFromUseList(); 2262 use->BindTo(other);
2275 use->set_definition(other);
2276 other->AddInputUse(use);
2277 } 2263 }
2278 } 2264 }
2279 } 2265 }
2280 2266
2281 2267
2282 // For a comparison operation return an operation for the equivalent flipped 2268 // For a comparison operation return an operation for the equivalent flipped
2283 // comparison: a (op) b === b (op') a. 2269 // comparison: a (op) b === b (op') a.
2284 static Token::Kind FlipComparison(Token::Kind op) { 2270 static Token::Kind FlipComparison(Token::Kind op) {
2285 switch (op) { 2271 switch (op) {
2286 case Token::kEQ: return Token::kEQ; 2272 case Token::kEQ: return Token::kEQ;
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
2611 if ((defn != NULL) && 2597 if ((defn != NULL) &&
2612 (defn->ssa_temp_index() != -1) && 2598 (defn->ssa_temp_index() != -1) &&
2613 smi_definitions_->Contains(defn->ssa_temp_index())) { 2599 smi_definitions_->Contains(defn->ssa_temp_index())) {
2614 defn->InferRange(); 2600 defn->InferRange();
2615 } else if (FLAG_array_bounds_check_elimination && 2601 } else if (FLAG_array_bounds_check_elimination &&
2616 current->IsCheckArrayBound()) { 2602 current->IsCheckArrayBound()) {
2617 CheckArrayBoundInstr* check = current->AsCheckArrayBound(); 2603 CheckArrayBoundInstr* check = current->AsCheckArrayBound();
2618 RangeBoundary array_length = 2604 RangeBoundary array_length =
2619 RangeBoundary::FromDefinition(check->length()->definition()); 2605 RangeBoundary::FromDefinition(check->length()->definition());
2620 if (check->IsRedundant(array_length)) { 2606 if (check->IsRedundant(array_length)) {
2621 current->UnuseAllInputs();
2622 it.RemoveCurrentFromGraph(); 2607 it.RemoveCurrentFromGraph();
2623 } 2608 }
2624 } 2609 }
2625 } 2610 }
2626 2611
2627 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { 2612 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
2628 InferRangesRecursive(block->dominated_blocks()[i]); 2613 InferRangesRecursive(block->dominated_blocks()[i]);
2629 } 2614 }
2630 } 2615 }
2631 2616
(...skipping 21 matching lines...) Expand all
2653 2638
2654 void RangeAnalysis::RemoveConstraints() { 2639 void RangeAnalysis::RemoveConstraints() {
2655 for (intptr_t i = 0; i < constraints_.length(); i++) { 2640 for (intptr_t i = 0; i < constraints_.length(); i++) {
2656 Definition* def = constraints_[i]->value()->definition(); 2641 Definition* def = constraints_[i]->value()->definition();
2657 // Some constraints might be constraining constraints. Unwind the chain of 2642 // Some constraints might be constraining constraints. Unwind the chain of
2658 // constraints until we reach the actual definition. 2643 // constraints until we reach the actual definition.
2659 while (def->IsConstraint()) { 2644 while (def->IsConstraint()) {
2660 def = def->AsConstraint()->value()->definition(); 2645 def = def->AsConstraint()->value()->definition();
2661 } 2646 }
2662 constraints_[i]->ReplaceUsesWith(def); 2647 constraints_[i]->ReplaceUsesWith(def);
2663 constraints_[i]->UnuseAllInputs();
2664 constraints_[i]->RemoveFromGraph(); 2648 constraints_[i]->RemoveFromGraph();
2665 } 2649 }
2666 } 2650 }
2667 2651
2668 2652
2669 void FlowGraphOptimizer::InferSmiRanges() { 2653 void FlowGraphOptimizer::InferSmiRanges() {
2670 RangeAnalysis range_analysis(flow_graph_); 2654 RangeAnalysis range_analysis(flow_graph_);
2671 range_analysis.Analyze(); 2655 range_analysis.Analyze();
2672 } 2656 }
2673 2657
2674 2658
2675 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) { 2659 static BlockEntryInstr* FindPreHeader(BlockEntryInstr* header) {
2676 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) { 2660 for (intptr_t j = 0; j < header->PredecessorCount(); ++j) {
2677 BlockEntryInstr* candidate = header->PredecessorAt(j); 2661 BlockEntryInstr* candidate = header->PredecessorAt(j);
2678 if (header->dominator() == candidate) { 2662 if (header->dominator() == candidate) {
2679 return candidate; 2663 return candidate;
2680 } 2664 }
2681 } 2665 }
2682 return NULL; 2666 return NULL;
2683 } 2667 }
2684 2668
2685 2669
2670 LICM::LICM(FlowGraph* flow_graph) : flow_graph_(flow_graph) {
2671 }
2672
2673
2686 void LICM::Hoist(ForwardInstructionIterator* it, 2674 void LICM::Hoist(ForwardInstructionIterator* it,
2687 BlockEntryInstr* pre_header, 2675 BlockEntryInstr* pre_header,
2688 Instruction* current) { 2676 Instruction* current) {
2689 // TODO(fschneider): Avoid repeated deoptimization when 2677 // TODO(fschneider): Avoid repeated deoptimization when
2690 // speculatively hoisting checks. 2678 // speculatively hoisting checks.
2691 if (FLAG_trace_optimization) { 2679 if (FLAG_trace_optimization) {
2692 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n", 2680 OS::Print("Hoisting instruction %s:%"Pd" from B%"Pd" to B%"Pd"\n",
2693 current->DebugName(), 2681 current->DebugName(),
2694 current->GetDeoptId(), 2682 current->GetDeoptId(),
2695 current->GetBlock()->block_id(), 2683 current->GetBlock()->block_id(),
2696 pre_header->block_id()); 2684 pre_header->block_id());
2697 } 2685 }
2698 // Move the instruction out of the loop. 2686 // Move the instruction out of the loop.
2687 current->RemoveEnvironment();
2699 it->RemoveCurrentFromGraph(); 2688 it->RemoveCurrentFromGraph();
2700 GotoInstr* last = pre_header->last_instruction()->AsGoto(); 2689 GotoInstr* last = pre_header->last_instruction()->AsGoto();
2701 current->InsertBefore(last); 2690 // Using kind kEffect will not assign a fresh ssa temporary index.
2702 // Attach the environment of the Goto instruction to the hoisted 2691 flow_graph()->InsertBefore(last, current, last->env(), Definition::kEffect);
2703 // instruction and set the correct deopt_id.
2704 ASSERT(last->env() != NULL);
2705 last->env()->DeepCopyTo(current);
2706 current->deopt_id_ = last->GetDeoptId(); 2692 current->deopt_id_ = last->GetDeoptId();
2707 } 2693 }
2708 2694
2709 2695
2710 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it, 2696 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it,
2711 BlockEntryInstr* header, 2697 BlockEntryInstr* header,
2712 BlockEntryInstr* pre_header, 2698 BlockEntryInstr* pre_header,
2713 CheckSmiInstr* current) { 2699 CheckSmiInstr* current) {
2714 PhiInstr* phi = current->value()->definition()->AsPhi(); 2700 PhiInstr* phi = current->value()->definition()->AsPhi();
2715 if (!header->loop_info()->Contains(phi->block()->preorder_number())) { 2701 if (!header->loop_info()->Contains(phi->block()->preorder_number())) {
2716 return; 2702 return;
2717 } 2703 }
2718 2704
2719 if (phi->Type()->ToCid() == kSmiCid) { 2705 if (phi->Type()->ToCid() == kSmiCid) {
2720 current->UnuseAllInputs();
2721 it->RemoveCurrentFromGraph(); 2706 it->RemoveCurrentFromGraph();
2722 return; 2707 return;
2723 } 2708 }
2724 2709
2725 // Check if there is only a single kDynamicCid input to the phi that 2710 // Check if there is only a single kDynamicCid input to the phi that
2726 // comes from the pre-header. 2711 // comes from the pre-header.
2727 const intptr_t kNotFound = -1; 2712 const intptr_t kNotFound = -1;
2728 intptr_t non_smi_input = kNotFound; 2713 intptr_t non_smi_input = kNotFound;
2729 for (intptr_t i = 0; i < phi->InputCount(); ++i) { 2714 for (intptr_t i = 0; i < phi->InputCount(); ++i) {
2730 Value* input = phi->InputAt(i); 2715 Value* input = phi->InputAt(i);
(...skipping 10 matching lines...) Expand all
2741 } 2726 }
2742 2727
2743 if ((non_smi_input == kNotFound) || 2728 if ((non_smi_input == kNotFound) ||
2744 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { 2729 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) {
2745 return; 2730 return;
2746 } 2731 }
2747 2732
2748 // Host CheckSmi instruction and make this phi smi one. 2733 // Host CheckSmi instruction and make this phi smi one.
2749 Hoist(it, pre_header, current); 2734 Hoist(it, pre_header, current);
2750 2735
2751 // Replace value we are checking with phi's input. Maintain use lists. 2736 // Replace value we are checking with phi's input.
2752 Definition* non_smi_input_defn = phi->InputAt(non_smi_input)->definition(); 2737 current->value()->BindTo(phi->InputAt(non_smi_input)->definition());
2753 current->value()->RemoveFromUseList();
2754 current->value()->set_definition(non_smi_input_defn);
2755 non_smi_input_defn->AddInputUse(current->value());
2756 2738
2757 phi->UpdateType(CompileType::FromCid(kSmiCid)); 2739 phi->UpdateType(CompileType::FromCid(kSmiCid));
2758 } 2740 }
2759 2741
2760 2742
2761 void LICM::Optimize(FlowGraph* flow_graph) { 2743 void LICM::Optimize() {
2762 GrowableArray<BlockEntryInstr*> loop_headers; 2744 GrowableArray<BlockEntryInstr*> loop_headers;
2763 flow_graph->ComputeLoops(&loop_headers); 2745 flow_graph()->ComputeLoops(&loop_headers);
2764 2746
2765 for (intptr_t i = 0; i < loop_headers.length(); ++i) { 2747 for (intptr_t i = 0; i < loop_headers.length(); ++i) {
2766 BlockEntryInstr* header = loop_headers[i]; 2748 BlockEntryInstr* header = loop_headers[i];
2767 // Skip loop that don't have a pre-header block. 2749 // Skip loop that don't have a pre-header block.
2768 BlockEntryInstr* pre_header = FindPreHeader(header); 2750 BlockEntryInstr* pre_header = FindPreHeader(header);
2769 if (pre_header == NULL) continue; 2751 if (pre_header == NULL) continue;
2770 2752
2771 for (BitVector::Iterator loop_it(header->loop_info()); 2753 for (BitVector::Iterator loop_it(header->loop_info());
2772 !loop_it.Done(); 2754 !loop_it.Done();
2773 loop_it.Advance()) { 2755 loop_it.Advance()) {
2774 BlockEntryInstr* block = flow_graph->preorder()[loop_it.Current()]; 2756 BlockEntryInstr* block = flow_graph()->preorder()[loop_it.Current()];
2775 for (ForwardInstructionIterator it(block); 2757 for (ForwardInstructionIterator it(block);
2776 !it.Done(); 2758 !it.Done();
2777 it.Advance()) { 2759 it.Advance()) {
2778 Instruction* current = it.Current(); 2760 Instruction* current = it.Current();
2779 if (!current->IsPushArgument() && !current->AffectedBySideEffect()) { 2761 if (!current->IsPushArgument() && !current->AffectedBySideEffect()) {
2780 bool inputs_loop_invariant = true; 2762 bool inputs_loop_invariant = true;
2781 for (int i = 0; i < current->InputCount(); ++i) { 2763 for (int i = 0; i < current->InputCount(); ++i) {
2782 Definition* input_def = current->InputAt(i)->definition(); 2764 Definition* input_def = current->InputAt(i)->definition();
2783 if (!input_def->GetBlock()->Dominates(pre_header)) { 2765 if (!input_def->GetBlock()->Dominates(pre_header)) {
2784 inputs_loop_invariant = false; 2766 inputs_loop_invariant = false;
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
3120 3102
3121 Definition* replacement = (*out_values)[expr_id]; 3103 Definition* replacement = (*out_values)[expr_id];
3122 EnsureSSATempIndex(graph_, defn, replacement); 3104 EnsureSSATempIndex(graph_, defn, replacement);
3123 if (FLAG_trace_optimization) { 3105 if (FLAG_trace_optimization) {
3124 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", 3106 OS::Print("Replacing load v%"Pd" with v%"Pd"\n",
3125 defn->ssa_temp_index(), 3107 defn->ssa_temp_index(),
3126 replacement->ssa_temp_index()); 3108 replacement->ssa_temp_index());
3127 } 3109 }
3128 3110
3129 defn->ReplaceUsesWith(replacement); 3111 defn->ReplaceUsesWith(replacement);
3130 defn->UnuseAllInputs();
3131 instr_it.RemoveCurrentFromGraph(); 3112 instr_it.RemoveCurrentFromGraph();
3132 continue; 3113 continue;
3133 } else if (!kill->Contains(expr_id)) { 3114 } else if (!kill->Contains(expr_id)) {
3134 // This is an exposed load: it is the first representative of a 3115 // This is an exposed load: it is the first representative of a
3135 // given expression id and it is not killed on the path from 3116 // given expression id and it is not killed on the path from
3136 // the block entry. 3117 // the block entry.
3137 if (exposed_values == NULL) { 3118 if (exposed_values == NULL) {
3138 static const intptr_t kMaxExposedValuesInitialSize = 5; 3119 static const intptr_t kMaxExposedValuesInitialSize = 5;
3139 exposed_values = new ZoneGrowableArray<Definition*>( 3120 exposed_values = new ZoneGrowableArray<Definition*>(
3140 Utils::Minimum(kMaxExposedValuesInitialSize, max_expr_id_)); 3121 Utils::Minimum(kMaxExposedValuesInitialSize, max_expr_id_));
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
3328 if (load != replacement) { 3309 if (load != replacement) {
3329 EnsureSSATempIndex(graph_, load, replacement); 3310 EnsureSSATempIndex(graph_, load, replacement);
3330 3311
3331 if (FLAG_trace_optimization) { 3312 if (FLAG_trace_optimization) {
3332 OS::Print("Replacing load v%"Pd" with v%"Pd"\n", 3313 OS::Print("Replacing load v%"Pd" with v%"Pd"\n",
3333 load->ssa_temp_index(), 3314 load->ssa_temp_index(),
3334 replacement->ssa_temp_index()); 3315 replacement->ssa_temp_index());
3335 } 3316 }
3336 3317
3337 load->ReplaceUsesWith(replacement); 3318 load->ReplaceUsesWith(replacement);
3338 load->UnuseAllInputs();
3339 load->RemoveFromGraph(); 3319 load->RemoveFromGraph();
3340 load->SetReplacement(replacement); 3320 load->SetReplacement(replacement);
3341 } 3321 }
3342 } 3322 }
3343 } 3323 }
3344 } 3324 }
3345 3325
3346 // Check if the given phi take the same value on all code paths. 3326 // Check if the given phi take the same value on all code paths.
3347 // Eliminate it as redundant if this is the case. 3327 // Eliminate it as redundant if this is the case.
3348 // When analyzing phi operands assumes that only generated during 3328 // When analyzing phi operands assumes that only generated during
(...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after
4377 4357
4378 if (FLAG_trace_constant_propagation) { 4358 if (FLAG_trace_constant_propagation) {
4379 OS::Print("\n==== After constant propagation ====\n"); 4359 OS::Print("\n==== After constant propagation ====\n");
4380 FlowGraphPrinter printer(*graph_); 4360 FlowGraphPrinter printer(*graph_);
4381 printer.PrintBlocks(); 4361 printer.PrintBlocks();
4382 } 4362 }
4383 } 4363 }
4384 4364
4385 4365
4386 } // namespace dart 4366 } // 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