| 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/intermediate_language.h" | 5 #include "vm/intermediate_language.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 while (!result->IsBlockEntry()) result = result->previous(); | 368 while (!result->IsBlockEntry()) result = result->previous(); |
| 369 return result->AsBlockEntry(); | 369 return result->AsBlockEntry(); |
| 370 } | 370 } |
| 371 | 371 |
| 372 | 372 |
| 373 void ForwardInstructionIterator::RemoveCurrentFromGraph() { | 373 void ForwardInstructionIterator::RemoveCurrentFromGraph() { |
| 374 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. | 374 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. |
| 375 } | 375 } |
| 376 | 376 |
| 377 | 377 |
| 378 void ForwardInstructionIterator::ReplaceCurrentWith(Definition* other) { | |
| 379 Definition* defn = current_->AsDefinition(); | |
| 380 ASSERT(defn != NULL); | |
| 381 defn->ReplaceUsesWith(other); | |
| 382 ASSERT(other->env() == NULL); | |
| 383 other->set_env(defn->env()); | |
| 384 defn->set_env(NULL); | |
| 385 ASSERT(!other->HasSSATemp()); | |
| 386 if (defn->HasSSATemp()) other->set_ssa_temp_index(defn->ssa_temp_index()); | |
| 387 | |
| 388 other->InsertBefore(current_); // So other will be current. | |
| 389 RemoveCurrentFromGraph(); | |
| 390 } | |
| 391 | |
| 392 | |
| 393 // Default implementation of visiting basic blocks. Can be overridden. | 378 // Default implementation of visiting basic blocks. Can be overridden. |
| 394 void FlowGraphVisitor::VisitBlocks() { | 379 void FlowGraphVisitor::VisitBlocks() { |
| 395 ASSERT(current_iterator_ == NULL); | 380 ASSERT(current_iterator_ == NULL); |
| 396 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 381 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 397 BlockEntryInstr* entry = block_order_[i]; | 382 BlockEntryInstr* entry = block_order_[i]; |
| 398 entry->Accept(this); | 383 entry->Accept(this); |
| 399 ForwardInstructionIterator it(entry); | 384 ForwardInstructionIterator it(entry); |
| 400 current_iterator_ = ⁢ | 385 current_iterator_ = ⁢ |
| 401 for (; !it.Done(); it.Advance()) { | 386 for (; !it.Done(); it.Advance()) { |
| 402 it.Current()->Accept(this); | 387 it.Current()->Accept(this); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 InputAt(i)->RemoveFromUseList(); | 524 InputAt(i)->RemoveFromUseList(); |
| 540 } | 525 } |
| 541 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) { | 526 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) { |
| 542 it.CurrentValue()->RemoveFromUseList(); | 527 it.CurrentValue()->RemoveFromUseList(); |
| 543 } | 528 } |
| 544 } | 529 } |
| 545 | 530 |
| 546 | 531 |
| 547 void Definition::ReplaceWith(Definition* other, | 532 void Definition::ReplaceWith(Definition* other, |
| 548 ForwardInstructionIterator* iterator) { | 533 ForwardInstructionIterator* iterator) { |
| 534 // Record other's input uses. |
| 535 for (intptr_t i = other->InputCount() - 1; i >= 0; --i) { |
| 536 Value* input = other->InputAt(i); |
| 537 input->definition()->AddInputUse(input); |
| 538 input->set_instruction(other); |
| 539 input->set_use_index(i); |
| 540 } |
| 541 // Take other's environment from this definition. |
| 542 ASSERT(other->env() == NULL); |
| 543 intptr_t use_index = 0; |
| 544 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) { |
| 545 Value* use = it.CurrentValue(); |
| 546 use->set_instruction(other); |
| 547 use->set_use_index(use_index++); |
| 548 } |
| 549 other->set_env(env()); |
| 550 set_env(NULL); |
| 551 // Replace all uses of this definition with other. |
| 552 ReplaceUsesWith(other); |
| 553 // Reuse this instruction's SSA name for other. |
| 554 ASSERT(!other->HasSSATemp()); |
| 555 if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index()); |
| 556 // Remove this definition's input uses. |
| 557 UnuseAllInputs(); |
| 558 |
| 559 // Finally remove this definition from the graph. |
| 560 previous()->LinkTo(other); |
| 549 if ((iterator != NULL) && (this == iterator->Current())) { | 561 if ((iterator != NULL) && (this == iterator->Current())) { |
| 550 iterator->ReplaceCurrentWith(other); | 562 // Remove through the iterator. |
| 563 other->LinkTo(this); |
| 564 iterator->RemoveCurrentFromGraph(); |
| 551 } else { | 565 } else { |
| 552 ReplaceUsesWith(other); | |
| 553 ASSERT(other->env() == NULL); | |
| 554 other->set_env(env()); | |
| 555 set_env(NULL); | |
| 556 ASSERT(!other->HasSSATemp()); | |
| 557 if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index()); | |
| 558 | |
| 559 previous()->LinkTo(other); | |
| 560 other->LinkTo(next()); | 566 other->LinkTo(next()); |
| 561 | |
| 562 set_previous(NULL); | |
| 563 set_next(NULL); | |
| 564 } | 567 } |
| 568 set_previous(NULL); |
| 569 set_next(NULL); |
| 565 } | 570 } |
| 566 | 571 |
| 567 | 572 |
| 568 // ==== Postorder graph traversal. | 573 // ==== Postorder graph traversal. |
| 569 static bool IsMarked(BlockEntryInstr* block, | 574 static bool IsMarked(BlockEntryInstr* block, |
| 570 GrowableArray<BlockEntryInstr*>* preorder) { | 575 GrowableArray<BlockEntryInstr*>* preorder) { |
| 571 // Detect that a block has been visited as part of the current | 576 // Detect that a block has been visited as part of the current |
| 572 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block | 577 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block |
| 573 // will be 'marked' by (1) having a preorder number in the range of the | 578 // will be 'marked' by (1) having a preorder number in the range of the |
| 574 // preorder array and (2) being in the preorder array at that index. | 579 // preorder array and (2) being in the preorder array at that index. |
| (...skipping 503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1078 Definition* LoadFieldInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1083 Definition* LoadFieldInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1079 if (!IsImmutableLengthLoad()) return this; | 1084 if (!IsImmutableLengthLoad()) return this; |
| 1080 | 1085 |
| 1081 // For fixed length arrays if the array is the result of a known constructor | 1086 // For fixed length arrays if the array is the result of a known constructor |
| 1082 // call we can replace the length load with the length argument passed to | 1087 // call we can replace the length load with the length argument passed to |
| 1083 // the constructor. | 1088 // the constructor. |
| 1084 StaticCallInstr* call = value()->definition()->AsStaticCall(); | 1089 StaticCallInstr* call = value()->definition()->AsStaticCall(); |
| 1085 if (call != NULL && | 1090 if (call != NULL && |
| 1086 call->is_known_constructor() && | 1091 call->is_known_constructor() && |
| 1087 (call->Type()->ToCid() == kArrayCid)) { | 1092 (call->Type()->ToCid() == kArrayCid)) { |
| 1088 return call->ArgumentAt(1)->value()->definition(); | 1093 return call->ArgumentAt(1); |
| 1089 } | 1094 } |
| 1090 return this; | 1095 return this; |
| 1091 } | 1096 } |
| 1092 | 1097 |
| 1093 | 1098 |
| 1094 Definition* AssertBooleanInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1099 Definition* AssertBooleanInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1095 if (FLAG_eliminate_type_checks && (value()->Type()->ToCid() == kBoolCid)) { | 1100 if (FLAG_eliminate_type_checks && (value()->Type()->ToCid() == kBoolCid)) { |
| 1096 return value()->definition(); | 1101 return value()->definition(); |
| 1097 } | 1102 } |
| 1098 | 1103 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1147 comp->InputAt(i)->definition()->representation()) { | 1152 comp->InputAt(i)->definition()->representation()) { |
| 1148 return this; | 1153 return this; |
| 1149 } | 1154 } |
| 1150 } | 1155 } |
| 1151 | 1156 |
| 1152 // Replace the comparison if the replacement is used at this branch, | 1157 // Replace the comparison if the replacement is used at this branch, |
| 1153 // and has exactly one use. | 1158 // and has exactly one use. |
| 1154 if ((comp->input_use_list()->instruction() == this) && | 1159 if ((comp->input_use_list()->instruction() == this) && |
| 1155 (comp->input_use_list()->next_use() == NULL) && | 1160 (comp->input_use_list()->next_use() == NULL) && |
| 1156 (comp->env_use_list() == NULL)) { | 1161 (comp->env_use_list() == NULL)) { |
| 1162 comparison()->UnuseAllInputs(); |
| 1157 comp->RemoveFromGraph(); | 1163 comp->RemoveFromGraph(); |
| 1158 // It is safe to pass a NULL iterator because we're replacing the | 1164 // It is safe to pass a NULL iterator because we're replacing the |
| 1159 // comparison wrapped in a BranchInstr which does not modify the | 1165 // comparison wrapped in a BranchInstr which does not modify the |
| 1160 // linked list of instructions. | 1166 // linked list of instructions. |
| 1161 ReplaceWith(comp, NULL /* ignored */); | 1167 ReplaceWith(comp, NULL /* ignored */); |
| 1162 for (intptr_t i = 0; i < comp->InputCount(); ++i) { | 1168 for (intptr_t i = 0; i < comp->InputCount(); ++i) { |
| 1163 Value* operand = comp->InputAt(i); | 1169 Value* operand = comp->InputAt(i); |
| 1164 operand->set_instruction(this); | 1170 operand->set_instruction(this); |
| 1165 } | 1171 } |
| 1166 if (FLAG_trace_optimization) { | 1172 if (FLAG_trace_optimization) { |
| 1167 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); | 1173 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); |
| 1168 } | 1174 } |
| 1169 // Clear the comparison's use list, temp index and ssa temp index since | 1175 // Clear the comparison's temp index and ssa temp index since the |
| 1170 // the value of the comparison is not used outside the branch anymore. | 1176 // value of the comparison is not used outside the branch anymore. |
| 1171 comp->set_input_use_list(NULL); | 1177 ASSERT(comp->input_use_list() == NULL); |
| 1172 comp->ClearSSATempIndex(); | 1178 comp->ClearSSATempIndex(); |
| 1173 comp->ClearTempIndex(); | 1179 comp->ClearTempIndex(); |
| 1174 } | 1180 } |
| 1175 } | 1181 } |
| 1176 return this; | 1182 return this; |
| 1177 } | 1183 } |
| 1178 | 1184 |
| 1179 | 1185 |
| 1180 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1186 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1181 if (!right()->BindsToConstant()) return this; | 1187 if (!right()->BindsToConstant()) return this; |
| (...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2195 default: | 2201 default: |
| 2196 UNREACHABLE(); | 2202 UNREACHABLE(); |
| 2197 } | 2203 } |
| 2198 return kPowRuntimeEntry; | 2204 return kPowRuntimeEntry; |
| 2199 } | 2205 } |
| 2200 | 2206 |
| 2201 | 2207 |
| 2202 #undef __ | 2208 #undef __ |
| 2203 | 2209 |
| 2204 } // namespace dart | 2210 } // namespace dart |
| OLD | NEW |