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