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

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

Issue 504143003: Support Int32 representation for selected binary operations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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) 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/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 305
306 bool BinarySmiOpInstr::AttributesEqual(Instruction* other) const { 306 bool BinarySmiOpInstr::AttributesEqual(Instruction* other) const {
307 BinarySmiOpInstr* other_op = other->AsBinarySmiOp(); 307 BinarySmiOpInstr* other_op = other->AsBinarySmiOp();
308 ASSERT(other_op != NULL); 308 ASSERT(other_op != NULL);
309 return (op_kind() == other_op->op_kind()) && 309 return (op_kind() == other_op->op_kind()) &&
310 (overflow_ == other_op->overflow_) && 310 (overflow_ == other_op->overflow_) &&
311 (is_truncating_ == other_op->is_truncating_); 311 (is_truncating_ == other_op->is_truncating_);
312 } 312 }
313 313
314 314
315 bool BinaryInt32OpInstr::AttributesEqual(Instruction* other) const {
316 BinaryInt32OpInstr* other_op = other->AsBinaryInt32Op();
317 ASSERT(other_op != NULL);
318 return (op_kind() == other_op->op_kind()) &&
319 (overflow_ == other_op->overflow_) &&
320 (is_truncating_ == other_op->is_truncating_);
321 }
322
323
315 EffectSet LoadFieldInstr::Dependencies() const { 324 EffectSet LoadFieldInstr::Dependencies() const {
316 return immutable_ ? EffectSet::None() : EffectSet::All(); 325 return immutable_ ? EffectSet::None() : EffectSet::All();
317 } 326 }
318 327
319 328
320 bool LoadFieldInstr::AttributesEqual(Instruction* other) const { 329 bool LoadFieldInstr::AttributesEqual(Instruction* other) const {
321 LoadFieldInstr* other_load = other->AsLoadField(); 330 LoadFieldInstr* other_load = other->AsLoadField();
322 ASSERT(other_load != NULL); 331 ASSERT(other_load != NULL);
323 if (field() != NULL) { 332 if (field() != NULL) {
324 return (other_load->field() != NULL) && 333 return (other_load->field() != NULL) &&
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 } 390 }
382 391
383 392
384 bool ConstantInstr::AttributesEqual(Instruction* other) const { 393 bool ConstantInstr::AttributesEqual(Instruction* other) const {
385 ConstantInstr* other_constant = other->AsConstant(); 394 ConstantInstr* other_constant = other->AsConstant();
386 ASSERT(other_constant != NULL); 395 ASSERT(other_constant != NULL);
387 return (value().raw() == other_constant->value().raw()); 396 return (value().raw() == other_constant->value().raw());
388 } 397 }
389 398
390 399
391 UnboxedConstantInstr::UnboxedConstantInstr(const Object& value) 400 UnboxedConstantInstr::UnboxedConstantInstr(const Object& value,
392 : ConstantInstr(value), constant_address_(0) { 401 Representation representation)
393 // Only doubles supported for now. 402 : ConstantInstr(value),
394 ASSERT(value.IsDouble()); 403 representation_(representation),
395 constant_address_ = 404 constant_address_(0) {
396 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value()); 405 if (representation_ == kUnboxedDouble) {
406 ASSERT(value.IsDouble());
407 constant_address_ =
408 FlowGraphBuilder::FindDoubleConstant(Double::Cast(value).value());
409 }
397 } 410 }
398 411
399 412
400 bool Value::BindsTo32BitMaskConstant() const { 413 bool Value::BindsTo32BitMaskConstant() const {
401 if (!definition()->IsUnboxInteger() || !definition()->IsUnboxUint32()) { 414 if (!definition()->IsUnboxInteger() || !definition()->IsUnboxUint32()) {
402 return false; 415 return false;
403 } 416 }
404 // Two cases to consider: UnboxInteger and UnboxUint32. 417 // Two cases to consider: UnboxInteger and UnboxUint32.
405 if (definition()->IsUnboxInteger()) { 418 if (definition()->IsUnboxInteger()) {
406 UnboxIntegerInstr* instr = definition()->AsUnboxInteger(); 419 UnboxIntegerInstr* instr = definition()->AsUnboxInteger();
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 } 684 }
672 685
673 set_previous_use(NULL); 686 set_previous_use(NULL);
674 set_next_use(NULL); 687 set_next_use(NULL);
675 } 688 }
676 689
677 690
678 // True if the definition has a single input use and is used only in 691 // True if the definition has a single input use and is used only in
679 // environments at the same instruction as that input use. 692 // environments at the same instruction as that input use.
680 bool Definition::HasOnlyUse(Value* use) const { 693 bool Definition::HasOnlyUse(Value* use) const {
681 if ((input_use_list() != use) || (use->next_use() != NULL)) return false; 694 if (!HasOnlyInputUse(use)) {
695 return false;
696 }
682 697
683 Instruction* target = use->instruction(); 698 Instruction* target = use->instruction();
684 for (Value::Iterator it(env_use_list()); !it.Done(); it.Advance()) { 699 for (Value::Iterator it(env_use_list()); !it.Done(); it.Advance()) {
685 if (it.Current()->instruction() != target) return false; 700 if (it.Current()->instruction() != target) return false;
686 } 701 }
687 return true; 702 return true;
688 } 703 }
689 704
690 705
706 bool Definition::HasOnlyInputUse(Value* use) const {
707 return (input_use_list() == use) && (use->next_use() == NULL);
708 }
709
710
691 void Definition::ReplaceUsesWith(Definition* other) { 711 void Definition::ReplaceUsesWith(Definition* other) {
692 ASSERT(other != NULL); 712 ASSERT(other != NULL);
693 ASSERT(this != other); 713 ASSERT(this != other);
694 714
695 Value* current = NULL; 715 Value* current = NULL;
696 Value* next = input_use_list(); 716 Value* next = input_use_list();
697 if (next != NULL) { 717 if (next != NULL) {
698 // Change all the definitions. 718 // Change all the definitions.
699 while (next != NULL) { 719 while (next != NULL) {
700 current = next; 720 current = next;
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 ASSERT(index == 0); 1162 ASSERT(index == 0);
1143 return successor(); 1163 return successor();
1144 } 1164 }
1145 1165
1146 1166
1147 void Instruction::Goto(JoinEntryInstr* entry) { 1167 void Instruction::Goto(JoinEntryInstr* entry) {
1148 LinkTo(new GotoInstr(entry)); 1168 LinkTo(new GotoInstr(entry));
1149 } 1169 }
1150 1170
1151 1171
1172 bool UnboxedIntConverterInstr::CanDeoptimize() const {
1173 return (to() == kUnboxedInt32) &&
1174 !Range::Fits(value()->definition()->range(),
1175 RangeBoundary::kRangeBoundaryInt32);
1176 }
1177
1178
1179 bool UnboxInt32Instr::CanDeoptimize() const {
1180 const intptr_t value_cid = value()->Type()->ToCid();
1181 if (value_cid == kSmiCid) {
1182 return false;
1183 } else if (value_cid == kMintCid) {
1184 return !Range::Fits(value()->definition()->range(),
1185 RangeBoundary::kRangeBoundaryInt32);
1186 } else {
1187 return true;
1188 }
1189 }
1190
1191
1192 bool BinaryInt32OpInstr::CanDeoptimize() const {
1193 switch (op_kind()) {
1194 case Token::kBIT_AND:
1195 case Token::kBIT_OR:
1196 case Token::kBIT_XOR:
1197 return false;
1198
1199 case Token::kSHR:
1200 return false;
1201
1202 case Token::kSHL:
1203 return true;
1204
1205 case Token::kMOD: {
1206 UNREACHABLE();
1207 }
1208
1209 default:
1210 return overflow_;
1211 }
1212 }
1213
1214
1152 bool BinarySmiOpInstr::CanDeoptimize() const { 1215 bool BinarySmiOpInstr::CanDeoptimize() const {
1153 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) { 1216 if (FLAG_throw_on_javascript_int_overflow && (Smi::kBits > 32)) {
1154 // If Smi's are bigger than 32-bits, then the instruction could deoptimize 1217 // If Smi's are bigger than 32-bits, then the instruction could deoptimize
1155 // if the result is too big. 1218 // if the result is too big.
1156 return true; 1219 return true;
1157 } 1220 }
1158 switch (op_kind()) { 1221 switch (op_kind()) {
1159 case Token::kBIT_AND: 1222 case Token::kBIT_AND:
1160 case Token::kBIT_OR: 1223 case Token::kBIT_OR:
1161 case Token::kBIT_XOR: 1224 case Token::kBIT_XOR:
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1418 left(), 1481 left(),
1419 truncation_mask); 1482 truncation_mask);
1420 if (result != NULL) { 1483 if (result != NULL) {
1421 return result; 1484 return result;
1422 } 1485 }
1423 1486
1424 return this; 1487 return this;
1425 } 1488 }
1426 1489
1427 1490
1491 Definition* BinaryInt32OpInstr::Canonicalize(FlowGraph* flow_graph) {
1492 Definition* result = NULL;
1493
1494 result = CanonicalizeCommutativeArithmetic(op_kind(),
1495 kSmiCid,
1496 left(),
1497 right());
1498 if (result != NULL) {
1499 return result;
1500 }
1501
1502 result = CanonicalizeCommutativeArithmetic(op_kind(),
1503 kSmiCid,
1504 right(),
1505 left());
1506 if (result != NULL) {
1507 return result;
1508 }
1509
1510 return this;
1511 }
1512
1513
1428 // Optimizations that eliminate or simplify individual instructions. 1514 // Optimizations that eliminate or simplify individual instructions.
1429 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) { 1515 Instruction* Instruction::Canonicalize(FlowGraph* flow_graph) {
1430 return this; 1516 return this;
1431 } 1517 }
1432 1518
1433 1519
1434 Definition* Definition::Canonicalize(FlowGraph* flow_graph) { 1520 Definition* Definition::Canonicalize(FlowGraph* flow_graph) {
1435 return this; 1521 return this;
1436 } 1522 }
1437 1523
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
1616 // Fold away BoxDouble(UnboxDouble(v)) if value is known to be double. 1702 // Fold away BoxDouble(UnboxDouble(v)) if value is known to be double.
1617 UnboxDoubleInstr* defn = value()->definition()->AsUnboxDouble(); 1703 UnboxDoubleInstr* defn = value()->definition()->AsUnboxDouble();
1618 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kDoubleCid)) { 1704 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kDoubleCid)) {
1619 return defn->value()->definition(); 1705 return defn->value()->definition();
1620 } 1706 }
1621 1707
1622 return this; 1708 return this;
1623 } 1709 }
1624 1710
1625 1711
1712 bool BoxIntNInstr::ValueFitsSmi() const {
1713 Range* range = value()->definition()->range();
1714 return Range::Fits(range, RangeBoundary::kRangeBoundarySmi);
1715 }
1716
1717
1718 Definition* BoxIntNInstr::Canonicalize(FlowGraph* flow_graph) {
1719 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
1720 // Environments can accomodate any representation. No need to box.
1721 return value()->definition();
1722 }
1723
1724 return this;
1725 }
1726
1727
1728 Definition* UnboxIntNInstr::Canonicalize(FlowGraph* flow_graph) {
1729 if (!HasUses()) return NULL;
1730
1731 // Fold away UnboxInt<N>Instr(BoxInt<N>Instr(v)).
1732 BoxIntNInstr* box_defn = value()->definition()->AsBoxIntN();
1733 if (box_defn != NULL) {
1734 if (box_defn->value()->definition()->representation() == representation()) {
1735 return box_defn->value()->definition();
1736 } else {
1737 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
1738 box_defn->value()->definition()->representation(),
1739 representation(),
1740 box_defn->value()->CopyWithType(),
1741 representation() == kUnboxedInt32 ? deopt_id_ : Isolate::kNoDeoptId);
1742 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
1743 return converter;
1744 }
1745 }
1746
1747 return this;
1748 }
1749
1750
1751 Definition* UnboxedIntConverterInstr::Canonicalize(FlowGraph* flow_graph) {
1752 if (!HasUses()) return NULL;
1753
1754 UnboxedIntConverterInstr* box_defn =
1755 value()->definition()->AsUnboxedIntConverter();
1756 if ((box_defn != NULL) && (box_defn->representation() == from())) {
1757 if (box_defn->from() == to()) {
1758 return box_defn->value()->definition();
1759 }
1760
1761 UnboxedIntConverterInstr* converter = new UnboxedIntConverterInstr(
1762 box_defn->from(),
1763 representation(),
1764 box_defn->value()->CopyWithType(),
1765 to() == kUnboxedInt32 ? deopt_id_ : NULL);
1766 flow_graph->InsertBefore(this, converter, env(), FlowGraph::kValue);
1767 return converter;
1768 }
1769
1770 UnboxIntegerInstr* unbox_defn = value()->definition()->AsUnboxInteger();
1771 if (unbox_defn != NULL &&
1772 (from() == kUnboxedMint) &&
1773 (to() == kUnboxedInt32) &&
1774 unbox_defn->HasOnlyInputUse(value())) {
1775 // TODO(vegorov): there is a duplication of code between UnboxedIntCoverter
1776 // and code path that unboxes Mint into Int32. We should just schedule
1777 // these instructions close to each other instead of fusing them.
1778 Definition* replacement =
1779 new UnboxInt32Instr(unbox_defn->value()->CopyWithType(), deopt_id_);
1780 flow_graph->InsertBefore(this,
1781 replacement,
1782 env(),
1783 FlowGraph::kValue);
1784 return replacement;
1785 }
1786
1787 return this;
1788 }
1789
1790
1791 Definition* UnboxInt32Instr::Canonicalize(FlowGraph* flow_graph) {
1792 Definition* replacement = UnboxIntNInstr::Canonicalize(flow_graph);
1793 if (replacement != this) {
1794 return replacement;
1795 }
1796
1797 ConstantInstr* c = value()->definition()->AsConstant();
1798 if ((c != NULL) && c->value().IsSmi()) {
1799 UnboxedConstantInstr* uc =
1800 new UnboxedConstantInstr(c->value(), kUnboxedInt32);
1801 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
1802 return uc;
1803 }
1804
1805 return this;
1806 }
1807
1808
1626 Definition* UnboxDoubleInstr::Canonicalize(FlowGraph* flow_graph) { 1809 Definition* UnboxDoubleInstr::Canonicalize(FlowGraph* flow_graph) {
1627 if (!HasUses()) return NULL; 1810 if (!HasUses()) return NULL;
1628 // Fold away UnboxDouble(BoxDouble(v)). 1811 // Fold away UnboxDouble(BoxDouble(v)).
1629 BoxDoubleInstr* box_defn = value()->definition()->AsBoxDouble(); 1812 BoxDoubleInstr* box_defn = value()->definition()->AsBoxDouble();
1630 if (box_defn != NULL) { 1813 if (box_defn != NULL) {
1631 return box_defn->value()->definition(); 1814 return box_defn->value()->definition();
1632 } 1815 }
1633 1816
1634 ConstantInstr* c = value()->definition()->AsConstant(); 1817 ConstantInstr* c = value()->definition()->AsConstant();
1635 if ((c != NULL) && c->value().IsDouble()) { 1818 if ((c != NULL) && c->value().IsDouble()) {
1636 UnboxedConstantInstr* uc = new UnboxedConstantInstr(c->value()); 1819 UnboxedConstantInstr* uc =
1820 new UnboxedConstantInstr(c->value(), kUnboxedDouble);
1637 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue); 1821 flow_graph->InsertBefore(this, uc, NULL, FlowGraph::kValue);
1638 return uc; 1822 return uc;
1639 } 1823 }
1640 1824
1641 return this; 1825 return this;
1642 } 1826 }
1643 1827
1644 1828
1829 Definition* BoxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
1830 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
1831 // Environments can accomodate any representation. No need to box.
1832 return value()->definition();
1833 }
1834
1835 UnboxedIntConverterInstr* conv =
1836 value()->definition()->AsUnboxedIntConverter();
1837 if (conv != NULL) {
1838 Definition* replacement = this;
1839
1840 switch (conv->from()) {
1841 case kUnboxedInt32:
1842 replacement = new BoxInt32Instr(conv->value()->CopyWithType());
1843 break;
1844 case kUnboxedUint32:
1845 replacement = new BoxUint32Instr(conv->value()->CopyWithType());
1846 break;
1847 default:
1848 UNREACHABLE();
1849 break;
1850 }
1851
1852 if (replacement != this) {
1853 flow_graph->InsertBefore(this,
1854 replacement,
1855 NULL,
1856 FlowGraph::kValue);
1857 }
1858
1859 return replacement;
1860 }
1861
1862 return this;
1863 }
1864
1865
1866 Definition* UnboxIntegerInstr::Canonicalize(FlowGraph* flow_graph) {
1867 if (!HasUses()) return NULL;
1868 return this;
1869 }
1870
1871
1645 Definition* BoxFloat32x4Instr::Canonicalize(FlowGraph* flow_graph) { 1872 Definition* BoxFloat32x4Instr::Canonicalize(FlowGraph* flow_graph) {
1646 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) { 1873 if ((input_use_list() == NULL) && !HasTryBlockUse(env_use_list())) {
1647 // Environments can accomodate any representation. No need to box. 1874 // Environments can accomodate any representation. No need to box.
1648 return value()->definition(); 1875 return value()->definition();
1649 } 1876 }
1650 1877
1651 // Fold away BoxFloat32x4(UnboxFloat32x4(v)). 1878 // Fold away BoxFloat32x4(UnboxFloat32x4(v)).
1652 UnboxFloat32x4Instr* defn = value()->definition()->AsUnboxFloat32x4(); 1879 UnboxFloat32x4Instr* defn = value()->definition()->AsUnboxFloat32x4();
1653 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kFloat32x4Cid)) { 1880 if ((defn != NULL) && (defn->value()->Type()->ToCid() == kFloat32x4Cid)) {
1654 return defn->value()->definition(); 1881 return defn->value()->definition();
(...skipping 1206 matching lines...) Expand 10 before | Expand all | Expand 10 after
2861 case Token::kTRUNCDIV: return 0; 3088 case Token::kTRUNCDIV: return 0;
2862 case Token::kMOD: return 1; 3089 case Token::kMOD: return 1;
2863 default: UNIMPLEMENTED(); return -1; 3090 default: UNIMPLEMENTED(); return -1;
2864 } 3091 }
2865 } 3092 }
2866 3093
2867 3094
2868 #undef __ 3095 #undef __
2869 3096
2870 } // namespace dart 3097 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698