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 26 matching lines...) Expand all Loading... |
37 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); | 37 DEFINE_FLAG(bool, remove_redundant_phis, true, "Remove redundant phis."); |
38 DEFINE_FLAG(bool, trace_constant_propagation, false, | 38 DEFINE_FLAG(bool, trace_constant_propagation, false, |
39 "Print constant propagation and useless code elimination."); | 39 "Print constant propagation and useless code elimination."); |
40 DEFINE_FLAG(bool, trace_load_optimization, false, | 40 DEFINE_FLAG(bool, trace_load_optimization, false, |
41 "Print live sets for load optimization pass."); | 41 "Print live sets for load optimization pass."); |
42 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); | 42 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); |
43 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); | 43 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); |
44 DEFINE_FLAG(bool, truncating_left_shift, true, | 44 DEFINE_FLAG(bool, truncating_left_shift, true, |
45 "Optimize left shift to truncate if possible"); | 45 "Optimize left shift to truncate if possible"); |
46 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); | 46 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); |
| 47 DEFINE_FLAG(bool, trace_integer_ir_selection, false, |
| 48 "Print integer IR selection optimization pass."); |
47 DECLARE_FLAG(bool, enable_type_checks); | 49 DECLARE_FLAG(bool, enable_type_checks); |
48 DECLARE_FLAG(bool, source_lines); | 50 DECLARE_FLAG(bool, source_lines); |
49 DECLARE_FLAG(bool, trace_type_check_elimination); | 51 DECLARE_FLAG(bool, trace_type_check_elimination); |
50 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | 52 DECLARE_FLAG(bool, warn_on_javascript_compatibility); |
51 | 53 |
52 // Quick access to the locally defined isolate() method. | 54 // Quick access to the locally defined isolate() method. |
53 #define I (isolate()) | 55 #define I (isolate()) |
54 | 56 |
55 static bool ShouldInlineSimd() { | 57 static bool ShouldInlineSimd() { |
56 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 58 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 deopt_target = insert_before = use->instruction(); | 603 deopt_target = insert_before = use->instruction(); |
602 } | 604 } |
603 | 605 |
604 Definition* converted = NULL; | 606 Definition* converted = NULL; |
605 if ((from == kTagged) && (to == kUnboxedMint)) { | 607 if ((from == kTagged) && (to == kUnboxedMint)) { |
606 ASSERT((deopt_target != NULL) || | 608 ASSERT((deopt_target != NULL) || |
607 (use->Type()->ToCid() == kUnboxedMint)); | 609 (use->Type()->ToCid() == kUnboxedMint)); |
608 const intptr_t deopt_id = (deopt_target != NULL) ? | 610 const intptr_t deopt_id = (deopt_target != NULL) ? |
609 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 611 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
610 converted = new(I) UnboxIntegerInstr(use->CopyWithType(), deopt_id); | 612 converted = new(I) UnboxIntegerInstr(use->CopyWithType(), deopt_id); |
611 | |
612 } else if ((from == kUnboxedMint) && (to == kTagged)) { | 613 } else if ((from == kUnboxedMint) && (to == kTagged)) { |
613 converted = new(I) BoxIntegerInstr(use->CopyWithType()); | 614 converted = new(I) BoxIntegerInstr(use->CopyWithType()); |
614 | 615 } else if ((from == kUnboxedMint) && (to == kUnboxedUint32)) { |
| 616 converted = new(I) UnboxedIntConverterInstr(from, to, use->CopyWithType()); |
| 617 } else if ((from == kUnboxedUint32) && (to == kUnboxedMint)) { |
| 618 converted = new(I) UnboxedIntConverterInstr(from, to, use->CopyWithType()); |
615 } else if (from == kUnboxedMint && to == kUnboxedDouble) { | 619 } else if (from == kUnboxedMint && to == kUnboxedDouble) { |
616 ASSERT(CanUnboxDouble()); | 620 ASSERT(CanUnboxDouble()); |
617 // Convert by boxing/unboxing. | 621 // Convert by boxing/unboxing. |
618 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. | 622 // TODO(fschneider): Implement direct unboxed mint-to-double conversion. |
619 BoxIntegerInstr* boxed = | 623 BoxIntegerInstr* boxed = |
620 new(I) BoxIntegerInstr(use->CopyWithType()); | 624 new(I) BoxIntegerInstr(use->CopyWithType()); |
621 use->BindTo(boxed); | 625 use->BindTo(boxed); |
622 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); | 626 InsertBefore(insert_before, boxed, NULL, FlowGraph::kValue); |
623 | 627 |
624 const intptr_t deopt_id = (deopt_target != NULL) ? | 628 const intptr_t deopt_id = (deopt_target != NULL) ? |
(...skipping 3883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4508 } | 4512 } |
4509 | 4513 |
4510 // Discard the environment from the original instruction because the store | 4514 // Discard the environment from the original instruction because the store |
4511 // can't deoptimize. | 4515 // can't deoptimize. |
4512 instr->RemoveEnvironment(); | 4516 instr->RemoveEnvironment(); |
4513 ReplaceCall(instr, store); | 4517 ReplaceCall(instr, store); |
4514 return true; | 4518 return true; |
4515 } | 4519 } |
4516 | 4520 |
4517 | 4521 |
4518 // Range analysis for smi values. | 4522 // Replaces Mint IL instructions with Uint32 IL instructions |
| 4523 // when possible. Uses output of RangeAnalysis. |
| 4524 class IntegerInstructionSelector : public ValueObject { |
| 4525 public: |
| 4526 explicit IntegerInstructionSelector(FlowGraph* flow_graph) |
| 4527 : flow_graph_(flow_graph), |
| 4528 isolate_(NULL) { |
| 4529 ASSERT(flow_graph_ != NULL); |
| 4530 isolate_ = flow_graph_->isolate(); |
| 4531 ASSERT(isolate_ != NULL); |
| 4532 selected_uint32_defs_ = |
| 4533 new(I) BitVector(flow_graph_->current_ssa_temp_index()); |
| 4534 } |
| 4535 |
| 4536 void Select(); |
| 4537 |
| 4538 private: |
| 4539 bool IsPotentialUint32Definition(Definition* def); |
| 4540 void FindPotentialUint32Definitions(); |
| 4541 bool IsUint32NarrowingDefinition(Definition* def); |
| 4542 void FindUint32NarrowingDefinitions(); |
| 4543 bool AllUsesAreUint32Narrowing(Value* list_head); |
| 4544 bool CanBecomeUint32(Definition* def); |
| 4545 void Propagate(); |
| 4546 Definition* ConstructReplacementFor(Definition* def); |
| 4547 void ReplaceInstructions(); |
| 4548 |
| 4549 Isolate* isolate() const { return isolate_; } |
| 4550 |
| 4551 GrowableArray<Definition*> potential_uint32_defs_; |
| 4552 BitVector* selected_uint32_defs_; |
| 4553 |
| 4554 FlowGraph* flow_graph_; |
| 4555 Isolate* isolate_; |
| 4556 }; |
| 4557 |
| 4558 |
| 4559 void IntegerInstructionSelector::Select() { |
| 4560 if (FLAG_trace_integer_ir_selection) { |
| 4561 OS::Print("---- starting integer ir selection -------\n"); |
| 4562 } |
| 4563 FindPotentialUint32Definitions(); |
| 4564 FindUint32NarrowingDefinitions(); |
| 4565 Propagate(); |
| 4566 ReplaceInstructions(); |
| 4567 if (FLAG_trace_integer_ir_selection) { |
| 4568 OS::Print("---- after integer ir selection -------\n"); |
| 4569 FlowGraphPrinter printer(*flow_graph_); |
| 4570 printer.PrintBlocks(); |
| 4571 } |
| 4572 } |
| 4573 |
| 4574 |
| 4575 bool IntegerInstructionSelector::IsPotentialUint32Definition(Definition* def) { |
| 4576 // TODO(johnmccutchan): Consider Smi operations, to avoid unnecessary tagging |
| 4577 // & untagged of intermediate results. |
| 4578 // TODO(johnmccutchan): Consider phis. |
| 4579 return def->IsBoxInteger() || // BoxMint. |
| 4580 def->IsUnboxInteger() || // UnboxMint. |
| 4581 def->IsBinaryMintOp() || |
| 4582 def->IsShiftMintOp() || |
| 4583 def->IsUnaryMintOp(); |
| 4584 } |
| 4585 |
| 4586 |
| 4587 void IntegerInstructionSelector::FindPotentialUint32Definitions() { |
| 4588 if (FLAG_trace_integer_ir_selection) { |
| 4589 OS::Print("++++ Finding potential Uint32 definitions:\n"); |
| 4590 } |
| 4591 |
| 4592 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
| 4593 !block_it.Done(); |
| 4594 block_it.Advance()) { |
| 4595 BlockEntryInstr* block = block_it.Current(); |
| 4596 |
| 4597 for (ForwardInstructionIterator instr_it(block); |
| 4598 !instr_it.Done(); |
| 4599 instr_it.Advance()) { |
| 4600 Instruction* current = instr_it.Current(); |
| 4601 Definition* defn = current->AsDefinition(); |
| 4602 if ((defn != NULL) && (defn->ssa_temp_index() != -1)) { |
| 4603 if (IsPotentialUint32Definition(defn)) { |
| 4604 if (FLAG_trace_integer_ir_selection) { |
| 4605 OS::Print("Adding %s\n", current->ToCString()); |
| 4606 } |
| 4607 potential_uint32_defs_.Add(defn); |
| 4608 } |
| 4609 } |
| 4610 } |
| 4611 } |
| 4612 } |
| 4613 |
| 4614 |
| 4615 // BinaryMintOp masks and stores into unsigned typed arrays that truncate the |
| 4616 // value into a Uint32 range. |
| 4617 bool IntegerInstructionSelector::IsUint32NarrowingDefinition(Definition* def) { |
| 4618 if (def->IsBinaryMintOp()) { |
| 4619 BinaryMintOpInstr* op = def->AsBinaryMintOp(); |
| 4620 // Must be a mask operation. |
| 4621 if (op->op_kind() != Token::kBIT_AND) { |
| 4622 return false; |
| 4623 } |
| 4624 Range* range = op->range(); |
| 4625 if ((range == NULL) || |
| 4626 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) { |
| 4627 return false; |
| 4628 } |
| 4629 return true; |
| 4630 } |
| 4631 // TODO(johnmccutchan): Add typed array stores. |
| 4632 return false; |
| 4633 } |
| 4634 |
| 4635 |
| 4636 void IntegerInstructionSelector::FindUint32NarrowingDefinitions() { |
| 4637 ASSERT(selected_uint32_defs_ != NULL); |
| 4638 if (FLAG_trace_integer_ir_selection) { |
| 4639 OS::Print("++++ Selecting Uint32 definitions:\n"); |
| 4640 OS::Print("++++ Initial set:\n"); |
| 4641 } |
| 4642 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { |
| 4643 Definition* defn = potential_uint32_defs_[i]; |
| 4644 if (IsUint32NarrowingDefinition(defn)) { |
| 4645 if (FLAG_trace_integer_ir_selection) { |
| 4646 OS::Print("Adding %s\n", defn->ToCString()); |
| 4647 } |
| 4648 selected_uint32_defs_->Add(defn->ssa_temp_index()); |
| 4649 } |
| 4650 } |
| 4651 } |
| 4652 |
| 4653 |
| 4654 bool IntegerInstructionSelector::AllUsesAreUint32Narrowing(Value* list_head) { |
| 4655 for (Value::Iterator it(list_head); |
| 4656 !it.Done(); |
| 4657 it.Advance()) { |
| 4658 Value* use = it.Current(); |
| 4659 Definition* defn = use->instruction()->AsDefinition(); |
| 4660 if ((defn == NULL) || |
| 4661 (defn->ssa_temp_index() == -1) || |
| 4662 !selected_uint32_defs_->Contains(defn->ssa_temp_index())) { |
| 4663 return false; |
| 4664 } |
| 4665 } |
| 4666 return true; |
| 4667 } |
| 4668 |
| 4669 |
| 4670 bool IntegerInstructionSelector::CanBecomeUint32(Definition* def) { |
| 4671 ASSERT(IsPotentialUint32Definition(def)); |
| 4672 if (def->IsBoxInteger()) { |
| 4673 // If a BoxInteger's input is a candidate, the box is a candidate. |
| 4674 BoxIntegerInstr* box = def->AsBoxInteger(); |
| 4675 Definition* box_input = box->value()->definition(); |
| 4676 return selected_uint32_defs_->Contains(box_input->ssa_temp_index()); |
| 4677 } |
| 4678 // A right shift with an input outside of Uint32 range cannot be converted |
| 4679 // because we need the high bits. |
| 4680 if (def->IsShiftMintOp()) { |
| 4681 ShiftMintOpInstr* op = def->AsShiftMintOp(); |
| 4682 if (op->op_kind() == Token::kSHR) { |
| 4683 Definition* shift_input = op->left()->definition(); |
| 4684 ASSERT(shift_input != NULL); |
| 4685 Range* range = shift_input->range(); |
| 4686 if ((range == NULL) || |
| 4687 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) { |
| 4688 return false; |
| 4689 } |
| 4690 } |
| 4691 } |
| 4692 if (!def->HasUses()) { |
| 4693 // No uses, skip. |
| 4694 return false; |
| 4695 } |
| 4696 return AllUsesAreUint32Narrowing(def->input_use_list()) && |
| 4697 AllUsesAreUint32Narrowing(def->env_use_list()); |
| 4698 } |
| 4699 |
| 4700 |
| 4701 void IntegerInstructionSelector::Propagate() { |
| 4702 ASSERT(selected_uint32_defs_ != NULL); |
| 4703 bool changed = true; |
| 4704 intptr_t iteration = 0; |
| 4705 while (changed) { |
| 4706 if (FLAG_trace_integer_ir_selection) { |
| 4707 OS::Print("+++ Iteration: %" Pd "\n", iteration++); |
| 4708 } |
| 4709 changed = false; |
| 4710 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { |
| 4711 Definition* defn = potential_uint32_defs_[i]; |
| 4712 if (selected_uint32_defs_->Contains(defn->ssa_temp_index())) { |
| 4713 // Already marked as a candidate, skip. |
| 4714 continue; |
| 4715 } |
| 4716 if (defn->IsConstant()) { |
| 4717 // Skip constants. |
| 4718 continue; |
| 4719 } |
| 4720 if (CanBecomeUint32(defn)) { |
| 4721 if (FLAG_trace_integer_ir_selection) { |
| 4722 OS::Print("Adding %s\n", defn->ToCString()); |
| 4723 } |
| 4724 // Found a new candidate. |
| 4725 selected_uint32_defs_->Add(defn->ssa_temp_index()); |
| 4726 // Haven't reached fixed point yet. |
| 4727 changed = true; |
| 4728 } |
| 4729 } |
| 4730 } |
| 4731 if (FLAG_trace_integer_ir_selection) { |
| 4732 OS::Print("Reached fixed point\n"); |
| 4733 } |
| 4734 } |
| 4735 |
| 4736 |
| 4737 Definition* IntegerInstructionSelector::ConstructReplacementFor( |
| 4738 Definition* def) { |
| 4739 // Should only see mint definitions. |
| 4740 ASSERT(IsPotentialUint32Definition(def)); |
| 4741 // Should not see constant instructions. |
| 4742 ASSERT(!def->IsConstant()); |
| 4743 if (def->IsBinaryMintOp()) { |
| 4744 BinaryMintOpInstr* op = def->AsBinaryMintOp(); |
| 4745 Token::Kind op_kind = op->op_kind(); |
| 4746 Value* left = op->left()->CopyWithType(); |
| 4747 Value* right = op->right()->CopyWithType(); |
| 4748 intptr_t deopt_id = op->DeoptimizationTarget(); |
| 4749 return new(I) BinaryUint32OpInstr(op_kind, left, right, deopt_id); |
| 4750 } else if (def->IsBoxInteger()) { |
| 4751 BoxIntegerInstr* box = def->AsBoxInteger(); |
| 4752 Value* value = box->value()->CopyWithType(); |
| 4753 return new(I) BoxUint32Instr(value); |
| 4754 } else if (def->IsUnboxInteger()) { |
| 4755 UnboxIntegerInstr* unbox = def->AsUnboxInteger(); |
| 4756 Value* value = unbox->value()->CopyWithType(); |
| 4757 intptr_t deopt_id = unbox->deopt_id(); |
| 4758 return new(I) UnboxUint32Instr(value, deopt_id); |
| 4759 } else if (def->IsUnaryMintOp()) { |
| 4760 UnaryMintOpInstr* op = def->AsUnaryMintOp(); |
| 4761 Token::Kind op_kind = op->op_kind(); |
| 4762 Value* value = op->value()->CopyWithType(); |
| 4763 intptr_t deopt_id = op->DeoptimizationTarget(); |
| 4764 return new(I) UnaryUint32OpInstr(op_kind, value, deopt_id); |
| 4765 } else if (def->IsShiftMintOp()) { |
| 4766 ShiftMintOpInstr* op = def->AsShiftMintOp(); |
| 4767 Token::Kind op_kind = op->op_kind(); |
| 4768 Value* left = op->left()->CopyWithType(); |
| 4769 Value* right = op->right()->CopyWithType(); |
| 4770 intptr_t deopt_id = op->DeoptimizationTarget(); |
| 4771 return new(I) ShiftUint32OpInstr(op_kind, left, right, deopt_id); |
| 4772 } |
| 4773 UNREACHABLE(); |
| 4774 return NULL; |
| 4775 } |
| 4776 |
| 4777 |
| 4778 void IntegerInstructionSelector::ReplaceInstructions() { |
| 4779 if (FLAG_trace_integer_ir_selection) { |
| 4780 OS::Print("++++ Replacing instructions:\n"); |
| 4781 } |
| 4782 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { |
| 4783 Definition* defn = potential_uint32_defs_[i]; |
| 4784 if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) { |
| 4785 // Not a candidate. |
| 4786 continue; |
| 4787 } |
| 4788 Definition* replacement = ConstructReplacementFor(defn); |
| 4789 ASSERT(replacement != NULL); |
| 4790 if (FLAG_trace_integer_ir_selection) { |
| 4791 OS::Print("Replacing %s with %s\n", defn->ToCString(), |
| 4792 replacement->ToCString()); |
| 4793 } |
| 4794 defn->ReplaceWith(replacement, NULL); |
| 4795 ASSERT(flow_graph_->VerifyUseLists()); |
| 4796 } |
| 4797 } |
| 4798 |
| 4799 void FlowGraphOptimizer::SelectIntegerInstructions() { |
| 4800 IntegerInstructionSelector iis(flow_graph_); |
| 4801 iis.Select(); |
| 4802 } |
| 4803 |
| 4804 |
| 4805 // Range analysis for integer values. |
4519 class RangeAnalysis : public ValueObject { | 4806 class RangeAnalysis : public ValueObject { |
4520 public: | 4807 public: |
4521 explicit RangeAnalysis(FlowGraph* flow_graph) | 4808 explicit RangeAnalysis(FlowGraph* flow_graph) |
4522 : flow_graph_(flow_graph), | 4809 : flow_graph_(flow_graph), |
4523 marked_defns_(NULL) { } | 4810 marked_defns_(NULL) { } |
4524 | 4811 |
4525 // Infer ranges for all values and remove overflow checks from binary smi | 4812 // Infer ranges for all values and remove overflow checks from binary smi |
4526 // operations when proven redundant. | 4813 // operations when proven redundant. |
4527 void Analyze(); | 4814 void Analyze(); |
4528 | 4815 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4617 BitVector* marked_defns_; | 4904 BitVector* marked_defns_; |
4618 | 4905 |
4619 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis); | 4906 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis); |
4620 }; | 4907 }; |
4621 | 4908 |
4622 | 4909 |
4623 void RangeAnalysis::Analyze() { | 4910 void RangeAnalysis::Analyze() { |
4624 CollectValues(); | 4911 CollectValues(); |
4625 InsertConstraints(); | 4912 InsertConstraints(); |
4626 InferRanges(); | 4913 InferRanges(); |
| 4914 IntegerInstructionSelector iis(flow_graph_); |
| 4915 iis.Select(); |
4627 RemoveConstraints(); | 4916 RemoveConstraints(); |
4628 } | 4917 } |
4629 | 4918 |
4630 | 4919 |
4631 void RangeAnalysis::CollectValues() { | 4920 void RangeAnalysis::CollectValues() { |
4632 const GrowableArray<Definition*>& initial = | 4921 const GrowableArray<Definition*>& initial = |
4633 *flow_graph_->graph_entry()->initial_definitions(); | 4922 *flow_graph_->graph_entry()->initial_definitions(); |
4634 for (intptr_t i = 0; i < initial.length(); ++i) { | 4923 for (intptr_t i = 0; i < initial.length(); ++i) { |
4635 Definition* current = initial[i]; | 4924 Definition* current = initial[i]; |
4636 if (current->Type()->ToCid() == kSmiCid) { | 4925 if (current->Type()->ToCid() == kSmiCid) { |
(...skipping 3841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8478 UNREACHABLE(); | 8767 UNREACHABLE(); |
8479 } | 8768 } |
8480 } else { | 8769 } else { |
8481 // TODO(kmillikin): support other types. | 8770 // TODO(kmillikin): support other types. |
8482 SetValue(instr, non_constant_); | 8771 SetValue(instr, non_constant_); |
8483 } | 8772 } |
8484 } | 8773 } |
8485 } | 8774 } |
8486 | 8775 |
8487 | 8776 |
| 8777 void ConstantPropagator::TruncateInteger(Definition* defn, int64_t mask) { |
| 8778 const Object& value = defn->constant_value(); |
| 8779 if (IsNonConstant(value)) { |
| 8780 return; |
| 8781 } |
| 8782 ASSERT(IsConstant(value)); |
| 8783 if (!value.IsInteger()) { |
| 8784 return; |
| 8785 } |
| 8786 const Integer& value_int = Integer::Cast(value); |
| 8787 int64_t truncated = value_int.AsInt64Value() & mask; |
| 8788 Instance& result = Integer::ZoneHandle(I, Integer::New(truncated)); |
| 8789 result = result.CheckAndCanonicalize(NULL); |
| 8790 ASSERT(!result.IsNull()); |
| 8791 SetValue(defn, result); |
| 8792 } |
| 8793 |
| 8794 |
8488 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { | 8795 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) { |
8489 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | 8796 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); |
8490 } | 8797 } |
8491 | 8798 |
8492 | 8799 |
8493 void ConstantPropagator::VisitBoxInteger(BoxIntegerInstr* instr) { | 8800 void ConstantPropagator::VisitBoxInteger(BoxIntegerInstr* instr) { |
8494 // TODO(kmillikin): Handle box operation. | 8801 // TODO(kmillikin): Handle box operation. |
8495 SetValue(instr, non_constant_); | 8802 SetValue(instr, non_constant_); |
8496 } | 8803 } |
8497 | 8804 |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8910 const Object& value = instr->value()->definition()->constant_value(); | 9217 const Object& value = instr->value()->definition()->constant_value(); |
8911 if (IsNonConstant(value)) { | 9218 if (IsNonConstant(value)) { |
8912 SetValue(instr, non_constant_); | 9219 SetValue(instr, non_constant_); |
8913 } else if (IsConstant(value)) { | 9220 } else if (IsConstant(value)) { |
8914 // TODO(kmillikin): Handle conversion. | 9221 // TODO(kmillikin): Handle conversion. |
8915 SetValue(instr, non_constant_); | 9222 SetValue(instr, non_constant_); |
8916 } | 9223 } |
8917 } | 9224 } |
8918 | 9225 |
8919 | 9226 |
| 9227 void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) { |
| 9228 // TODO(kmillikin): Handle box operation. |
| 9229 SetValue(instr, non_constant_); |
| 9230 } |
| 9231 |
| 9232 |
| 9233 void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) { |
| 9234 // TODO(kmillikin): Handle unbox operation. |
| 9235 SetValue(instr, non_constant_); |
| 9236 } |
| 9237 |
| 9238 |
| 9239 void ConstantPropagator::VisitUnboxedIntConverter( |
| 9240 UnboxedIntConverterInstr* instr) { |
| 9241 SetValue(instr, non_constant_); |
| 9242 } |
| 9243 |
| 9244 |
| 9245 void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) { |
| 9246 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); |
| 9247 TruncateInteger(instr, static_cast<int64_t>(0xFFFFFFFF)); |
| 9248 } |
| 9249 |
| 9250 |
| 9251 void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) { |
| 9252 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); |
| 9253 TruncateInteger(instr, static_cast<int64_t>(0xFFFFFFFF)); |
| 9254 } |
| 9255 |
| 9256 |
| 9257 void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) { |
| 9258 // TODO(kmillikin): Handle unary operations. |
| 9259 SetValue(instr, non_constant_); |
| 9260 } |
| 9261 |
| 9262 |
8920 void ConstantPropagator::Analyze() { | 9263 void ConstantPropagator::Analyze() { |
8921 GraphEntryInstr* entry = graph_->graph_entry(); | 9264 GraphEntryInstr* entry = graph_->graph_entry(); |
8922 reachable_->Add(entry->preorder_number()); | 9265 reachable_->Add(entry->preorder_number()); |
8923 block_worklist_.Add(entry); | 9266 block_worklist_.Add(entry); |
8924 | 9267 |
8925 while (true) { | 9268 while (true) { |
8926 if (block_worklist_.is_empty()) { | 9269 if (block_worklist_.is_empty()) { |
8927 if (definition_worklist_.is_empty()) break; | 9270 if (definition_worklist_.is_empty()) break; |
8928 Definition* definition = definition_worklist_.RemoveLast(); | 9271 Definition* definition = definition_worklist_.RemoveLast(); |
8929 definition_marks_->Remove(definition->ssa_temp_index()); | 9272 definition_marks_->Remove(definition->ssa_temp_index()); |
(...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9783 } | 10126 } |
9784 | 10127 |
9785 // Insert materializations at environment uses. | 10128 // Insert materializations at environment uses. |
9786 for (intptr_t i = 0; i < exits.length(); i++) { | 10129 for (intptr_t i = 0; i < exits.length(); i++) { |
9787 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 10130 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
9788 } | 10131 } |
9789 } | 10132 } |
9790 | 10133 |
9791 | 10134 |
9792 } // namespace dart | 10135 } // namespace dart |
OLD | NEW |