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

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: addressed majority of comments 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 constrain them at branch successors.
1224 // Additionally constraint values after CheckSmi instructions.
1225 void InsertConstraints();
1226
1227 // Iterate over uses of the given definition and discover branches that
1228 // constrain 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* InsertConstraintFor(Definition* defn,
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.
ngeoffray 2012/09/24 21:44:15 using -> used
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() {
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 dead phis.
1370 if (use->instruction()->IsPhi() &&
1371 !use->instruction()->AsPhi()->is_alive()) {
1372 prev_use = use;
1373 continue;
1374 }
1375
1376 if (IsDominatedUse(dom, use)) {
1377 if (prev_use != NULL) {
1378 prev_use->set_next_use(next_use);
1379 } else {
1380 def->set_input_use_list(next_use);
1381 }
1382 use->set_definition(other);
1383 use->AddToInputUseList();
1384 } else {
1385 prev_use = use;
1386 }
1387 }
1388 }
1389
1390
1391 // For a comparison operation return an operation for the equivalent flipped
1392 // comparison: a (op) b === b (op') a.
1393 static Token::Kind FlipComparison(Token::Kind op) {
1394 switch (op) {
1395 case Token::kEQ: return Token::kEQ;
1396 case Token::kNE: return Token::kNE;
1397 case Token::kLT: return Token::kGT;
1398 case Token::kGT: return Token::kLT;
1399 case Token::kLTE: return Token::kGTE;
1400 case Token::kGTE: return Token::kLTE;
1401 default:
1402 UNREACHABLE();
1403 return Token::kILLEGAL;
1404 }
1405 }
1406
1407 // For a comparison operation return an operation for the negated comparison:
1408 // !(a (op) b) === a (op') b
1409 static Token::Kind NegateComparison(Token::Kind op) {
1410 switch (op) {
1411 case Token::kEQ: return Token::kNE;
1412 case Token::kNE: return Token::kEQ;
1413 case Token::kLT: return Token::kGTE;
1414 case Token::kGT: return Token::kLTE;
1415 case Token::kLTE: return Token::kGT;
1416 case Token::kGTE: return Token::kLT;
1417 default:
1418 UNREACHABLE();
1419 return Token::kILLEGAL;
1420 }
1421 }
1422
1423
1424 // Given a boundary (right operand) and a comparison operation return
1425 // a symbolic range constraint for the left operand of the comparison assuming
1426 // that it evaluated to true.
1427 // For example for the comparison a < b symbol a is constrained with range
1428 // [Smi::kMinValue, b - 1].
1429 static Range* ConstraintRange(Token::Kind op, Definition* boundary) {
1430 switch (op) {
1431 case Token::kEQ:
1432 return new Range(RangeBoundary::FromDefinition(boundary),
1433 RangeBoundary::FromDefinition(boundary));
1434 case Token::kNE:
1435 return Range::Unknown();
1436 case Token::kLT:
1437 return new Range(RangeBoundary::MinSmi(),
1438 RangeBoundary::FromDefinition(boundary, -1));
1439 case Token::kGT:
1440 return new Range(RangeBoundary::FromDefinition(boundary, 1),
1441 RangeBoundary::MaxSmi());
1442 case Token::kLTE:
1443 return new Range(RangeBoundary::MinSmi(),
1444 RangeBoundary::FromDefinition(boundary));
1445 case Token::kGTE:
1446 return new Range(RangeBoundary::FromDefinition(boundary),
1447 RangeBoundary::MaxSmi());
1448 default:
1449 UNREACHABLE();
1450 return Range::Unknown();
1451 }
1452 }
1453
1454
1455 ConstraintInstr* RangeAnalysis::InsertConstraintFor(Definition* defn,
1456 Range* constraint_range,
ngeoffray 2012/09/24 21:44:15 Weird indentation.
1457 Instruction* after) {
1458 // No need to constrain constants.
1459 if (defn->IsConstant()) return NULL;
1460
1461 ConstraintInstr* constraint =
1462 new ConstraintInstr(new Value(defn), constraint_range);
1463 constraint->InsertAfter(after);
1464 constraint->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
1465 RenameDominatedUses(defn, after, constraint);
1466 constraints_.Add(constraint);
1467 constraint->value()->set_instruction(constraint);
1468 constraint->value()->set_use_index(0);
1469 constraint->value()->AddToInputUseList();
1470 return constraint;
1471 }
1472
1473
1474 void RangeAnalysis::InsertConstraintsFor(Definition* defn) {
1475 for (Value* use = defn->input_use_list();
1476 use != NULL;
1477 use = use->next_use()) {
1478 if (use->instruction()->IsBranch()) {
1479 BranchInstr* branch = use->instruction()->AsBranch();
1480 RelationalOpInstr* rel_op = branch->comparison()->AsRelationalOp();
1481 if ((rel_op != NULL) && (rel_op->operands_class_id() == kSmiCid)) {
1482 // Found comparison of two smis. Constrain defn at true and false
1483 // successors using the other operand as a boundary.
1484 Definition* boundary;
1485 Token::Kind op_kind;
1486 if (use->use_index() == 0) { // Left operand.
1487 boundary = rel_op->InputAt(1)->definition();
1488 op_kind = rel_op->kind();
1489 } else {
1490 ASSERT(use->use_index() == 1); // Right operand.
1491 boundary = rel_op->InputAt(0)->definition();
1492 // InsertConstraintFor assumes that defn is left operand of a
1493 // comparison if it is right operand flip the comparison.
1494 op_kind = FlipComparison(rel_op->kind());
1495 }
1496
1497 // Constrain definition at the true successor.
1498 ConstraintInstr* true_constraint =
1499 InsertConstraintFor(defn,
1500 ConstraintRange(op_kind, boundary),
1501 branch->true_successor());
1502 // Mark true_constraint an artificial use of boundary. This ensures
1503 // that constraint's range is recalculated if boundary's range changes.
1504 if (true_constraint != NULL) true_constraint->AddDependency(boundary);
1505
1506 // Constrain definition with a negated condition at the false successor.
1507 ConstraintInstr* false_constraint =
1508 InsertConstraintFor(
1509 defn,
1510 ConstraintRange(NegateComparison(op_kind), boundary),
1511 branch->false_successor());
1512 // Mark false_constraint an artificial use of boundary. This ensures
1513 // that constraint's range is recalculated if boundary's range changes.
1514 if (false_constraint != NULL) false_constraint->AddDependency(boundary);
1515 }
1516 }
1517 }
1518 }
1519
1520
1521 void RangeAnalysis::InsertConstraints() {
1522 for (intptr_t i = 0; i < smi_checks_.length(); i++) {
1523 CheckSmiInstr* check = smi_checks_[i];
1524 ConstraintInstr* constraint =
1525 InsertConstraintFor(check->value()->definition(),
1526 Range::Unknown(),
1527 check);
1528 InsertConstraintsFor(constraint); // Constrain uses further.
1529 }
1530
1531 for (intptr_t i = 0; i < smi_values_.length(); i++) {
1532 InsertConstraintsFor(smi_values_[i]);
1533 }
1534 }
1535
1536
1537 void RangeAnalysis::InitializeRangesRecursive(BlockEntryInstr* block) {
1538 JoinEntryInstr* join = block->AsJoinEntry();
1539 if ((join != NULL) && (join->phis() != NULL)) {
1540 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
1541 PhiInstr* phi = (*join->phis())[i];
1542 if (phi == NULL) continue;
1543 if (smi_definitions_->Contains(phi->ssa_temp_index())) {
1544 phi->InferRange();
1545 AddToWorklist(phi);
1546 }
1547 }
1548 }
1549
1550 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1551 Definition* defn = it.Current()->AsDefinition();
1552 if ((defn != NULL) &&
1553 (defn->ssa_temp_index() != -1) &&
1554 smi_definitions_->Contains(defn->ssa_temp_index())) {
1555 defn->InferRange();
1556 AddToWorklist(defn);
1557 }
1558 }
1559
1560 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
1561 InitializeRangesRecursive(block->dominated_blocks()[i]);
1562 }
1563 }
1564
1565
1566 void RangeAnalysis::CreateWorklists() {
1567 active_worklist_ = new ZoneGrowableArray<Definition*>(10);
1568 inactive_worklist_ = new ZoneGrowableArray<Definition*>(10);
1569 in_inactive_worklist_ = new BitVector(
1570 flow_graph_->current_ssa_temp_index());
1571 }
1572
1573
1574 void RangeAnalysis::SwapWorklists() {
1575 ZoneGrowableArray<Definition*>* temp = active_worklist_;
1576 active_worklist_ = inactive_worklist_;
1577 inactive_worklist_ = temp;
1578 inactive_worklist_->Clear();
1579 in_inactive_worklist_->Clear();
1580 }
1581
1582
1583 void RangeAnalysis::InferRanges() {
1584 CreateWorklists();
1585
1586 // Initialize bitvector for quick filtering of smi values.
1587 smi_definitions_ = new BitVector(flow_graph_->current_ssa_temp_index());
1588 for (intptr_t i = 0; i < smi_values_.length(); i++) {
1589 smi_definitions_->Add(smi_values_[i]->ssa_temp_index());
1590 }
1591 for (intptr_t i = 0; i < constraints_.length(); i++) {
1592 smi_definitions_->Add(constraints_[i]->ssa_temp_index());
1593 }
1594
1595 // Infer initial values of ranges.
1596 InitializeRangesRecursive(flow_graph_->graph_entry());
1597
1598 // Active worklist is empty, inactive now contains all smi values.
1599 SwapWorklists();
1600
1601 // Iterate until fix point is reached.
1602 while (!IsWorklistEmpty()) {
1603 for (intptr_t i = 0; i < active_worklist_->length(); i++) {
1604 Definition* defn = (*active_worklist_)[i];
1605 if (defn->InferRange()) { // Update the range.
1606 // Range change. Place all uses to the worklist.
1607 for (Value* use = defn->input_use_list();
1608 use != NULL;
1609 use = use->next_use()) {
1610 Definition* use_defn = use->instruction()->AsDefinition();
1611 if ((use_defn != NULL) &&
1612 (use_defn->ssa_temp_index() != -1) &&
1613 smi_definitions_->Contains(use_defn->ssa_temp_index())) {
1614 AddToWorklist(use_defn);
1615 }
1616 }
1617 }
1618 }
1619
1620 // Active worklist has been processed. Inactive contains all values which
1621 // can be affected by changed ranges.
1622 SwapWorklists();
1623 }
1624 }
1625
1626
1627 void RangeAnalysis::RemoveConstraints() {
1628 for (intptr_t i = 0; i < constraints_.length(); i++) {
1629 Definition* def = constraints_[i]->value()->definition();
1630 // Some constraints might be constraining constraints. Unwind the chain of
1631 // constraints until we reach the actual definition.
1632 while (def->IsConstraint()) {
1633 def = def->AsConstraint()->value()->definition();
1634 }
1635 constraints_[i]->ReplaceUsesWith(def);
1636 constraints_[i]->RemoveDependency();
1637 constraints_[i]->RemoveFromGraph();
1638 }
1639 }
1640
1641
1642 void FlowGraphOptimizer::InferSmiRanges() {
1643 RangeAnalysis range_analysis(flow_graph_);
1644 range_analysis.Analyze();
1645 }
1646
1647
1207 void FlowGraphTypePropagator::VisitBlocks() { 1648 void FlowGraphTypePropagator::VisitBlocks() {
1208 ASSERT(current_iterator_ == NULL); 1649 ASSERT(current_iterator_ == NULL);
1209 for (intptr_t i = 0; i < block_order_.length(); ++i) { 1650 for (intptr_t i = 0; i < block_order_.length(); ++i) {
1210 BlockEntryInstr* entry = block_order_[i]; 1651 BlockEntryInstr* entry = block_order_[i];
1211 entry->Accept(this); 1652 entry->Accept(this);
1212 ForwardInstructionIterator it(entry); 1653 ForwardInstructionIterator it(entry);
1213 current_iterator_ = &it; 1654 current_iterator_ = &it;
1214 for (; !it.Done(); it.Advance()) { 1655 for (; !it.Done(); it.Advance()) {
1215 Instruction* current = it.Current(); 1656 Instruction* current = it.Current();
1216 // No need to propagate the input types of the instruction, as long as 1657 // No need to propagate the input types of the instruction, as long as
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1500 // instruction and set the correct deopt_id. 1941 // instruction and set the correct deopt_id.
1501 ASSERT(last->env() != NULL); 1942 ASSERT(last->env() != NULL);
1502 last->env()->DeepCopyTo(current); 1943 last->env()->DeepCopyTo(current);
1503 current->deopt_id_ = last->GetDeoptId(); 1944 current->deopt_id_ = last->GetDeoptId();
1504 } 1945 }
1505 1946
1506 1947
1507 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it, 1948 void LICM::TryHoistCheckSmiThroughPhi(ForwardInstructionIterator* it,
1508 BlockEntryInstr* header, 1949 BlockEntryInstr* header,
1509 BlockEntryInstr* pre_header, 1950 BlockEntryInstr* pre_header,
1510 Instruction* current) { 1951 CheckSmiInstr* current) {
1511 PhiInstr* phi = current->InputAt(0)->definition()->AsPhi(); 1952 PhiInstr* phi = current->InputAt(0)->definition()->AsPhi();
1512 if (!header->loop_info()->Contains(phi->block()->preorder_number())) { 1953 if (!header->loop_info()->Contains(phi->block()->preorder_number())) {
1513 return; 1954 return;
1514 } 1955 }
1515 1956
1516 if (phi->GetPropagatedCid() == kSmiCid) { 1957 if (phi->GetPropagatedCid() == kSmiCid) {
1517 it->RemoveCurrentFromGraph(); 1958 it->RemoveCurrentFromGraph();
1518 return; 1959 return;
1519 } 1960 }
1520 1961
(...skipping 14 matching lines...) Expand all
1535 } 1976 }
1536 } 1977 }
1537 1978
1538 if ((non_smi_input == kNotFound) || 1979 if ((non_smi_input == kNotFound) ||
1539 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) { 1980 (phi->block()->PredecessorAt(non_smi_input) != pre_header)) {
1540 return; 1981 return;
1541 } 1982 }
1542 1983
1543 // Host CheckSmi instruction and make this phi smi one. 1984 // Host CheckSmi instruction and make this phi smi one.
1544 Hoist(it, pre_header, current); 1985 Hoist(it, pre_header, current);
1545 current->SetInputAt(0, phi->InputAt(non_smi_input)); 1986
1987 // Replace value we are checking with phi's input. Maintain use lists.
1988 Definition* non_smi_input_defn = phi->InputAt(non_smi_input)->definition();
1989 current->value()->RemoveFromInputUseList();
1990 current->value()->set_definition(non_smi_input_defn);
1991 current->value()->AddToInputUseList();
1992
1546 phi->SetPropagatedCid(kSmiCid); 1993 phi->SetPropagatedCid(kSmiCid);
1547 } 1994 }
1548 1995
1549 1996
1550 void LICM::Optimize(FlowGraph* flow_graph) { 1997 void LICM::Optimize(FlowGraph* flow_graph) {
1551 GrowableArray<BlockEntryInstr*> loop_headers; 1998 GrowableArray<BlockEntryInstr*> loop_headers;
1552 flow_graph->ComputeLoops(&loop_headers); 1999 flow_graph->ComputeLoops(&loop_headers);
1553 2000
1554 for (intptr_t i = 0; i < loop_headers.length(); ++i) { 2001 for (intptr_t i = 0; i < loop_headers.length(); ++i) {
1555 BlockEntryInstr* header = loop_headers[i]; 2002 BlockEntryInstr* header = loop_headers[i];
(...skipping 15 matching lines...) Expand all
1571 Definition* input_def = current->InputAt(i)->definition(); 2018 Definition* input_def = current->InputAt(i)->definition();
1572 if (!input_def->GetBlock()->Dominates(pre_header)) { 2019 if (!input_def->GetBlock()->Dominates(pre_header)) {
1573 inputs_loop_invariant = false; 2020 inputs_loop_invariant = false;
1574 break; 2021 break;
1575 } 2022 }
1576 } 2023 }
1577 if (inputs_loop_invariant) { 2024 if (inputs_loop_invariant) {
1578 Hoist(&it, pre_header, current); 2025 Hoist(&it, pre_header, current);
1579 } else if (current->IsCheckSmi() && 2026 } else if (current->IsCheckSmi() &&
1580 current->InputAt(0)->definition()->IsPhi()) { 2027 current->InputAt(0)->definition()->IsPhi()) {
1581 TryHoistCheckSmiThroughPhi(&it, header, pre_header, current); 2028 TryHoistCheckSmiThroughPhi(
2029 &it, header, pre_header, current->AsCheckSmi());
1582 } 2030 }
1583 } 2031 }
1584 } 2032 }
1585 } 2033 }
1586 } 2034 }
1587 } 2035 }
1588 2036
1589 2037
1590 static intptr_t NumberLoadExpressions(FlowGraph* graph) { 2038 static intptr_t NumberLoadExpressions(FlowGraph* graph) {
1591 DirectChainedHashMap<Definition*> map; 2039 DirectChainedHashMap<Definition*> map;
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after
2317 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) { 2765 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {
2318 // Nothing to do. Has no value. 2766 // Nothing to do. Has no value.
2319 } 2767 }
2320 2768
2321 2769
2322 void ConstantPropagator::VisitConstant(ConstantInstr* instr) { 2770 void ConstantPropagator::VisitConstant(ConstantInstr* instr) {
2323 SetValue(instr, instr->value()); 2771 SetValue(instr, instr->value());
2324 } 2772 }
2325 2773
2326 2774
2775 void ConstantPropagator::VisitConstraint(ConstraintInstr* instr) {
2776 // Should not be used outside of range analysis.
2777 UNREACHABLE();
2778 }
2779
2780
2327 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) { 2781 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) {
2328 // Nothing to do. Not a value. 2782 // Nothing to do. Not a value.
2329 } 2783 }
2330 2784
2331 2785
2332 void ConstantPropagator::VisitUnboxedDoubleBinaryOp( 2786 void ConstantPropagator::VisitUnboxedDoubleBinaryOp(
2333 UnboxedDoubleBinaryOpInstr* instr) { 2787 UnboxedDoubleBinaryOpInstr* instr) {
2334 const Object& left = instr->left()->definition()->constant_value(); 2788 const Object& left = instr->left()->definition()->constant_value();
2335 const Object& right = instr->right()->definition()->constant_value(); 2789 const Object& right = instr->right()->definition()->constant_value();
2336 if (IsNonConstant(left) || IsNonConstant(right)) { 2790 if (IsNonConstant(left) || IsNonConstant(right)) {
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
2488 it.Advance()) { 2942 it.Advance()) {
2489 JoinEntryInstr* join = it.Current()->AsJoinEntry(); 2943 JoinEntryInstr* join = it.Current()->AsJoinEntry();
2490 if (join != NULL) join->EliminateUnreachablePhiInputs(); 2944 if (join != NULL) join->EliminateUnreachablePhiInputs();
2491 } 2945 }
2492 2946
2493 graph_->ComputeUseLists(); 2947 graph_->ComputeUseLists();
2494 } 2948 }
2495 2949
2496 2950
2497 } // namespace dart 2951 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698