Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(138)

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 12340108: Remove dead phis as soon as they are discovered. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/flow_graph_compiler.h" 10 #include "vm/flow_graph_compiler.h"
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 const Representation to_rep = 376 const Representation to_rep =
377 use->instruction()->RequiredInputRepresentation(use->use_index()); 377 use->instruction()->RequiredInputRepresentation(use->use_index());
378 if (from_rep == to_rep) { 378 if (from_rep == to_rep) {
379 continue; 379 continue;
380 } 380 }
381 381
382 Instruction* insert_before; 382 Instruction* insert_before;
383 Instruction* deopt_target; 383 Instruction* deopt_target;
384 PhiInstr* phi = use->instruction()->AsPhi(); 384 PhiInstr* phi = use->instruction()->AsPhi();
385 if (phi != NULL) { 385 if (phi != NULL) {
386 if (!phi->is_alive()) continue; 386 ASSERT(phi->is_alive());
387
388 // For phis conversions have to be inserted in the predecessor. 387 // For phis conversions have to be inserted in the predecessor.
389 insert_before = 388 insert_before =
390 phi->block()->PredecessorAt(use->use_index())->last_instruction(); 389 phi->block()->PredecessorAt(use->use_index())->last_instruction();
391 deopt_target = NULL; 390 deopt_target = NULL;
392 } else { 391 } else {
393 deopt_target = insert_before = use->instruction(); 392 deopt_target = insert_before = use->instruction();
394 } 393 }
395 394
396 InsertConversion(from_rep, to_rep, use, insert_before, deopt_target); 395 InsertConversion(from_rep, to_rep, use, insert_before, deopt_target);
397 } 396 }
398 } 397 }
399 398
400 399
401 void FlowGraphOptimizer::SelectRepresentations() { 400 void FlowGraphOptimizer::SelectRepresentations() {
402 // Convervatively unbox all phis that were proven to be of type Double. 401 // Convervatively unbox all phis that were proven to be of type Double.
403 for (intptr_t i = 0; i < block_order_.length(); ++i) { 402 for (intptr_t i = 0; i < block_order_.length(); ++i) {
404 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry(); 403 JoinEntryInstr* join_entry = block_order_[i]->AsJoinEntry();
405 if (join_entry == NULL) continue; 404 if (join_entry != NULL) {
406 405 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
407 if (join_entry->phis() != NULL) { 406 PhiInstr* phi = it.Current();
408 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { 407 ASSERT(phi != NULL);
409 PhiInstr* phi = (*join_entry->phis())[i];
410 if (phi == NULL) continue;
411 if (phi->Type()->ToCid() == kDoubleCid) { 408 if (phi->Type()->ToCid() == kDoubleCid) {
412 phi->set_representation(kUnboxedDouble); 409 phi->set_representation(kUnboxedDouble);
413 } 410 }
414 } 411 }
415 } 412 }
416 } 413 }
417 414
418 // Process all instructions and insert conversions where needed. 415 // Process all instructions and insert conversions where needed.
419 GraphEntryInstr* graph_entry = block_order_[0]->AsGraphEntry(); 416 GraphEntryInstr* graph_entry = block_order_[0]->AsGraphEntry();
420 417
421 // Visit incoming parameters and constants. 418 // Visit incoming parameters and constants.
422 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) { 419 for (intptr_t i = 0; i < graph_entry->initial_definitions()->length(); i++) {
423 InsertConversionsFor((*graph_entry->initial_definitions())[i]); 420 InsertConversionsFor((*graph_entry->initial_definitions())[i]);
424 } 421 }
425 422
426 for (intptr_t i = 0; i < block_order_.length(); ++i) { 423 for (intptr_t i = 0; i < block_order_.length(); ++i) {
427 BlockEntryInstr* entry = block_order_[i]; 424 BlockEntryInstr* entry = block_order_[i];
428
429 JoinEntryInstr* join_entry = entry->AsJoinEntry(); 425 JoinEntryInstr* join_entry = entry->AsJoinEntry();
430 if ((join_entry != NULL) && (join_entry->phis() != NULL)) { 426 if (join_entry != NULL) {
431 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { 427 for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
432 PhiInstr* phi = (*join_entry->phis())[i]; 428 PhiInstr* phi = it.Current();
433 if ((phi != NULL) && (phi->is_alive())) { 429 ASSERT(phi != NULL);
434 InsertConversionsFor(phi); 430 ASSERT(phi->is_alive());
435 } 431 InsertConversionsFor(phi);
436 } 432 }
437 } 433 }
438
439 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 434 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
440 Definition* def = it.Current()->AsDefinition(); 435 Definition* def = it.Current()->AsDefinition();
441 if (def != NULL) { 436 if (def != NULL) {
442 InsertConversionsFor(def); 437 InsertConversionsFor(def);
443 } 438 }
444 } 439 }
445 } 440 }
446 } 441 }
447 442
448 443
(...skipping 1800 matching lines...) Expand 10 before | Expand all | Expand 10 after
2249 void RangeAnalysis::RenameDominatedUses(Definition* def, 2244 void RangeAnalysis::RenameDominatedUses(Definition* def,
2250 Instruction* dom, 2245 Instruction* dom,
2251 Definition* other) { 2246 Definition* other) {
2252 for (Value::Iterator it(def->input_use_list()); 2247 for (Value::Iterator it(def->input_use_list());
2253 !it.Done(); 2248 !it.Done();
2254 it.Advance()) { 2249 it.Advance()) {
2255 Value* use = it.Current(); 2250 Value* use = it.Current();
2256 2251
2257 // Skip dead phis. 2252 // Skip dead phis.
2258 PhiInstr* phi = use->instruction()->AsPhi(); 2253 PhiInstr* phi = use->instruction()->AsPhi();
2259 if ((phi != NULL) && !phi->is_alive()) continue; 2254 ASSERT((phi == NULL) || phi->is_alive());
2260
2261 if (IsDominatedUse(dom, use)) { 2255 if (IsDominatedUse(dom, use)) {
2262 use->BindTo(other); 2256 use->BindTo(other);
2263 } 2257 }
2264 } 2258 }
2265 } 2259 }
2266 2260
2267 2261
2268 // For a comparison operation return an operation for the equivalent flipped 2262 // For a comparison operation return an operation for the equivalent flipped
2269 // comparison: a (op) b === b (op') a. 2263 // comparison: a (op) b === b (op') a.
2270 static Token::Kind FlipComparison(Token::Kind op) { 2264 static Token::Kind FlipComparison(Token::Kind op) {
(...skipping 1098 matching lines...) Expand 10 before | Expand all | Expand 10 after
3369 // All phis in the worklist are redundant and have the same computed 3363 // All phis in the worklist are redundant and have the same computed
3370 // value on all code paths. 3364 // value on all code paths.
3371 ASSERT(value != NULL); 3365 ASSERT(value != NULL);
3372 for (intptr_t i = 0; i < worklist_.length(); i++) { 3366 for (intptr_t i = 0; i < worklist_.length(); i++) {
3373 worklist_[i]->ReplaceUsesWith(value); 3367 worklist_[i]->ReplaceUsesWith(value);
3374 } 3368 }
3375 3369
3376 return true; 3370 return true;
3377 } 3371 }
3378 3372
3379 // Emit non-redundant phis created during ComputeOutValues and ForwardLoads. 3373 // Phis have not yet been inserted into the graph but they have uses of
3374 // their inputs. Insert the non-redundant ones and clear the input uses
3375 // of the redundant ones.
3380 void EmitPhis() { 3376 void EmitPhis() {
3381 for (intptr_t i = 0; i < phis_.length(); i++) { 3377 for (intptr_t i = 0; i < phis_.length(); i++) {
3382 PhiInstr* phi = phis_[i]; 3378 PhiInstr* phi = phis_[i];
3383 if ((phi->input_use_list() != NULL) && !EliminateRedundantPhi(phi)) { 3379 if ((phi->input_use_list() != NULL) && !EliminateRedundantPhi(phi)) {
3384 phi->mark_alive(); 3380 phi->mark_alive();
3385 phi->block()->InsertPhi(phi); 3381 phi->block()->InsertPhi(phi);
3382 } else {
3383 for (intptr_t j = phi->InputCount() - 1; j >= 0; --j) {
3384 phi->InputAt(j)->RemoveFromUseList();
3385 }
3386 } 3386 }
3387 } 3387 }
3388 } 3388 }
3389 3389
3390 ZoneGrowableArray<Definition*>* CreateBlockOutValues() { 3390 ZoneGrowableArray<Definition*>* CreateBlockOutValues() {
3391 ZoneGrowableArray<Definition*>* out = 3391 ZoneGrowableArray<Definition*>* out =
3392 new ZoneGrowableArray<Definition*>(max_expr_id_); 3392 new ZoneGrowableArray<Definition*>(max_expr_id_);
3393 for (intptr_t i = 0; i < max_expr_id_; i++) { 3393 for (intptr_t i = 0; i < max_expr_id_; i++) {
3394 out->Add(NULL); 3394 out->Add(NULL);
3395 } 3395 }
(...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after
4244 it.Current()->UnuseAllInputs(); 4244 it.Current()->UnuseAllInputs();
4245 } 4245 }
4246 continue; 4246 continue;
4247 } 4247 }
4248 4248
4249 if (join != NULL) { 4249 if (join != NULL) {
4250 // Remove phi inputs corresponding to unreachable predecessor blocks. 4250 // Remove phi inputs corresponding to unreachable predecessor blocks.
4251 // Predecessors will be recomputed (in block id order) after removing 4251 // Predecessors will be recomputed (in block id order) after removing
4252 // unreachable code so we merely have to keep the phi inputs in order. 4252 // unreachable code so we merely have to keep the phi inputs in order.
4253 ZoneGrowableArray<PhiInstr*>* phis = join->phis(); 4253 ZoneGrowableArray<PhiInstr*>* phis = join->phis();
4254 if (phis != NULL) { 4254 if ((phis != NULL) && !phis->is_empty()) {
4255 intptr_t pred_count = join->PredecessorCount(); 4255 intptr_t pred_count = join->PredecessorCount();
4256 intptr_t live_count = 0; 4256 intptr_t live_count = 0;
4257 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) { 4257 for (intptr_t pred_idx = 0; pred_idx < pred_count; ++pred_idx) {
4258 if (reachable_->Contains( 4258 if (reachable_->Contains(
4259 join->PredecessorAt(pred_idx)->preorder_number())) { 4259 join->PredecessorAt(pred_idx)->preorder_number())) {
4260 if (live_count < pred_idx) { 4260 if (live_count < pred_idx) {
4261 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { 4261 for (PhiIterator it(join); !it.Done(); it.Advance()) {
4262 PhiInstr* phi = (*phis)[phi_idx]; 4262 PhiInstr* phi = it.Current();
4263 if (phi == NULL) continue; 4263 ASSERT(phi != NULL);
4264 phi->SetInputAt(live_count, phi->InputAt(pred_idx)); 4264 phi->SetInputAt(live_count, phi->InputAt(pred_idx));
4265 } 4265 }
4266 } 4266 }
4267 ++live_count; 4267 ++live_count;
4268 } else { 4268 } else {
4269 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { 4269 for (PhiIterator it(join); !it.Done(); it.Advance()) {
4270 PhiInstr* phi = (*phis)[phi_idx]; 4270 PhiInstr* phi = it.Current();
4271 if (phi == NULL) continue; 4271 ASSERT(phi != NULL);
4272 phi->InputAt(pred_idx)->RemoveFromUseList(); 4272 phi->InputAt(pred_idx)->RemoveFromUseList();
4273 } 4273 }
4274 } 4274 }
4275 } 4275 }
4276 if (live_count < pred_count) { 4276 if (live_count < pred_count) {
4277 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) { 4277 intptr_t to_idx = 0;
4278 PhiInstr* phi = (*phis)[phi_idx]; 4278 for (intptr_t from_idx = 0; from_idx < phis->length(); ++from_idx) {
4279 if (phi == NULL) continue; 4279 PhiInstr* phi = (*phis)[from_idx];
4280 ASSERT(phi != NULL);
4280 if (FLAG_remove_redundant_phis && (live_count == 1)) { 4281 if (FLAG_remove_redundant_phis && (live_count == 1)) {
Vyacheslav Egorov (Google) 2013/02/27 21:53:02 Do we have any code that kills truly redundant phi
Kevin Millikin (Google) 2013/02/28 08:12:02 I don't think so. I wonder, do they arise?
4281 Value* input = phi->InputAt(0); 4282 Value* input = phi->InputAt(0);
4282 phi->ReplaceUsesWith(input->definition()); 4283 phi->ReplaceUsesWith(input->definition());
4283 input->RemoveFromUseList(); 4284 input->RemoveFromUseList();
4284 (*phis)[phi_idx] = NULL;
4285 } else { 4285 } else {
4286 phi->inputs_.TruncateTo(live_count); 4286 phi->inputs_.TruncateTo(live_count);
4287 (*phis)[to_idx++] = phi;
4287 } 4288 }
4288 } 4289 }
4290 if (to_idx == 0) {
4291 join->phis_ = NULL;
4292 } else {
4293 phis->TruncateTo(to_idx);
4294 }
4289 } 4295 }
4290 } 4296 }
4291 } 4297 }
4292 4298
4293 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) { 4299 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) {
4294 Definition* defn = i.Current()->AsDefinition(); 4300 Definition* defn = i.Current()->AsDefinition();
4295 // Replace constant-valued instructions without observable side 4301 // Replace constant-valued instructions without observable side
4296 // effects. Do this for smis only to avoid having to copy other 4302 // effects. Do this for smis only to avoid having to copy other
4297 // objects into the heap's old generation. 4303 // objects into the heap's old generation.
4298 if ((defn != NULL) && 4304 if ((defn != NULL) &&
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
4357 4363
4358 if (FLAG_trace_constant_propagation) { 4364 if (FLAG_trace_constant_propagation) {
4359 OS::Print("\n==== After constant propagation ====\n"); 4365 OS::Print("\n==== After constant propagation ====\n");
4360 FlowGraphPrinter printer(*graph_); 4366 FlowGraphPrinter printer(*graph_);
4361 printer.PrintBlocks(); 4367 printer.PrintBlocks();
4362 } 4368 }
4363 } 4369 }
4364 4370
4365 4371
4366 } // namespace dart 4372 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698