Chromium Code Reviews| 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 Iterate(); | |
| 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(); | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
"InitialDefinition" is a confusing name. I would c
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
"InitialDefinition" is a confusing name. I would c
| |
| 5198 Iterate(); | |
| 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()) { | |
| 5210 // Not a mint op. | |
| 5211 return false; | |
| 5212 } | |
| 5213 if (def->IsLoadField()) { | |
| 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 = | |
| 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 | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
remove empty line
Cutch
2014/07/07 22:34:28
Done.
| |
| 5243 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) { | |
| 5244 const GrowableArray<Definition*>& initial = block->IsGraphEntry() | |
| 5245 ? *block->AsGraphEntry()->initial_definitions() | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
Did not we already iterate over graph entry above?
Cutch
2014/07/07 22:34:28
Done.
| |
| 5246 : *block->AsCatchBlockEntry()->initial_definitions(); | |
| 5247 for (intptr_t i = 0; i < initial.length(); ++i) { | |
| 5248 Definition* current = initial[i]; | |
| 5249 if (IsPotentialUint32Definition(current)) { | |
| 5250 if (FLAG_trace_integer_ir_selection) { | |
| 5251 OS::Print("Adding %s\n", current->ToCString()); | |
| 5252 } | |
| 5253 potential_uint32_defs_.Add(current); | |
| 5254 } | |
| 5255 } | |
| 5256 } | |
| 5257 | |
| 5258 for (ForwardInstructionIterator instr_it(block); | |
| 5259 !instr_it.Done(); | |
| 5260 instr_it.Advance()) { | |
| 5261 Instruction* current = instr_it.Current(); | |
| 5262 Definition* defn = current->AsDefinition(); | |
| 5263 if ((defn != NULL) && (defn->ssa_temp_index() != -1)) { | |
| 5264 if (IsPotentialUint32Definition(defn)) { | |
| 5265 if (FLAG_trace_integer_ir_selection) { | |
| 5266 OS::Print("Adding %s\n", current->ToCString()); | |
| 5267 } | |
| 5268 potential_uint32_defs_.Add(defn); | |
| 5269 } | |
| 5270 } | |
| 5271 } | |
| 5272 } | |
| 5273 } | |
| 5274 | |
| 5275 | |
| 5276 // BinaryMintOp masks and stores into unsigned typed arrays that truncate the | |
| 5277 // value into a Uint32 range. | |
| 5278 bool IntegerInstructionSelector::IsInitialUint32Candidate(Definition* def) { | |
| 5279 if (def->IsBinaryMintOp()) { | |
| 5280 BinaryMintOpInstr* op = def->AsBinaryMintOp(); | |
| 5281 // Must be a mask operation. | |
| 5282 if (op->op_kind() != Token::kBIT_AND) { | |
| 5283 return false; | |
| 5284 } | |
| 5285 Range* range = op->range(); | |
| 5286 if ((range == NULL) || | |
| 5287 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) { | |
| 5288 return false; | |
| 5289 } | |
| 5290 return true; | |
| 5291 } | |
| 5292 // TODO(johnmccutchan): Add typed array stores. | |
| 5293 return false; | |
| 5294 } | |
| 5295 | |
| 5296 | |
| 5297 void IntegerInstructionSelector::SelectInitialUint32Definitions() { | |
| 5298 ASSERT(selected_uint32_defs_ != NULL); | |
| 5299 if (FLAG_trace_integer_ir_selection) { | |
| 5300 OS::Print("++++ Selecting Uint32 definitions:\n"); | |
| 5301 OS::Print("++++ Initial set:\n"); | |
| 5302 } | |
| 5303 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { | |
| 5304 Definition* defn = potential_uint32_defs_[i]; | |
| 5305 if (IsInitialUint32Candidate(defn)) { | |
| 5306 if (FLAG_trace_integer_ir_selection) { | |
| 5307 OS::Print("Adding %s\n", defn->ToCString()); | |
| 5308 } | |
| 5309 selected_uint32_defs_->Add(defn->ssa_temp_index()); | |
| 5310 } | |
| 5311 } | |
| 5312 } | |
| 5313 | |
| 5314 | |
| 5315 bool IntegerInstructionSelector::IsUint32Candidate(Definition* def) { | |
| 5316 ASSERT(def->IsMintDefinition()); | |
| 5317 if (def->IsBoxInteger()) { | |
| 5318 // If a BoxInteger's input is a candidate, the box is a candidate. | |
| 5319 BoxIntegerInstr* box = def->AsBoxInteger(); | |
| 5320 Definition* box_input = box->value()->definition(); | |
| 5321 return selected_uint32_defs_->Contains(box_input->ssa_temp_index()); | |
| 5322 } | |
| 5323 // A right shift with a range outside Uint32 cannot be converted because we | |
| 5324 // may need the high bits. | |
| 5325 if (def->IsShiftMintOp()) { | |
| 5326 ShiftMintOpInstr* op = def->AsShiftMintOp(); | |
| 5327 if (op->op_kind() == Token::kSHR) { | |
| 5328 Range* range = op->range(); | |
| 5329 if ((range == NULL) || | |
| 5330 !range->IsWithin(0, static_cast<int64_t>(kMaxUint32))) { | |
| 5331 return false; | |
| 5332 } | |
| 5333 } | |
| 5334 } | |
| 5335 if (!def->HasUses()) { | |
| 5336 // No uses, skip. | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
[sidenote: we should DCE those instructions :)]
| |
| 5337 return false; | |
| 5338 } | |
| 5339 // All uses are candidates. | |
| 5340 Value* use = def->input_use_list(); | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
What about environment uses? It is not safe to ign
| |
| 5341 bool only_candidate_uses = true; | |
| 5342 while ((use != NULL) && only_candidate_uses) { | |
| 5343 Instruction* instr = use->instruction(); | |
| 5344 if (!instr->IsDefinition()) { | |
| 5345 // Not a definition. | |
| 5346 only_candidate_uses = false; | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
return false;
Cutch
2014/07/07 22:34:28
Done.
| |
| 5347 break; | |
| 5348 } | |
| 5349 Definition* defn = instr->AsDefinition(); | |
| 5350 if (!defn->IsMintDefinition()) { | |
| 5351 // Not a mint definition. | |
| 5352 only_candidate_uses = false; | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
return false;
Cutch
2014/07/07 22:34:28
Done.
| |
| 5353 break; | |
| 5354 } | |
| 5355 only_candidate_uses = only_candidate_uses && | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
only_candidate_uses are true at this point no need
Cutch
2014/07/07 22:34:28
Done.
| |
| 5356 selected_uint32_defs_->Contains(defn->ssa_temp_index()); | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
You can just do:
for (Value* use = def->input_use
Cutch
2014/07/07 22:34:28
Done.
| |
| 5357 use = use->next_use(); | |
| 5358 } | |
| 5359 return only_candidate_uses; | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
return true;
| |
| 5360 } | |
| 5361 | |
| 5362 | |
| 5363 void IntegerInstructionSelector::Iterate() { | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
I would call it Propagate().
| |
| 5364 ASSERT(selected_uint32_defs_ != NULL); | |
| 5365 ASSERT(changed_); | |
| 5366 intptr_t iteration = 0; | |
| 5367 while (changed_) { | |
| 5368 if (FLAG_trace_integer_ir_selection) { | |
| 5369 OS::Print("+++ Iteration: %" Pd "\n", iteration++); | |
| 5370 } | |
| 5371 changed_ = false; | |
| 5372 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { | |
| 5373 Definition* defn = potential_uint32_defs_[i]; | |
| 5374 if (selected_uint32_defs_->Contains(defn->ssa_temp_index())) { | |
| 5375 // Already marked as a candidate, skip. | |
| 5376 continue; | |
| 5377 } | |
| 5378 if (defn->IsConstant()) { | |
| 5379 // Skip constants. | |
| 5380 continue; | |
| 5381 } | |
| 5382 if (IsUint32Candidate(defn)) { | |
| 5383 if (FLAG_trace_integer_ir_selection) { | |
| 5384 OS::Print("Adding %s\n", defn->ToCString()); | |
| 5385 } | |
| 5386 // Found a new candidate. | |
| 5387 selected_uint32_defs_->Add(defn->ssa_temp_index()); | |
| 5388 // Haven't reached fixed point yet. | |
| 5389 changed_ = true; | |
| 5390 } | |
| 5391 } | |
| 5392 } | |
| 5393 if (FLAG_trace_integer_ir_selection) { | |
| 5394 OS::Print("Reached fixed point\n"); | |
| 5395 } | |
| 5396 } | |
| 5397 | |
| 5398 | |
| 5399 Definition* IntegerInstructionSelector::ConstructReplacementFor( | |
| 5400 Definition* def) { | |
| 5401 // Should only see mint definitions. | |
| 5402 ASSERT(def->IsMintDefinition()); | |
| 5403 // Should not see constant instructions. | |
| 5404 ASSERT(!def->IsConstant()); | |
| 5405 if (def->IsBinaryMintOp()) { | |
| 5406 BinaryMintOpInstr* op = def->AsBinaryMintOp(); | |
| 5407 Token::Kind op_kind = op->op_kind(); | |
| 5408 Value* left = op->left()->CopyWithType(); | |
| 5409 Value* right = op->right()->CopyWithType(); | |
| 5410 intptr_t deopt_id = op->DeoptimizationTarget(); | |
| 5411 return new(I) BinaryUint32OpInstr(op_kind, left, right, deopt_id); | |
| 5412 } else if (def->IsBoxInteger()) { | |
| 5413 BoxIntegerInstr* box = def->AsBoxInteger(); | |
| 5414 Value* value = box->value()->CopyWithType(); | |
| 5415 return new(I) BoxUint32Instr(value); | |
| 5416 } else if (def->IsUnboxInteger()) { | |
| 5417 UnboxIntegerInstr* unbox = def->AsUnboxInteger(); | |
| 5418 Value* value = unbox->value()->CopyWithType(); | |
| 5419 intptr_t deopt_id = unbox->deopt_id(); | |
| 5420 return new(I) UnboxUint32Instr(value, deopt_id); | |
| 5421 } else if (def->IsUnaryMintOp()) { | |
| 5422 UnaryMintOpInstr* op = def->AsUnaryMintOp(); | |
| 5423 Token::Kind op_kind = op->op_kind(); | |
| 5424 Value* value = op->value()->CopyWithType(); | |
| 5425 intptr_t deopt_id = op->DeoptimizationTarget(); | |
| 5426 return new(I) UnaryUint32OpInstr(op_kind, value, deopt_id); | |
| 5427 } else if (def->IsShiftMintOp()) { | |
| 5428 ShiftMintOpInstr* op = def->AsShiftMintOp(); | |
| 5429 Token::Kind op_kind = op->op_kind(); | |
| 5430 Value* left = op->left()->CopyWithType(); | |
| 5431 Value* right = op->right()->CopyWithType(); | |
| 5432 intptr_t deopt_id = op->DeoptimizationTarget(); | |
| 5433 return new(I) ShiftUint32OpInstr(op_kind, left, right, deopt_id); | |
| 5434 } | |
| 5435 printf("%s\n", def->ToCString()); | |
| 5436 UNREACHABLE(); | |
| 5437 return NULL; | |
| 5438 } | |
| 5439 | |
| 5440 | |
| 5441 void IntegerInstructionSelector::ReplaceInstructions() { | |
| 5442 if (FLAG_trace_integer_ir_selection) { | |
| 5443 OS::Print("++++ Replacing instructions:\n"); | |
| 5444 } | |
| 5445 for (intptr_t i = 0; i < potential_uint32_defs_.length(); i++) { | |
| 5446 Definition* defn = potential_uint32_defs_[i]; | |
| 5447 if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) { | |
| 5448 // Not a candidate. | |
| 5449 continue; | |
| 5450 } | |
| 5451 Definition* replacement = ConstructReplacementFor(defn); | |
| 5452 ASSERT(replacement != NULL); | |
| 5453 if (FLAG_trace_integer_ir_selection) { | |
| 5454 OS::Print("Replacing %s with %s\n", defn->ToCString(), | |
| 5455 replacement->ToCString()); | |
| 5456 } | |
| 5457 defn->ReplaceWith(replacement, NULL); | |
| 5458 ASSERT(flow_graph_->VerifyUseLists()); | |
| 5459 } | |
| 5460 } | |
| 5461 | |
| 5462 void FlowGraphOptimizer::SelectIntegerInstructions() { | |
| 5463 IntegerInstructionSelector iis(flow_graph_); | |
| 5464 iis.Select(); | |
| 5465 } | |
| 5466 | |
| 5467 | |
| 5150 void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) { | 5468 void TryCatchAnalyzer::Optimize(FlowGraph* flow_graph) { |
| 5151 // For every catch-block: Iterate over all call instructions inside the | 5469 // For every catch-block: Iterate over all call instructions inside the |
| 5152 // corresponding try-block and figure out for each environment value if it | 5470 // 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 | 5471 // is the same constant at all calls. If yes, replace the initial definition |
| 5154 // at the catch-entry with this constant. | 5472 // at the catch-entry with this constant. |
| 5155 const GrowableArray<CatchBlockEntryInstr*>& catch_entries = | 5473 const GrowableArray<CatchBlockEntryInstr*>& catch_entries = |
| 5156 flow_graph->graph_entry()->catch_entries(); | 5474 flow_graph->graph_entry()->catch_entries(); |
| 5157 intptr_t base = kFirstLocalSlotFromFp + flow_graph->num_non_copied_params(); | 5475 intptr_t base = kFirstLocalSlotFromFp + flow_graph->num_non_copied_params(); |
| 5158 for (intptr_t catch_idx = 0; | 5476 for (intptr_t catch_idx = 0; |
| 5159 catch_idx < catch_entries.length(); | 5477 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(); | 9223 const Object& value = instr->value()->definition()->constant_value(); |
| 8906 if (IsNonConstant(value)) { | 9224 if (IsNonConstant(value)) { |
| 8907 SetValue(instr, non_constant_); | 9225 SetValue(instr, non_constant_); |
| 8908 } else if (IsConstant(value)) { | 9226 } else if (IsConstant(value)) { |
| 8909 // TODO(kmillikin): Handle conversion. | 9227 // TODO(kmillikin): Handle conversion. |
| 8910 SetValue(instr, non_constant_); | 9228 SetValue(instr, non_constant_); |
| 8911 } | 9229 } |
| 8912 } | 9230 } |
| 8913 | 9231 |
| 8914 | 9232 |
| 9233 void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) { | |
| 9234 // TODO(kmillikin): Handle box operation. | |
| 9235 SetValue(instr, non_constant_); | |
| 9236 } | |
| 9237 | |
| 9238 | |
| 9239 void ConstantPropagator::VisitUnboxUint32(UnboxUint32Instr* instr) { | |
| 9240 // TODO(kmillikin): Handle unbox operation. | |
| 9241 SetValue(instr, non_constant_); | |
| 9242 } | |
| 9243 | |
| 9244 | |
| 9245 void ConstantPropagator::VisitUnboxedIntConverter( | |
| 9246 UnboxedIntConverterInstr* instr) { | |
| 9247 SetValue(instr, non_constant_); | |
| 9248 } | |
| 9249 | |
| 9250 | |
| 9251 void ConstantPropagator::VisitBinaryUint32Op(BinaryUint32OpInstr* instr) { | |
| 9252 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | |
|
Vyacheslav Egorov (Google)
2014/07/07 16:16:03
Should result of HandleBinaryOp be truncated to ma
| |
| 9253 } | |
| 9254 | |
| 9255 | |
| 9256 void ConstantPropagator::VisitShiftUint32Op(ShiftUint32OpInstr* instr) { | |
| 9257 HandleBinaryOp(instr, instr->op_kind(), *instr->left(), *instr->right()); | |
| 9258 } | |
| 9259 | |
| 9260 | |
| 9261 void ConstantPropagator::VisitUnaryUint32Op(UnaryUint32OpInstr* instr) { | |
| 9262 // TODO(kmillikin): Handle unary operations. | |
| 9263 SetValue(instr, non_constant_); | |
| 9264 } | |
| 9265 | |
| 9266 | |
| 8915 void ConstantPropagator::Analyze() { | 9267 void ConstantPropagator::Analyze() { |
| 8916 GraphEntryInstr* entry = graph_->graph_entry(); | 9268 GraphEntryInstr* entry = graph_->graph_entry(); |
| 8917 reachable_->Add(entry->preorder_number()); | 9269 reachable_->Add(entry->preorder_number()); |
| 8918 block_worklist_.Add(entry); | 9270 block_worklist_.Add(entry); |
| 8919 | 9271 |
| 8920 while (true) { | 9272 while (true) { |
| 8921 if (block_worklist_.is_empty()) { | 9273 if (block_worklist_.is_empty()) { |
| 8922 if (definition_worklist_.is_empty()) break; | 9274 if (definition_worklist_.is_empty()) break; |
| 8923 Definition* definition = definition_worklist_.RemoveLast(); | 9275 Definition* definition = definition_worklist_.RemoveLast(); |
| 8924 definition_marks_->Remove(definition->ssa_temp_index()); | 9276 definition_marks_->Remove(definition->ssa_temp_index()); |
| (...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9818 } | 10170 } |
| 9819 | 10171 |
| 9820 // Insert materializations at environment uses. | 10172 // Insert materializations at environment uses. |
| 9821 for (intptr_t i = 0; i < exits.length(); i++) { | 10173 for (intptr_t i = 0; i < exits.length(); i++) { |
| 9822 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); | 10174 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); |
| 9823 } | 10175 } |
| 9824 } | 10176 } |
| 9825 | 10177 |
| 9826 | 10178 |
| 9827 } // namespace dart | 10179 } // namespace dart |
| OLD | NEW |