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

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

Issue 78733002: Generalize if-conversion to arbitrary smi comparisons. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: added missing test file Created 7 years, 1 month 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/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 call->deopt_id(), 1355 call->deopt_id(),
1356 call->env(), 1356 call->env(),
1357 call); 1357 call);
1358 cid = kSmiCid; 1358 cid = kSmiCid;
1359 } else { 1359 } else {
1360 // Shortcut for equality with null. 1360 // Shortcut for equality with null.
1361 ConstantInstr* right_const = right->AsConstant(); 1361 ConstantInstr* right_const = right->AsConstant();
1362 ConstantInstr* left_const = left->AsConstant(); 1362 ConstantInstr* left_const = left->AsConstant();
1363 if ((right_const != NULL && right_const->value().IsNull()) || 1363 if ((right_const != NULL && right_const->value().IsNull()) ||
1364 (left_const != NULL && left_const->value().IsNull())) { 1364 (left_const != NULL && left_const->value().IsNull())) {
1365 StrictCompareInstr* comp = new StrictCompareInstr(call->token_pos(), 1365 StrictCompareInstr* comp =
1366 Token::kEQ_STRICT, 1366 new StrictCompareInstr(call->token_pos(),
1367 new Value(left), 1367 Token::kEQ_STRICT,
1368 new Value(right)); 1368 new Value(left),
1369 new Value(right),
1370 false); // No number check.
1369 ReplaceCall(call, comp); 1371 ReplaceCall(call, comp);
1370 return true; 1372 return true;
1371 } 1373 }
1372 return false; 1374 return false;
1373 } 1375 }
1374 } 1376 }
1375 ASSERT(cid != kIllegalCid); 1377 ASSERT(cid != kIllegalCid);
1376 EqualityCompareInstr* comp = new EqualityCompareInstr(call->token_pos(), 1378 EqualityCompareInstr* comp = new EqualityCompareInstr(call->token_pos(),
1377 op_kind, 1379 op_kind,
1378 new Value(left), 1380 new Value(left),
(...skipping 4885 matching lines...) Expand 10 before | Expand all | Expand 10 after
6264 } 6266 }
6265 6267
6266 6268
6267 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) { 6269 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) {
6268 // Instruction is eliminated when translating to SSA. 6270 // Instruction is eliminated when translating to SSA.
6269 UNREACHABLE(); 6271 UNREACHABLE();
6270 } 6272 }
6271 6273
6272 6274
6273 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) { 6275 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) {
6274 ASSERT(Token::IsEqualityOperator(instr->kind())); 6276 instr->comparison()->Accept(this);
6275 6277 const Object& value = instr->comparison()->constant_value();
6276 const Object& left = instr->left()->definition()->constant_value(); 6278 if (IsNonConstant(value)) {
6277 const Object& right = instr->right()->definition()->constant_value(); 6279 SetValue(instr, non_constant_);
6278 6280 } else if (IsConstant(value)) {
6279 if (IsNonConstant(left) || IsNonConstant(right)) { 6281 ASSERT(value.IsBool());
Kevin Millikin (Google) 2013/11/22 14:09:34 Probably should assert that it's also not IsNull()
6280 // TODO(vegorov): incorporate nullability information into the lattice. 6282 bool result = Bool::Cast(value).value();
6281 if ((left.IsNull() && instr->right()->Type()->HasDecidableNullability()) || 6283 SetValue(instr,
6282 (right.IsNull() && instr->left()->Type()->HasDecidableNullability())) { 6284 Smi::Handle(Smi::New(
6283 bool result = left.IsNull() ? instr->right()->Type()->IsNull() 6285 result ? instr->if_true() : instr->if_false())));
6284 : instr->left()->Type()->IsNull();
6285 if (instr->kind() == Token::kNE_STRICT ||
6286 instr->kind() == Token::kNE) {
6287 result = !result;
6288 }
6289 SetValue(instr, Smi::Handle(
6290 Smi::New(result ? instr->if_true() : instr->if_false())));
6291 } else {
6292 SetValue(instr, non_constant_);
6293 }
6294 } else if (IsConstant(left) && IsConstant(right)) {
6295 bool result = (left.raw() == right.raw());
6296 if (instr->kind() == Token::kNE_STRICT ||
6297 instr->kind() == Token::kNE) {
6298 result = !result;
6299 }
6300 SetValue(instr, Smi::Handle(
6301 Smi::New(result ? instr->if_true() : instr->if_false())));
6302 } 6286 }
6303 } 6287 }
6304 6288
6305 6289
6306 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) { 6290 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) {
6307 const Object& left = instr->left()->definition()->constant_value(); 6291 const Object& left = instr->left()->definition()->constant_value();
6308 const Object& right = instr->right()->definition()->constant_value(); 6292 const Object& right = instr->right()->definition()->constant_value();
6309 6293
6310 if (instr->left()->definition() == instr->right()->definition()) { 6294 if (instr->left()->definition() == instr->right()->definition()) {
6311 // Fold x === x, and x !== x to true/false. 6295 // Fold x === x, and x !== x to true/false.
(...skipping 1043 matching lines...) Expand 10 before | Expand all | Expand 10 after
7355 new JoinEntryInstr(target->block_id(), target->try_index()); 7339 new JoinEntryInstr(target->block_id(), target->try_index());
7356 join->InheritDeoptTarget(target); 7340 join->InheritDeoptTarget(target);
7357 join->LinkTo(target->next()); 7341 join->LinkTo(target->next());
7358 join->set_last_instruction(target->last_instruction()); 7342 join->set_last_instruction(target->last_instruction());
7359 target->UnuseAllInputs(); 7343 target->UnuseAllInputs();
7360 return join; 7344 return join;
7361 } 7345 }
7362 7346
7363 7347
7364 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch, 7348 BranchInstr* BranchSimplifier::CloneBranch(BranchInstr* branch,
7365 Value* left, 7349 Value* new_left,
7366 Value* right) { 7350 Value* new_right) {
7367 ComparisonInstr* comparison = branch->comparison(); 7351 ComparisonInstr* comparison = branch->comparison();
7368 ComparisonInstr* new_comparison = NULL; 7352 ComparisonInstr* new_comparison =
7369 if (comparison->IsStrictCompare()) { 7353 comparison->CopyWithNewOperands(new_left, new_right);
7370 new_comparison = new StrictCompareInstr(comparison->token_pos(),
7371 comparison->kind(),
7372 left,
7373 right);
7374 } else if (comparison->IsEqualityCompare()) {
7375 EqualityCompareInstr* equality_compare = comparison->AsEqualityCompare();
7376 EqualityCompareInstr* new_equality_compare =
7377 new EqualityCompareInstr(equality_compare->token_pos(),
7378 comparison->kind(),
7379 left,
7380 right,
7381 equality_compare->operation_cid(),
7382 equality_compare->deopt_id());
7383 new_comparison = new_equality_compare;
7384 } else {
7385 ASSERT(comparison->IsRelationalOp());
7386 RelationalOpInstr* relational_op = comparison->AsRelationalOp();
7387 RelationalOpInstr* new_relational_op =
7388 new RelationalOpInstr(relational_op->token_pos(),
7389 comparison->kind(),
7390 left,
7391 right,
7392 relational_op->operation_cid(),
7393 relational_op->deopt_id());
7394 new_comparison = new_relational_op;
7395 }
7396 return new BranchInstr(new_comparison, branch->is_checked()); 7354 return new BranchInstr(new_comparison, branch->is_checked());
7397 } 7355 }
7398 7356
7399 7357
7400 void BranchSimplifier::Simplify(FlowGraph* flow_graph) { 7358 void BranchSimplifier::Simplify(FlowGraph* flow_graph) {
7401 // Optimize some branches that test the value of a phi. When it is safe 7359 // Optimize some branches that test the value of a phi. When it is safe
7402 // to do so, push the branch to each of the predecessor blocks. This is 7360 // to do so, push the branch to each of the predecessor blocks. This is
7403 // an optimization when (a) it can avoid materializing a boolean object at 7361 // an optimization when (a) it can avoid materializing a boolean object at
7404 // the phi only to test its value, and (b) it can expose opportunities for 7362 // the phi only to test its value, and (b) it can expose opportunities for
7405 // constant propagation and unreachable code elimination. This 7363 // constant propagation and unreachable code elimination. This
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
7597 BranchInstr* branch = pred->last_instruction()->AsBranch(); 7555 BranchInstr* branch = pred->last_instruction()->AsBranch();
7598 ComparisonInstr* comparison = branch->comparison(); 7556 ComparisonInstr* comparison = branch->comparison();
7599 7557
7600 // Check if the platform supports efficient branchless IfThenElseInstr 7558 // Check if the platform supports efficient branchless IfThenElseInstr
7601 // for the given combination of comparison and values flowing from 7559 // for the given combination of comparison and values flowing from
7602 // false and true paths. 7560 // false and true paths.
7603 if (IfThenElseInstr::Supports(comparison, v1, v2)) { 7561 if (IfThenElseInstr::Supports(comparison, v1, v2)) {
7604 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2; 7562 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2;
7605 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2; 7563 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2;
7606 7564
7565 ComparisonInstr* new_comparison =
7566 comparison->CopyWithNewOperands(comparison->left()->Copy(),
7567 comparison->right()->Copy());
7607 IfThenElseInstr* if_then_else = new IfThenElseInstr( 7568 IfThenElseInstr* if_then_else = new IfThenElseInstr(
7608 comparison->kind(), 7569 new_comparison,
7609 comparison->InputAt(0)->Copy(),
7610 comparison->InputAt(1)->Copy(),
7611 if_true->Copy(), 7570 if_true->Copy(),
7612 if_false->Copy()); 7571 if_false->Copy());
7613 flow_graph->InsertBefore(branch, 7572 flow_graph->InsertBefore(branch,
7614 if_then_else, 7573 if_then_else,
7615 NULL, 7574 NULL,
7616 Definition::kValue); 7575 Definition::kValue);
7617 7576
7618 phi->ReplaceUsesWith(if_then_else); 7577 phi->ReplaceUsesWith(if_then_else);
7619 7578
7620 // Connect IfThenElseInstr to the first instruction in the merge block 7579 // Connect IfThenElseInstr to the first instruction in the merge block
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
7912 } 7871 }
7913 7872
7914 // Insert materializations at environment uses. 7873 // Insert materializations at environment uses.
7915 for (intptr_t i = 0; i < exits.length(); i++) { 7874 for (intptr_t i = 0; i < exits.length(); i++) {
7916 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); 7875 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
7917 } 7876 }
7918 } 7877 }
7919 7878
7920 7879
7921 } // namespace dart 7880 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698