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

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

Issue 12540002: Implement a branch optimization pass. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Incorporated review comments. 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
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/il_printer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 4356 matching lines...) Expand 10 before | Expand all | Expand 10 after
4367 graph_->ComputeDominators(&dominance_frontier); 4367 graph_->ComputeDominators(&dominance_frontier);
4368 4368
4369 if (FLAG_trace_constant_propagation) { 4369 if (FLAG_trace_constant_propagation) {
4370 OS::Print("\n==== After constant propagation ====\n"); 4370 OS::Print("\n==== After constant propagation ====\n");
4371 FlowGraphPrinter printer(*graph_); 4371 FlowGraphPrinter printer(*graph_);
4372 printer.PrintBlocks(); 4372 printer.PrintBlocks();
4373 } 4373 }
4374 } 4374 }
4375 4375
4376 4376
4377 bool BranchSimplifier::Match(JoinEntryInstr* block) {
4378 // Match the pattern of a branch on a comparison whose left operand is a
4379 // phi from the same block, and whose right operand is a constant.
4380 //
4381 // Branch(Comparison(kind, Phi, Constant))
4382 //
4383 // These are the branches produced by inlining in a test context. Also,
4384 // the phi and the constant have no other uses so they can simply be
4385 // eliminated. The block has no other phis and no instructions
4386 // intervening between the phi, constant, and branch so the block can
4387 // simply be eliminated.
4388 BranchInstr* branch = block->last_instruction()->AsBranch();
4389 ASSERT(branch != NULL);
4390 ComparisonInstr* comparison = branch->comparison();
4391 Value* left = comparison->left();
4392 PhiInstr* phi = left->definition()->AsPhi();
4393 Value* right = comparison->right();
4394 ConstantInstr* constant = right->definition()->AsConstant();
4395 return (phi != NULL) &&
4396 (constant != NULL) &&
4397 (phi->GetBlock() == block) &&
4398 phi->HasOnlyUse(left) &&
4399 constant->HasOnlyUse(right) &&
4400 (block->next() == constant) &&
4401 (constant->next() == branch) &&
4402 (block->phis()->length() == 1);
4403 }
4404
4405
4406 JoinEntryInstr* BranchSimplifier::ToJoinEntry(TargetEntryInstr* target) {
4407 // Convert a target block into a join block. Branches will be duplicated
4408 // so the former true and false targets become joins of the control flows
4409 // from all the duplicated branches.
4410 JoinEntryInstr* join =
4411 new JoinEntryInstr(target->block_id(), target->try_index());
4412 join->LinkTo(target->next());
4413 join->set_last_instruction(target->last_instruction());
4414 return join;
4415 }
4416
4417
4418 ConstantInstr* BranchSimplifier::CloneConstant(FlowGraph* flow_graph,
4419 ConstantInstr* constant) {
4420 ConstantInstr* new_constant = new ConstantInstr(constant->value());
4421 new_constant->set_ssa_temp_index(flow_graph->alloc_ssa_temp_index());
4422 return new_constant;
4423 }
4424
4425
4426 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch,
4427 Value* left,
4428 Value* right) {
4429 ComparisonInstr* comparison = branch->comparison();
4430 ComparisonInstr* new_comparison = NULL;
4431 if (comparison->IsStrictCompare()) {
4432 new_comparison = new StrictCompareInstr(comparison->kind(), left, right);
4433 } else if (comparison->IsEqualityCompare()) {
4434 new_comparison =
4435 new EqualityCompareInstr(comparison->AsEqualityCompare()->token_pos(),
4436 comparison->kind(),
4437 left,
4438 right);
4439 } else {
4440 ASSERT(comparison->IsRelationalOp());
4441 new_comparison =
4442 new RelationalOpInstr(comparison->AsRelationalOp()->token_pos(),
4443 comparison->kind(),
4444 left,
4445 right);
4446 }
4447 return new BranchInstr(new_comparison, branch->is_checked());
4448 }
4449
4450
4451 void BranchSimplifier::Simplify(FlowGraph* flow_graph) {
4452 // Optimize some branches that test the value of a phi. When it is safe
4453 // to do so, push the branch to each of the predecessor blocks. This is
4454 // an optimization when (a) it can avoid materializing a boolean object at
4455 // the phi only to test its value, and (b) it can expose opportunities for
4456 // constant propagation and unreachable code elimination. This
4457 // optimization is intended to run after inlining which creates
4458 // opportunities for optimization (a) and before constant folding which
4459 // can perform optimization (b).
4460
4461 // Begin with a worklist of join blocks ending in branches. They are
4462 // candidates for the pattern below.
4463 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder();
4464 GrowableArray<BlockEntryInstr*> worklist(postorder.length());
4465 for (BlockIterator it(postorder); !it.Done(); it.Advance()) {
4466 BlockEntryInstr* block = it.Current();
4467 if (block->IsJoinEntry() && block->last_instruction()->IsBranch()) {
4468 worklist.Add(block);
4469 }
4470 }
4471
4472 // Rewrite until no more instance of the pattern exists.
4473 bool changed = false;
4474 while (!worklist.is_empty()) {
4475 // All blocks in the worklist are join blocks (ending with a branch).
4476 JoinEntryInstr* block = worklist.RemoveLast()->AsJoinEntry();
4477 ASSERT(block != NULL);
4478
4479 if (Match(block)) {
4480 changed = true;
4481
4482 // The branch will be copied and pushed to all the join's
4483 // predecessors. Convert the true and false target blocks into join
4484 // blocks to join the control flows from all of the true
4485 // (respectively, false) targets of the copied branches.
4486 //
4487 // The converted join block will have no phis, so it cannot be another
4488 // instance of the pattern. There is thus no need to add it to the
4489 // worklist.
4490 BranchInstr* branch = block->last_instruction()->AsBranch();
4491 ASSERT(branch != NULL);
4492 JoinEntryInstr* join_true = ToJoinEntry(branch->true_successor());
4493 JoinEntryInstr* join_false = ToJoinEntry(branch->false_successor());
4494
4495 ComparisonInstr* comparison = branch->comparison();
4496 PhiInstr* phi = comparison->left()->definition()->AsPhi();
4497 ConstantInstr* constant = comparison->right()->definition()->AsConstant();
4498 ASSERT(constant != NULL);
4499 // Copy the constant and branch and push it to all the predecessors.
4500 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) {
4501 GotoInstr* old_goto =
4502 block->PredecessorAt(i)->last_instruction()->AsGoto();
4503 ASSERT(old_goto != NULL);
4504
4505 // Insert a copy of the constant in all the predecessors.
4506 ConstantInstr* new_constant = CloneConstant(flow_graph, constant);
4507 new_constant->InsertBefore(old_goto);
4508
4509 // Replace the goto in each predecessor with a rewritten branch,
4510 // rewritten to use the corresponding phi input instead of the phi.
4511 Value* new_left = phi->InputAt(i)->Copy();
4512 Value* new_right = new Value(new_constant);
4513 BranchInstr* new_branch = CloneBranch(branch, new_left, new_right);
4514 new_branch->InsertBefore(old_goto);
4515 new_branch->set_next(NULL); // Detaching the goto from the graph.
4516 old_goto->UnuseAllInputs();
4517
4518 // Update the predecessor block. We may have created another
4519 // instance of the pattern so add it to the worklist if necessary.
4520 BlockEntryInstr* branch_block = new_branch->GetBlock();
4521 branch_block->set_last_instruction(new_branch);
4522 if (branch_block->IsJoinEntry()) worklist.Add(branch_block);
4523
4524 // Connect the branch to the true and false joins, via empty target
4525 // blocks.
4526 TargetEntryInstr* true_target =
4527 new TargetEntryInstr(flow_graph->max_block_id() + 1,
4528 block->try_index());
4529 TargetEntryInstr* false_target =
4530 new TargetEntryInstr(flow_graph->max_block_id() + 2,
4531 block->try_index());
4532 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2);
4533 *new_branch->true_successor_address() = true_target;
4534 *new_branch->false_successor_address() = false_target;
4535 GotoInstr* goto_true = new GotoInstr(join_true);
4536 true_target->LinkTo(goto_true);
4537 true_target->set_last_instruction(goto_true);
4538 GotoInstr* goto_false = new GotoInstr(join_false);
4539 false_target->LinkTo(goto_false);
4540 false_target->set_last_instruction(goto_false);
4541 }
4542 // When all predecessors have been rewritten, the original block is
4543 // unreachable from the graph.
4544 phi->UnuseAllInputs();
4545 branch->UnuseAllInputs();
4546 }
4547 }
4548
4549 if (changed) {
4550 // We may have changed the block order and the dominator tree.
4551 flow_graph->DiscoverBlocks();
4552 GrowableArray<BitVector*> dominance_frontier;
4553 flow_graph->ComputeDominators(&dominance_frontier);
4554 }
4555 }
4556
4557
4377 } // namespace dart 4558 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/il_printer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698