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 4515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5140 } | 5144 } |
5141 } | 5145 } |
5142 | 5146 |
5143 | 5147 |
5144 void FlowGraphOptimizer::InferIntRanges() { | 5148 void FlowGraphOptimizer::InferIntRanges() { |
5145 RangeAnalysis range_analysis(flow_graph_); | 5149 RangeAnalysis range_analysis(flow_graph_); |
5146 range_analysis.Analyze(); | 5150 range_analysis.Analyze(); |
5147 } | 5151 } |
5148 | 5152 |
5149 | 5153 |
5154 // Replaces Mint IL instructions with Uint32 IL instructions | |
5155 // when possible. Uses output of RangeAnalysis. | |
5156 class IntegerInstructionSelector : public ValueObject { | |
5157 public: | |
5158 explicit IntegerInstructionSelector(FlowGraph* flow_graph) | |
5159 : flow_graph_(flow_graph), | |
5160 isolate_(NULL), | |
5161 changed_(true) { | |
5162 ASSERT(flow_graph_ != NULL); | |
5163 isolate_ = flow_graph_->isolate(); | |
5164 ASSERT(isolate_ != NULL); | |
5165 selected_uint32_defs_ = | |
5166 new(I) BitVector(flow_graph_->current_ssa_temp_index()); | |
5167 } | |
5168 | |
5169 void Select(); | |
5170 | |
5171 private: | |
5172 bool IsPotentialUint32Definition(Definition* def); | |
5173 void FindPotentialUint32Definitions(); | |
5174 bool IsInitialUint32Candidate(Definition* def); | |
5175 void SelectInitialUint32Definitions(); | |
5176 bool IsUint32Candidate(Definition* def); | |
5177 void Propagate(); | |
5178 Definition* ConstructReplacementFor(Definition* def); | |
5179 void ReplaceInstructions(); | |
5180 | |
5181 Isolate* isolate() const { return isolate_; } | |
5182 | |
5183 GrowableArray<Definition*> potential_uint32_defs_; | |
5184 BitVector* selected_uint32_defs_; | |
5185 | |
5186 FlowGraph* flow_graph_; | |
5187 Isolate* isolate_; | |
5188 bool changed_; | |
5189 }; | |
5190 | |
5191 | |
5192 void IntegerInstructionSelector::Select() { | |
5193 if (FLAG_trace_integer_ir_selection) { | |
5194 OS::Print("---- starting integer ir selection -------\n"); | |
5195 } | |
5196 FindPotentialUint32Definitions(); | |
5197 SelectInitialUint32Definitions(); | |
5198 Propagate(); | |
5199 ReplaceInstructions(); | |
5200 if (FLAG_trace_integer_ir_selection) { | |
5201 OS::Print("---- after integer ir selection -------\n"); | |
5202 FlowGraphPrinter printer(*flow_graph_); | |
5203 printer.PrintBlocks(); | |
5204 } | |
5205 } | |
5206 | |
5207 | |
5208 bool IntegerInstructionSelector::IsPotentialUint32Definition(Definition* def) { | |
5209 if (!def->IsMintDefinition()) { | |
Florian Schneider
2014/07/08 12:24:29
Add a TODO to handle smi operations as well:
Bina
Cutch
2014/07/09 17:48:26
Done.
| |
5210 // Not a mint op. | |
5211 return false; | |
5212 } | |
5213 if (def->IsLoadField()) { | |
Florian Schneider
2014/07/08 12:24:29
Why is this needed? I'd rather enumerate the opera
Cutch
2014/07/09 17:48:25
Done.
| |
5214 // A load of a mint field. | |
5215 return false; | |
5216 } | |
5217 return true; | |
5218 } | |
5219 | |
5220 | |
5221 void IntegerInstructionSelector::FindPotentialUint32Definitions() { | |
5222 if (FLAG_trace_integer_ir_selection) { | |
5223 OS::Print("++++ Finding potential Uint32 definitions:\n"); | |
5224 } | |
5225 const GrowableArray<Definition*>& initial = | |
Florian Schneider
2014/07/08 12:24:28
Initial definitions are only Parameter or Constant
Cutch
2014/07/09 17:48:26
Done.
| |
5226 *flow_graph_->graph_entry()->initial_definitions(); | |
5227 for (intptr_t i = 0; i < initial.length(); ++i) { | |
5228 Definition* current = initial[i]; | |
5229 if (IsPotentialUint32Definition(current)) { | |
5230 if (FLAG_trace_integer_ir_selection) { | |
5231 OS::Print("Adding %s\n", current->ToCString()); | |
5232 } | |
5233 potential_uint32_defs_.Add(current); | |
5234 } | |
5235 } | |
5236 | |
5237 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); | |
5238 !block_it.Done(); | |
5239 block_it.Advance()) { | |
5240 BlockEntryInstr* block = block_it.Current(); | |
5241 | |
5242 if (block->IsCatchBlockEntry()) { | |
5243 const GrowableArray<Definition*>& initial = | |
5244 *block->AsCatchBlockEntry()->initial_definitions(); | |
5245 for (intptr_t i = 0; i < initial.length(); ++i) { | |
Florian Schneider
2014/07/08 12:24:28
No need to handle initial definitions here either.
Cutch
2014/07/09 17:48:26
Done.
| |
5246 Definition* current = initial[i]; | |
5247 if (IsPotentialUint32Definition(current)) { | |
5248 if (FLAG_trace_integer_ir_selection) { | |
5249 OS::Print("Adding %s\n", current->ToCString()); | |
5250 } | |
5251 potential_uint32_defs_.Add(current); | |
5252 } | |
5253 } | |
5254 } | |
5255 | |
5256 for (ForwardInstructionIterator instr_it(block); | |
5257 !instr_it.Done(); | |
5258 instr_it.Advance()) { | |
5259 Instruction* current = instr_it.Current(); | |
5260 Definition* defn = current->AsDefinition(); | |
5261 if ((defn != NULL) && (defn->ssa_temp_index() != -1)) { | |
5262 if (IsPotentialUint32Definition(defn)) { | |
5263 if (FLAG_trace_integer_ir_selection) { | |
5264 OS::Print("Adding %s\n", current->ToCString()); | |
5265 } | |
5266 potential_uint32_defs_.Add(defn); | |
5267 } | |
5268 } | |
5269 } | |
5270 } | |
5271 } | |
5272 | |
5273 | |
5274 // BinaryMintOp masks and stores into unsigned typed arrays that truncate the | |
5275 // value into a Uint32 range. | |
5276 bool IntegerInstructionSelector::IsInitialUint32Candidate(Definition* def) { | |
5277 if (def->IsBinaryMintOp()) { | |
5278 BinaryMintOpInstr* op = def->AsBinaryMintOp(); | |
5279 // Must be a mask operation. | |
5280 if (op->op_kind() != Token::kBIT_AND) { | |
5281 return false; | |
5282 } | |
5283 Range* range = op->range(); | |
5284 if ((range == NULL) || | |
5285 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) { | |
5286 return false; | |
5287 } | |
5288 return true; | |
5289 } | |
5290 // TODO(johnmccutchan): Add typed array stores. | |
5291 return false; | |
5292 } | |
5293 | |
5294 | |
5295 void IntegerInstructionSelector::SelectInitialUint32Definitions() { | |
5296 ASSERT(selected_uint32_defs_ != NULL); | |
5297 if (FLAG_trace_integer_ir_selection) { | |
5298 OS::Print("++++ Selecting Uint32 definitions:\n"); | |
5299 OS::Print("++++ Initial set:\n"); | |
5300 } | |
5301 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { | |
5302 Definition* defn = potential_uint32_defs_[i]; | |
5303 if (IsInitialUint32Candidate(defn)) { | |
5304 if (FLAG_trace_integer_ir_selection) { | |
5305 OS::Print("Adding %s\n", defn->ToCString()); | |
5306 } | |
5307 selected_uint32_defs_->Add(defn->ssa_temp_index()); | |
5308 } | |
5309 } | |
5310 } | |
5311 | |
5312 | |
5313 bool IntegerInstructionSelector::IsUint32Candidate(Definition* def) { | |
5314 ASSERT(def->IsMintDefinition()); | |
5315 if (def->IsBoxInteger()) { | |
5316 // If a BoxInteger's input is a candidate, the box is a candidate. | |
5317 BoxIntegerInstr* box = def->AsBoxInteger(); | |
5318 Definition* box_input = box->value()->definition(); | |
5319 return selected_uint32_defs_->Contains(box_input->ssa_temp_index()); | |
5320 } | |
5321 // A right shift with a range outside Uint32 cannot be converted because we | |
5322 // may need the high bits. | |
5323 if (def->IsShiftMintOp()) { | |
Vyacheslav Egorov (Google)
2014/07/08 12:39:31
should be checking the range of input for the high
Cutch
2014/07/09 17:48:26
Done.
| |
5324 ShiftMintOpInstr* op = def->AsShiftMintOp(); | |
5325 if (op->op_kind() == Token::kSHR) { | |
5326 Range* range = op->range(); | |
Florian Schneider
2014/07/08 12:24:29
I think you need to check the range of the input s
Cutch
2014/07/09 17:48:25
Done.
| |
5327 if ((range == NULL) || | |
5328 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) { | |
5329 return false; | |
5330 } | |
5331 } | |
5332 } | |
5333 if (!def->HasUses()) { | |
5334 // No uses, skip. | |
5335 return false; | |
5336 } | |
5337 // All input uses are candidates. | |
5338 for (Value* use = def->input_use_list(); use != NULL; use = use->next_use()) { | |
5339 Definition* defn = use->instruction()->AsDefinition(); | |
5340 if ((defn == NULL) || | |
5341 (defn->ssa_temp_index() == -1) || | |
5342 !selected_uint32_defs_->Contains(defn->ssa_temp_index())) { | |
5343 return false; | |
5344 } | |
5345 } | |
5346 | |
5347 // All environment uses are candidates. | |
Vyacheslav Egorov (Google)
2014/07/08 12:39:30
ShiftUint32OpInstr can deopt even though it is tru
Cutch
2014/07/09 17:48:26
We are conservatively replacing MintOps with Uint3
| |
5348 for (Value* use = def->env_use_list(); use != NULL; use = use->next_use()) { | |
5349 Definition* defn = use->instruction()->AsDefinition(); | |
5350 if ((defn == NULL) || | |
5351 (defn->ssa_temp_index() == -1) || | |
5352 !selected_uint32_defs_->Contains(defn->ssa_temp_index())) { | |
5353 return false; | |
5354 } | |
5355 } | |
5356 | |
5357 return true; | |
5358 } | |
5359 | |
5360 | |
5361 void IntegerInstructionSelector::Propagate() { | |
5362 ASSERT(selected_uint32_defs_ != NULL); | |
5363 ASSERT(changed_); | |
5364 intptr_t iteration = 0; | |
5365 while (changed_) { | |
5366 if (FLAG_trace_integer_ir_selection) { | |
5367 OS::Print("+++ Iteration: %" Pd "\n", iteration++); | |
5368 } | |
5369 changed_ = false; | |
5370 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { | |
5371 Definition* defn = potential_uint32_defs_[i]; | |
5372 if (selected_uint32_defs_->Contains(defn->ssa_temp_index())) { | |
5373 // Already marked as a candidate, skip. | |
5374 continue; | |
5375 } | |
5376 if (defn->IsConstant()) { | |
5377 // Skip constants. | |
5378 continue; | |
5379 } | |
5380 if (IsUint32Candidate(defn)) { | |
5381 if (FLAG_trace_integer_ir_selection) { | |
5382 OS::Print("Adding %s\n", defn->ToCString()); | |
5383 } | |
5384 // Found a new candidate. | |
5385 selected_uint32_defs_->Add(defn->ssa_temp_index()); | |
5386 // Haven't reached fixed point yet. | |
5387 changed_ = true; | |
5388 } | |
5389 } | |
5390 } | |
5391 if (FLAG_trace_integer_ir_selection) { | |
5392 OS::Print("Reached fixed point\n"); | |
5393 } | |
5394 } | |
5395 | |
5396 | |
5397 Definition* IntegerInstructionSelector::ConstructReplacementFor( | |
5398 Definition* def) { | |
5399 // Should only see mint definitions. | |
5400 ASSERT(def->IsMintDefinition()); | |
5401 // Should not see constant instructions. | |
5402 ASSERT(!def->IsConstant()); | |
5403 if (def->IsBinaryMintOp()) { | |
5404 BinaryMintOpInstr* op = def->AsBinaryMintOp(); | |
5405 Token::Kind op_kind = op->op_kind(); | |
5406 Value* left = op->left()->CopyWithType(); | |
5407 Value* right = op->right()->CopyWithType(); | |
5408 intptr_t deopt_id = op->DeoptimizationTarget(); | |
5409 return new(I) BinaryUint32OpInstr(op_kind, left, right, deopt_id); | |
5410 } else if (def->IsBoxInteger()) { | |
5411 BoxIntegerInstr* box = def->AsBoxInteger(); | |
5412 Value* value = box->value()->CopyWithType(); | |
5413 return new(I) BoxUint32Instr(value); | |
5414 } else if (def->IsUnboxInteger()) { | |
5415 UnboxIntegerInstr* unbox = def->AsUnboxInteger(); | |
5416 Value* value = unbox->value()->CopyWithType(); | |
5417 intptr_t deopt_id = unbox->deopt_id(); | |
5418 return new(I) UnboxUint32Instr(value, deopt_id); | |
5419 } else if (def->IsUnaryMintOp()) { | |
5420 UnaryMintOpInstr* op = def->AsUnaryMintOp(); | |
5421 Token::Kind op_kind = op->op_kind(); | |
5422 Value* value = op->value()->CopyWithType(); | |
5423 intptr_t deopt_id = op->DeoptimizationTarget(); | |
5424 return new(I) UnaryUint32OpInstr(op_kind, value, deopt_id); | |
5425 } else if (def->IsShiftMintOp()) { | |
5426 ShiftMintOpInstr* op = def->AsShiftMintOp(); | |
5427 Token::Kind op_kind = op->op_kind(); | |
5428 Value* left = op->left()->CopyWithType(); | |
5429 Value* right = op->right()->CopyWithType(); | |
5430 intptr_t deopt_id = op->DeoptimizationTarget(); | |
5431 return new(I) ShiftUint32OpInstr(op_kind, left, right, deopt_id); | |
5432 } | |
5433 printf("%s\n", def->ToCString()); | |
5434 UNREACHABLE(); | |
5435 return NULL; | |
5436 } | |
5437 | |
5438 | |
5439 void IntegerInstructionSelector::ReplaceInstructions() { | |
5440 if (FLAG_trace_integer_ir_selection) { | |
5441 OS::Print("++++ Replacing instructions:\n"); | |
5442 } | |
5443 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { | |
5444 Definition* defn = potential_uint32_defs_[i]; | |
5445 if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) { | |
5446 // Not a candidate. | |
5447 continue; | |
5448 } | |
5449 Definition* replacement = ConstructReplacementFor(defn); | |
5450 ASSERT(replacement != NULL); | |
5451 if (FLAG_trace_integer_ir_selection) { | |
5452 OS::Print("Replacing %s with %s\n", defn->ToCString(), | |
5453 replacement->ToCString()); | |
5454 } | |
5455 defn->ReplaceWith(replacement, NULL); | |
5456 ASSERT(flow_graph_->VerifyUseLists()); | |
5457 } | |
5458 } | |
5459 | |
5460 void FlowGraphOptimizer::SelectIntegerInstructions() { | |
5461 IntegerInstructionSelector iis(flow_graph_); | |
5462 iis.Select(); | |
5463 } | |
5464 | |
5465 | |
5150 void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) { | 5466 void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) { |
5151 // For every catch-block: Iterate over all call instructions inside the | 5467 // For every catch-block: Iterate over all call instructions inside the |
5152 // corresponding try-block and figure out for each environment value if it | 5468 // corresponding try-block and figure out for each environment value if it |
5153 // is the same constant at all calls. If yes, replace the initial definition | 5469 // is the same constant at all calls. If yes, replace the initial definition |
5154 // at the catch-entry with this constant. | 5470 // at the catch-entry with this constant. |
5155 const GrowableArray<CatchBlockEntryInstr*>& catch_entries = | 5471 const GrowableArray<CatchBlockEntryInstr*>& catch_entries = |
5156 flow_graph->graph_entry()->catch_entries(); | 5472 flow_graph->graph_entry()->catch_entries(); |
5157 intptr_t base = kFirstLocalSlotFromFp + flow_graph->num_non_copied_params(); | 5473 intptr_t base = kFirstLocalSlotFromFp + flow_graph->num_non_copied_params(); |
5158 for (intptr_t catch_idx = 0; | 5474 for (intptr_t catch_idx = 0; |
5159 catch_idx < catch_entries.length(); | 5475 catch_idx < catch_entries.length(); |
(...skipping 3745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8905 const Object& value = instr->value()->definition()->constant_value(); | 9221 const Object& value = instr->value()->definition()->constant_value(); |
8906 if (IsNonConstant(value)) { | 9222 if (IsNonConstant(value)) { |
8907 SetValue(instr, non_constant_); | 9223 SetValue(instr, non_constant_); |
8908 } else if (IsConstant(value)) { | 9224 } else if (IsConstant(value)) { |
8909 // TODO(kmillikin): Handle conversion. | 9225 // TODO(kmillikin): Handle conversion. |
8910 SetValue(instr, non_constant_); | 9226 SetValue(instr, non_constant_); |
8911 } | 9227 } |
8912 } | 9228 } |
8913 | 9229 |
8914 | 9230 |
9231 void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) { | |
9232 // TODO(kmillikin): Handle box operation. | |
9233 SetValue(instr, non_constant_); | |
9234 } | |
9235 | |
9236 | |
9237 void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) { | |
9238 // TODO(kmillikin): Handle unbox operation. | |
9239 SetValue(instr, non_constant_); | |
9240 } | |
9241 | |
9242 | |
9243 void ConstantPropagator::VisitUnboxedIntConverter( | |
9244 UnboxedIntConverterInstr* instr) { | |
9245 SetValue(instr, non_constant_); | |
9246 } | |
9247 | |
9248 | |
9249 void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) { | |
9250 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | |
Vyacheslav Egorov (Google)
2014/07/08 12:39:31
Why there is no truncation here?
Cutch
2014/07/09 17:48:25
Are you saying the constant resulting from HandleB
Vyacheslav Egorov (Google)
2014/07/11 16:00:08
Yes, to uint32 range, to ensure that constant_valu
Cutch
2014/07/11 22:04:13
Done.
| |
9251 } | |
9252 | |
9253 | |
9254 void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) { | |
9255 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | |
9256 } | |
9257 | |
9258 | |
9259 void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) { | |
9260 // TODO(kmillikin): Handle unary operations. | |
9261 SetValue(instr, non_constant_); | |
9262 } | |
9263 | |
9264 | |
8915 void ConstantPropagator::Analyze() { | 9265 void ConstantPropagator::Analyze() { |
8916 GraphEntryInstr* entry = graph_->graph_entry(); | 9266 GraphEntryInstr* entry = graph_->graph_entry(); |
8917 reachable_->Add(entry->preorder_number()); | 9267 reachable_->Add(entry->preorder_number()); |
8918 block_worklist_.Add(entry); | 9268 block_worklist_.Add(entry); |
8919 | 9269 |
8920 while (true) { | 9270 while (true) { |
8921 if (block_worklist_.is_empty()) { | 9271 if (block_worklist_.is_empty()) { |
8922 if (definition_worklist_.is_empty()) break; | 9272 if (definition_worklist_.is_empty()) break; |
8923 Definition* definition = definition_worklist_.RemoveLast(); | 9273 Definition* definition = definition_worklist_.RemoveLast(); |
8924 definition_marks_->Remove(definition->ssa_temp_index()); | 9274 definition_marks_->Remove(definition->ssa_temp_index()); |
(...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9818 } | 10168 } |
9819 | 10169 |
9820 // Insert materializations at environment uses. | 10170 // Insert materializations at environment uses. |
9821 for (intptr_t i = 0; i < exits.length(); i++) { | 10171 for (intptr_t i = 0; i < exits.length(); i++) { |
9822 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 10172 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
9823 } | 10173 } |
9824 } | 10174 } |
9825 | 10175 |
9826 | 10176 |
9827 } // namespace dart | 10177 } // namespace dart |
OLD | NEW |