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

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

Issue 10960014: Implement range analysis for smi values. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: cleanup Created 8 years, 3 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/hash_map.h" 10 #include "vm/hash_map.h"
(...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after
1027 HandleEqualityCompare(this, comparison->AsEqualityCompare(), instr, 1027 HandleEqualityCompare(this, comparison->AsEqualityCompare(), instr,
1028 current_iterator()); 1028 current_iterator());
1029 } else { 1029 } else {
1030 ASSERT(comparison->IsStrictCompare()); 1030 ASSERT(comparison->IsStrictCompare());
1031 // Nothing to do. 1031 // Nothing to do.
1032 } 1032 }
1033 } 1033 }
1034 1034
1035 1035
1036 // SminessPropagator ensures that CheckSmis are eliminated across phis. 1036 // SminessPropagator ensures that CheckSmis are eliminated across phis.
1037 class SminessPropagator { 1037 class SminessPropagator : public ValueObject {
1038 public: 1038 public:
1039 explicit SminessPropagator(FlowGraph* flow_graph) 1039 explicit SminessPropagator(FlowGraph* flow_graph)
1040 : flow_graph_(flow_graph), 1040 : flow_graph_(flow_graph),
1041 known_smis_(new BitVector(flow_graph_->current_ssa_temp_index())), 1041 known_smis_(new BitVector(flow_graph_->current_ssa_temp_index())),
1042 rollback_checks_(10), 1042 rollback_checks_(10),
1043 in_worklist_(NULL), 1043 in_worklist_(NULL),
1044 worklist_(0) { } 1044 worklist_(0) { }
1045 1045
1046 void Propagate(); 1046 void Propagate();
1047 1047
1048 private: 1048 private:
1049 void PropagateSminessRecursive(BlockEntryInstr* block); 1049 void PropagateSminessRecursive(BlockEntryInstr* block);
1050 void AddToWorklist(PhiInstr* phi); 1050 void AddToWorklist(PhiInstr* phi);
1051 PhiInstr* RemoveLastFromWorklist(); 1051 PhiInstr* RemoveLastFromWorklist();
1052 void ProcessPhis(); 1052 void ProcessPhis();
1053 1053
1054 FlowGraph* flow_graph_; 1054 FlowGraph* flow_graph_;
1055 1055
1056 BitVector* known_smis_; 1056 BitVector* known_smis_;
1057 GrowableArray<intptr_t> rollback_checks_; 1057 GrowableArray<intptr_t> rollback_checks_;
1058 1058
1059 BitVector* in_worklist_; 1059 BitVector* in_worklist_;
1060 GrowableArray<PhiInstr*> worklist_; 1060 GrowableArray<PhiInstr*> worklist_;
1061
1062 DISALLOW_COPY_AND_ASSIGN(SminessPropagator);
1061 }; 1063 };
1062 1064
1063 1065
1064 void SminessPropagator::AddToWorklist(PhiInstr* phi) { 1066 void SminessPropagator::AddToWorklist(PhiInstr* phi) {
1065 if (in_worklist_ == NULL) { 1067 if (in_worklist_ == NULL) {
1066 in_worklist_ = new BitVector(flow_graph_->current_ssa_temp_index()); 1068 in_worklist_ = new BitVector(flow_graph_->current_ssa_temp_index());
1067 } 1069 }
1068 if (!in_worklist_->Contains(phi->ssa_temp_index())) { 1070 if (!in_worklist_->Contains(phi->ssa_temp_index())) {
1069 in_worklist_->Add(phi->ssa_temp_index()); 1071 in_worklist_->Add(phi->ssa_temp_index());
1070 worklist_.Add(phi); 1072 worklist_.Add(phi);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 ProcessPhis(); 1199 ProcessPhis();
1198 } 1200 }
1199 1201
1200 1202
1201 void FlowGraphOptimizer::PropagateSminess() { 1203 void FlowGraphOptimizer::PropagateSminess() {
1202 SminessPropagator propagator(flow_graph_); 1204 SminessPropagator propagator(flow_graph_);
1203 propagator.Propagate(); 1205 propagator.Propagate();
1204 } 1206 }
1205 1207
1206 1208
1209 // Range analysis for smi values.
1210 class RangeAnalysis : public ValueObject {
1211 public:
1212 explicit RangeAnalysis(FlowGraph* flow_graph) : flow_graph_(flow_graph) { }
1213
1214 // Infer ranges for all values and remove overflow checks from binary smi
1215 // operations when proven redundant.
1216 void Analyze();
1217
1218 private:
1219 // Collect all values that were proven to be smi in smi_values_ array and all
1220 // CheckSmi instructions in smi_check_ array.
1221 void CollectSmiValues();
1222
1223 // Iterate over smi values and constraint them at branch successors.
Kevin Millikin (Google) 2012/09/21 08:59:33 constraint ==> constrain wherever used as a verb.
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1224 // Additionally constraint values after CheckSmi instructions.
1225 void InsertConstraints();
1226
1227 // Iterate over uses of the given definition and discover branches that
1228 // constraint it. Insert appropriate Constraint instructions at true
1229 // and false successor and rename all dominated uses to refer to a
1230 // Constraint instead of this definition.
1231 void InsertConstraintsFor(Definition* defn);
1232
1233 // Create a constraint for defn, insert it after given instruction and
1234 // rename all uses that are dominated by it.
1235 ConstraintInstr* ConstraintValue(Definition* defn,
Kevin Millikin (Google) 2012/09/21 08:59:33 ConstraintValue ==> ConstrainValue
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1236 Range* constraint,
1237 Instruction* after);
1238
1239 // Replace uses of the definition def that are dominated by instruction dom
1240 // with uses of other definition.
1241 void RenameDominatedUses(Definition* def,
1242 Instruction* dom,
1243 Definition* other);
1244
1245 // Propagate range information until fix-point is reached.
1246 void InferRanges();
1247
1248 // Walk the dominator tree, initialize ranges for smi values and place them
1249 // to the worklist.
1250 void InitializeRangesRecursive(BlockEntryInstr* block);
1251
1252 // Remove artificial Constraint instructions and replace them with actual
1253 // unconstrained definitions.
1254 void RemoveConstraints();
1255
1256 void CreateWorklists();
1257
1258 void AddToWorklist(Definition* value) {
1259 const intptr_t index = value->ssa_temp_index();
1260 if (!in_inactive_worklist_->Contains(index)) {
1261 in_inactive_worklist_->Add(index);
1262 inactive_worklist_->Add(value);
1263 }
1264 }
1265
1266 bool IsWorklistEmpty() const {
1267 return active_worklist_->is_empty();
1268 }
1269
1270 void SwapWorklists();
1271
1272 FlowGraph* flow_graph_;
1273
1274 GrowableArray<Definition*> smi_values_; // Value that are known to be smi.
1275 GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions.
1276
1277 // All Constraints inserted during InsertConstraints phase. They are treated
1278 // as smi values.
1279 GrowableArray<ConstraintInstr*> constraints_;
1280
1281 // Bitvector for a quick filtering of known smi values.
1282 BitVector* smi_definitions_;
1283
1284 // Worklists using during range propagation.
1285 ZoneGrowableArray<Definition*>* active_worklist_;
1286 ZoneGrowableArray<Definition*>* inactive_worklist_;
1287 BitVector* in_inactive_worklist_;
1288
1289 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis);
1290 };
1291
1292
1293 void RangeAnalysis::Analyze() {
1294 CollectSmiValues();
1295 InsertConstraints();
1296 InferRanges();
1297 RemoveConstraints();
1298 }
1299
1300
1301 void RangeAnalysis::CollectSmiValues() {
Kevin Millikin (Google) 2012/09/21 08:59:33 It seems more straightforward to directly insert c
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Agreed. I am going to commit as is and refactor it
1302 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
1303 !block_it.Done();
1304 block_it.Advance()) {
1305 BlockEntryInstr* block = block_it.Current();
1306 for (ForwardInstructionIterator instr_it(block);
1307 !instr_it.Done();
1308 instr_it.Advance()) {
1309 Instruction* current = instr_it.Current();
1310 Definition* defn = current->AsDefinition();
1311 if (defn != NULL) {
1312 if (defn->GetPropagatedCid() == kSmiCid) smi_values_.Add(defn);
1313 } else if (current->IsCheckSmi()) {
1314 smi_checks_.Add(current->AsCheckSmi());
1315 }
1316 }
1317
1318 JoinEntryInstr* join = block->AsJoinEntry();
1319 if (join != NULL) {
1320 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
1321 PhiInstr* current = phi_it.Current();
1322 if (current->GetPropagatedCid() == kSmiCid) {
1323 smi_values_.Add(current);
1324 }
1325 }
1326 }
1327 }
1328 }
1329
1330
1331 // Returns true if use is dominated by the given instruction.
1332 // Note: uses that occur at instruction itself are not dominated by it.
1333 static bool IsDominatedUse(Instruction* dom, Value* use) {
1334 BlockEntryInstr* dom_block = dom->GetBlock();
1335
1336 Instruction* instr = use->instruction();
1337
1338 PhiInstr* phi = instr->AsPhi();
1339 if (phi != NULL) {
1340 return dom_block->Dominates(phi->block()->PredecessorAt(use->use_index()));
1341 }
1342
1343 BlockEntryInstr* use_block = instr->GetBlock();
1344 if (use_block == dom_block) {
1345 // Fast path for the case of block entry.
1346 if (dom_block == dom) return true;
1347
1348 for (Instruction* curr = dom->next(); curr != NULL; curr = curr->next()) {
1349 if (curr == instr) return true;
1350 }
1351
1352 return false;
1353 }
1354
1355 return dom_block->Dominates(use_block);
1356 }
1357
1358
1359 void RangeAnalysis::RenameDominatedUses(Definition* def,
1360 Instruction* dom,
1361 Definition* other) {
1362 Value* next_use = NULL;
1363 Value* prev_use = NULL;
1364 for (Value* use = def->input_use_list();
1365 use != NULL;
1366 use = next_use) {
1367 next_use = use->next_use();
1368
1369 // Skip instructions that are outside of the graph and
1370 // dead phis.
1371 if (use->instruction()->WasEliminated() &&
Florian Schneider 2012/09/21 08:56:44 Why do you need to skip those?
Kevin Millikin (Google) 2012/09/21 08:59:33 Can live phis be WasEliminated? That's weird.
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 I don't want to compute ranges for things that are
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Our WasEliminated check just checks if previous()
1372 !(use->instruction()->IsPhi() &&
1373 use->instruction()->AsPhi()->is_alive())) {
1374 prev_use = use;
1375 continue;
1376 }
1377
1378 if (IsDominatedUse(dom, use)) {
1379 if (prev_use != NULL) {
1380 prev_use->set_next_use(next_use);
1381 } else {
1382 def->set_input_use_list(next_use);
1383 }
1384 use->set_definition(other);
1385 use->AddToInputUseList();
1386 } else {
1387 prev_use = use;
1388 }
1389 }
1390 }
1391
1392
1393 // For a comparison operation return an operation for the equivalent flipped
1394 // comparison: a (op) b === b (op') a.
1395 static Token::Kind FlipComparison(Token::Kind op) {
1396 switch (op) {
1397 case Token::kEQ: return Token::kEQ;
1398 case Token::kNE: return Token::kNE;
1399 case Token::kLT: return Token::kGT;
1400 case Token::kGT: return Token::kLT;
1401 case Token::kLTE: return Token::kGTE;
1402 case Token::kGTE: return Token::kLTE;
1403 default:
1404 UNREACHABLE();
1405 return Token::kILLEGAL;
1406 }
1407 }
1408
1409 // For a comparison operation return an operation for the negated comparison:
1410 // !(a (op) b) === a (op') b
1411 static Token::Kind NegateComparison(Token::Kind op) {
1412 switch (op) {
1413 case Token::kEQ: return Token::kNE;
1414 case Token::kNE: return Token::kEQ;
1415 case Token::kLT: return Token::kGTE;
1416 case Token::kGT: return Token::kLTE;
1417 case Token::kLTE: return Token::kGT;
1418 case Token::kGTE: return Token::kLT;
1419 default:
1420 UNREACHABLE();
1421 return Token::kILLEGAL;
1422 }
1423 }
1424
1425
1426 // Given a boundary (right operand) and a comparison operation return
1427 // a symbolic range constraint for the left operand of the comparison assuming
1428 // that it evaluated to true.
1429 // For example for the comparison a < b symbol a is constrained with range
1430 // [Smi::kMinValue, b - 1].
1431 static Range* ConstraintRange(Token::Kind op, Definition* boundary) {
1432 switch (op) {
1433 case Token::kEQ:
1434 return new Range(RangeBoundary::FromDefinition(boundary),
1435 RangeBoundary::FromDefinition(boundary));
1436 case Token::kNE:
1437 return Range::Unknown();
1438 case Token::kLT:
1439 return new Range(RangeBoundary::MinSmi(),
1440 RangeBoundary::FromDefinition(boundary, -1));
1441 case Token::kGT:
1442 return new Range(RangeBoundary::FromDefinition(boundary, 1),
1443 RangeBoundary::MaxSmi());
1444 case Token::kLTE:
1445 return new Range(RangeBoundary::MinSmi(),
1446 RangeBoundary::FromDefinition(boundary));
1447 case Token::kGTE:
1448 return new Range(RangeBoundary::FromDefinition(boundary),
1449 RangeBoundary::MaxSmi());
1450 default:
1451 UNREACHABLE();
1452 return Range::Unknown();
1453 }
1454 }
1455
1456
1457 ConstraintInstr* RangeAnalysis::ConstraintValue(Definition* defn,
Florian Schneider 2012/09/21 08:56:44 Suggested better name: InsertConstraintFor
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1458 Range* constraint_range,
1459 Instruction* after) {
Florian Schneider 2012/09/21 08:56:44 Maybe assert that Definition defn dominates Instru
1460 // No need to constraint constants.
Florian Schneider 2012/09/21 08:56:44 s/constraint/constrain/
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1461 if (defn->IsConstant()) return NULL;
1462
1463 ConstraintInstr* constraint =
1464 new ConstraintInstr(new Value(defn), constraint_range);
1465 constraint->InsertAfter(after);
1466 constraint->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
1467 RenameDominatedUses(defn, after, constraint);
1468 constraints_.Add(constraint);
1469 constraint->value()->set_instruction(constraint);
1470 constraint->value()->set_use_index(0);
1471 constraint->value()->AddToInputUseList();
1472 return constraint;
1473 }
1474
1475
1476 void RangeAnalysis::InsertConstraintsFor(Definition* defn) {
1477 for (Value* use = defn->input_use_list();
1478 use != NULL;
1479 use = use->next_use()) {
1480 if (use->instruction()->IsBranch()) {
1481 BranchInstr* branch = use->instruction()->AsBranch();
1482 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp();
1483 if ((rel_op != NULL) && (rel_op->operands_class_id() == kSmiCid)) {
1484 // Found comparison of two smis. Constrain defn at true and false
1485 // successors using the other operand as a boundary.
1486 Definition* boundary =
Kevin Millikin (Google) 2012/09/21 08:59:33 Since you test use_index() anyway, it's clearer to
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1487 rel_op->InputAt(1 - use->use_index())->definition();
1488
1489 // ConstraintValue assumes that defn is left operand of a comparison
1490 // if it is right operand flip the comparison.
1491 const Token::Kind op_kind =
1492 (use->use_index() == 0) ? rel_op->kind()
1493 : FlipComparison(rel_op->kind());
1494
1495 // Constrain definition at the true successor.
1496 ConstraintInstr* true_constraint =
1497 ConstraintValue(defn,
1498 ConstraintRange(op_kind, boundary),
1499 branch->true_successor());
1500 // Mark true_constraint an artificial use of boundary. This ensures
1501 // that constraints range is recalculated if boundary's range changes.
1502 if (true_constraint != NULL) true_constraint->AddDependency(boundary);
1503
1504 // Constrain definition with a negated condition at the false successor.
1505 ConstraintInstr* false_constraint =
1506 ConstraintValue(
1507 defn,
1508 ConstraintRange(NegateComparison(op_kind), boundary),
1509 branch->false_successor());
1510 // Mark false_constraint an artificial use of boundary. This ensures
1511 // that constraints range is recalculated if boundary's range changes.
1512 if (false_constraint != NULL) false_constraint->AddDependency(boundary);
1513 }
1514 }
1515 }
1516 }
1517
1518
1519 void RangeAnalysis::InsertConstraints() {
1520 for (intptr_t i = 0; i < smi_checks_.length(); i++) {
1521 CheckSmiInstr* check = smi_checks_[i];
1522 ConstraintInstr* constraint =
1523 ConstraintValue(check->value()->definition(),
1524 Range::Unknown(),
1525 check);
1526 InsertConstraintsFor(constraint); // Constraint uses further.
1527 }
1528
1529 for (intptr_t i = 0; i < smi_values_.length(); i++) {
1530 InsertConstraintsFor(smi_values_[i]);
1531 }
1532 }
1533
1534
1535 void RangeAnalysis::InitializeRangesRecursive(BlockEntryInstr* block) {
1536 JoinEntryInstr* join = block->AsJoinEntry();
Kevin Millikin (Google) 2012/09/21 08:59:33 It also seems like we could do this in the same wa
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 See above comment. I am going to commit as is now.
1537 if ((join != NULL) && (join->phis() != NULL)) {
1538 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
1539 PhiInstr* phi = (*join->phis())[i];
1540 if (phi == NULL) continue;
1541 if (smi_definitions_->Contains(phi->ssa_temp_index())) {
1542 phi->InferRange();
1543 AddToWorklist(phi);
1544 }
1545 }
1546 }
1547
1548 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1549 Definition* defn = it.Current()->AsDefinition();
1550 if ((defn != NULL) &&
1551 (defn->ssa_temp_index() != -1) &&
1552 smi_definitions_->Contains(defn->ssa_temp_index())) {
1553 defn->InferRange();
1554 AddToWorklist(defn);
1555 }
1556 }
1557
1558 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
1559 InitializeRangesRecursive(block->dominated_blocks()[i]);
1560 }
1561 }
1562
1563
1564 void RangeAnalysis::CreateWorklists() {
1565 active_worklist_ = new ZoneGrowableArray<Definition*>(10);
1566 inactive_worklist_ = new ZoneGrowableArray<Definition*>(10);
1567 in_inactive_worklist_ = new BitVector(
1568 flow_graph_->current_ssa_temp_index());
1569 }
1570
1571
1572 void RangeAnalysis::SwapWorklists() {
1573 ZoneGrowableArray<Definition*>* temp = active_worklist_;
1574 active_worklist_ = inactive_worklist_;
1575 inactive_worklist_ = temp;
1576 inactive_worklist_->Clear();
Kevin Millikin (Google) 2012/09/21 08:59:33 This worklist is assumed empty here, right?
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 We don't pop anything from the worklist. We just p
1577 in_inactive_worklist_->Clear();
1578 }
1579
1580
1581 void RangeAnalysis::InferRanges() {
1582 CreateWorklists();
1583
1584 // Initialize bitvector for quick filtering of smi values.
1585 smi_definitions_ = new BitVector(flow_graph_->current_ssa_temp_index());
1586 for (intptr_t i = 0; i < smi_values_.length(); i++) {
1587 smi_definitions_->Add(smi_values_[i]->ssa_temp_index());
1588 }
1589 for (intptr_t i = 0; i < constraints_.length(); i++) {
1590 smi_definitions_->Add(constraints_[i]->ssa_temp_index());
1591 }
1592
1593 // Infer initial values of ranges.
1594 InitializeRangesRecursive(flow_graph_->graph_entry());
1595
1596 // Active worklist is empty, inactive now contains all smi values.
1597 SwapWorklists();
1598
1599 // Iterate until fix point is reached.
1600 while (!IsWorklistEmpty()) {
1601 for (intptr_t i = 0; i < active_worklist_->length(); i++) {
1602 Definition* defn = (*active_worklist_)[i];
1603 if (defn->InferRange()) { // Update the range.
1604 // Range change. Place all uses to the worklist.
1605 for (Value* use = defn->input_use_list();
1606 use != NULL;
1607 use = use->next_use()) {
1608 Definition* use_defn = use->instruction()->AsDefinition();
1609 if ((use_defn != NULL) &&
1610 (use_defn->ssa_temp_index() != -1) &&
Florian Schneider 2012/09/21 08:56:44 Can we still have a Definition with an ssa_index =
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Yes, unfortunately we do. For example StoreIndexed
1611 smi_definitions_->Contains(use_defn->ssa_temp_index())) {
1612 AddToWorklist(use_defn);
Kevin Millikin (Google) 2012/09/21 08:59:33 The operation of the worklist is not clear. Here
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Worklist contains definition for which InferRange
1613 }
1614 }
1615 }
1616 }
1617
1618 // Active worklist has been processed. Inactive contains all values which
1619 // can be affected by changed ranges.
1620 SwapWorklists();
1621 }
1622 }
1623
1624
1625 void RangeAnalysis::RemoveConstraints() {
1626 for (intptr_t i = 0; i < constraints_.length(); i++) {
1627 Definition* def = constraints_[i]->value()->definition();
1628 // Some constraints might be constraining constraints. Unwind the chain of
1629 // constraints until
Florian Schneider 2012/09/21 08:56:44 Until what?
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
1630 while (def->IsConstraint()) {
1631 def = def->AsConstraint()->value()->definition();
1632 }
1633 constraints_[i]->ReplaceUsesWith(def);
1634 constraints_[i]->RemoveDependency();
1635 constraints_[i]->RemoveFromGraph();
1636 }
1637 }
1638
1639
1640 void FlowGraphOptimizer::InferSmiRanges() {
1641 RangeAnalysis range_analysis(flow_graph_);
1642 range_analysis.Analyze();
1643 }
1644
1645
1207 void FlowGraphTypePropagator::VisitBlocks() { 1646 void FlowGraphTypePropagator::VisitBlocks() {
1208 ASSERT(current_iterator_ == NULL); 1647 ASSERT(current_iterator_ == NULL);
1209 for (intptr_t i = 0; i < block_order_.length(); ++i) { 1648 for (intptr_t i = 0; i < block_order_.length(); ++i) {
1210 BlockEntryInstr* entry = block_order_[i]; 1649 BlockEntryInstr* entry = block_order_[i];
1211 entry->Accept(this); 1650 entry->Accept(this);
1212 ForwardInstructionIterator it(entry); 1651 ForwardInstructionIterator it(entry);
1213 current_iterator_ = &it; 1652 current_iterator_ = &it;
1214 for (; !it.Done(); it.Advance()) { 1653 for (; !it.Done(); it.Advance()) {
1215 Instruction* current = it.Current(); 1654 Instruction* current = it.Current();
1216 // No need to propagate the input types of the instruction, as long as 1655 // No need to propagate the input types of the instruction, as long as
(...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2317 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { 2756 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {
2318 // Nothing to do. Has no value. 2757 // Nothing to do. Has no value.
2319 } 2758 }
2320 2759
2321 2760
2322 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { 2761 void ConstantPropagator::VisitConstant(ConstantInstr* instr) {
2323 SetValue(instr, instr->value()); 2762 SetValue(instr, instr->value());
2324 } 2763 }
2325 2764
2326 2765
2766 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) {
2767 // Nothing to do. Is not used outside of range analysis.
Florian Schneider 2012/09/21 08:56:44 Maybe also make it UNREACHABLE()?
Vyacheslav Egorov (Google) 2012/09/21 20:08:07 Done.
2768 }
2769
2770
2327 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) { 2771 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) {
2328 // Nothing to do. Not a value. 2772 // Nothing to do. Not a value.
2329 } 2773 }
2330 2774
2331 2775
2332 void ConstantPropagator::VisitUnboxedDoubleBinaryOp( 2776 void ConstantPropagator::VisitUnboxedDoubleBinaryOp(
2333 UnboxedDoubleBinaryOpInstr* instr) { 2777 UnboxedDoubleBinaryOpInstr* instr) {
2334 const Object& left = instr->left()->definition()->constant_value(); 2778 const Object& left = instr->left()->definition()->constant_value();
2335 const Object& right = instr->right()->definition()->constant_value(); 2779 const Object& right = instr->right()->definition()->constant_value();
2336 if (IsNonConstant(left) || IsNonConstant(right)) { 2780 if (IsNonConstant(left) || IsNonConstant(right)) {
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
2488 it.Advance()) { 2932 it.Advance()) {
2489 JoinEntryInstr* join = it.Current()->AsJoinEntry(); 2933 JoinEntryInstr* join = it.Current()->AsJoinEntry();
2490 if (join != NULL) join->EliminateUnreachablePhiInputs(); 2934 if (join != NULL) join->EliminateUnreachablePhiInputs();
2491 } 2935 }
2492 2936
2493 graph_->ComputeUseLists(); 2937 graph_->ComputeUseLists();
2494 } 2938 }
2495 2939
2496 2940
2497 } // namespace dart 2941 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698