Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 #include "src/compiler/code-generator-impl.h" | 6 #include "src/compiler/code-generator-impl.h" |
| 7 #include "src/compiler/gap-resolver.h" | 7 #include "src/compiler/gap-resolver.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
| 10 #include "src/compiler/osr.h" | 10 #include "src/compiler/osr.h" |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 : OutOfLineRound(gen, result) {} | 196 : OutOfLineRound(gen, result) {} |
| 197 }; | 197 }; |
| 198 | 198 |
| 199 | 199 |
| 200 class OutOfLineCeil FINAL : public OutOfLineRound { | 200 class OutOfLineCeil FINAL : public OutOfLineRound { |
| 201 public: | 201 public: |
| 202 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) | 202 OutOfLineCeil(CodeGenerator* gen, DoubleRegister result) |
| 203 : OutOfLineRound(gen, result) {} | 203 : OutOfLineRound(gen, result) {} |
| 204 }; | 204 }; |
| 205 | 205 |
| 206 | |
| 207 Condition FlagsConditionToConditionCmp(FlagsCondition condition) { | |
| 208 switch (condition) { | |
| 209 case kEqual: | |
| 210 return eq; | |
| 211 break; | |
|
paul.l...
2015/01/13 17:34:57
Please remove the unnecessary break's after the re
balazs.kilvady
2015/01/13 18:23:40
Done.
| |
| 212 case kNotEqual: | |
| 213 return ne; | |
| 214 break; | |
| 215 case kSignedLessThan: | |
| 216 return lt; | |
| 217 break; | |
| 218 case kSignedGreaterThanOrEqual: | |
| 219 return ge; | |
| 220 break; | |
| 221 case kSignedLessThanOrEqual: | |
| 222 return le; | |
| 223 break; | |
| 224 case kSignedGreaterThan: | |
| 225 return gt; | |
| 226 break; | |
| 227 case kUnsignedLessThan: | |
| 228 return lo; | |
| 229 break; | |
| 230 case kUnsignedGreaterThanOrEqual: | |
| 231 return hs; | |
| 232 break; | |
| 233 case kUnsignedLessThanOrEqual: | |
| 234 return ls; | |
| 235 break; | |
| 236 case kUnsignedGreaterThan: | |
| 237 return hi; | |
| 238 break; | |
| 239 default: | |
| 240 break; | |
| 241 } | |
| 242 UNREACHABLE(); | |
| 243 return kNoCondition; | |
| 244 } | |
| 245 | |
| 246 | |
| 247 Condition FlagsConditionToConditionTst(FlagsCondition condition) { | |
| 248 switch (condition) { | |
| 249 case kNotEqual: | |
| 250 return ne; | |
| 251 break; | |
| 252 case kEqual: | |
| 253 return eq; | |
| 254 break; | |
| 255 default: | |
| 256 break; | |
| 257 } | |
| 258 UNREACHABLE(); | |
| 259 return kNoCondition; | |
| 260 } | |
| 261 | |
| 262 | |
| 263 Condition FlagsConditionToConditionOvf(FlagsCondition condition) { | |
| 264 switch (condition) { | |
| 265 case kOverflow: | |
| 266 return lt; | |
| 267 break; | |
| 268 case kNotOverflow: | |
| 269 return ge; | |
| 270 break; | |
| 271 default: | |
| 272 break; | |
| 273 } | |
| 274 UNREACHABLE(); | |
| 275 return kNoCondition; | |
| 276 } | |
| 277 | |
| 206 } // namespace | 278 } // namespace |
| 207 | 279 |
| 208 | 280 |
| 209 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ | 281 #define ASSEMBLE_CHECKED_LOAD_FLOAT(width, asm_instr) \ |
| 210 do { \ | 282 do { \ |
| 211 auto result = i.Output##width##Register(); \ | 283 auto result = i.Output##width##Register(); \ |
| 212 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ | 284 auto ool = new (zone()) OutOfLineLoad##width(this, result); \ |
| 213 if (instr->InputAt(0)->IsRegister()) { \ | 285 if (instr->InputAt(0)->IsRegister()) { \ |
| 214 auto offset = i.InputRegister(0); \ | 286 auto offset = i.InputRegister(0); \ |
| 215 __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \ | 287 __ Branch(USE_DELAY_SLOT, ool->entry(), hs, offset, i.InputOperand(1)); \ |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 639 // MIPS does not have condition code flags, so compare and branch are | 711 // MIPS does not have condition code flags, so compare and branch are |
| 640 // implemented differently than on the other arch's. The compare operations | 712 // implemented differently than on the other arch's. The compare operations |
| 641 // emit mips pseudo-instructions, which are handled here by branch | 713 // emit mips pseudo-instructions, which are handled here by branch |
| 642 // instructions that do the actual comparison. Essential that the input | 714 // instructions that do the actual comparison. Essential that the input |
| 643 // registers to compare pseudo-op are not modified before this branch op, as | 715 // registers to compare pseudo-op are not modified before this branch op, as |
| 644 // they are tested here. | 716 // they are tested here. |
| 645 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | 717 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were |
| 646 // not separated by other instructions. | 718 // not separated by other instructions. |
| 647 | 719 |
| 648 if (instr->arch_opcode() == kMipsTst) { | 720 if (instr->arch_opcode() == kMipsTst) { |
| 649 switch (branch->condition) { | 721 cc = FlagsConditionToConditionTst(branch->condition); |
| 650 case kNotEqual: | |
| 651 cc = ne; | |
| 652 break; | |
| 653 case kEqual: | |
| 654 cc = eq; | |
| 655 break; | |
| 656 default: | |
| 657 UNSUPPORTED_COND(kMipsTst, branch->condition); | |
| 658 break; | |
| 659 } | |
| 660 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 722 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| 661 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 723 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
| 662 | 724 |
| 663 } else if (instr->arch_opcode() == kMipsAddOvf || | 725 } else if (instr->arch_opcode() == kMipsAddOvf || |
| 664 instr->arch_opcode() == kMipsSubOvf) { | 726 instr->arch_opcode() == kMipsSubOvf) { |
| 665 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. | 727 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. |
| 666 switch (branch->condition) { | 728 cc = FlagsConditionToConditionOvf(branch->condition); |
| 667 case kOverflow: | |
| 668 cc = lt; | |
| 669 break; | |
| 670 case kNotOverflow: | |
| 671 cc = ge; | |
| 672 break; | |
| 673 default: | |
| 674 UNSUPPORTED_COND(kMipsAddOvf, branch->condition); | |
| 675 break; | |
| 676 } | |
| 677 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); | 729 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); |
| 678 | 730 |
| 679 } else if (instr->arch_opcode() == kMipsCmp) { | 731 } else if (instr->arch_opcode() == kMipsCmp) { |
| 680 switch (branch->condition) { | 732 cc = FlagsConditionToConditionCmp(branch->condition); |
| 681 case kEqual: | 733 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
| 682 cc = eq; | |
| 683 break; | |
| 684 case kNotEqual: | |
| 685 cc = ne; | |
| 686 break; | |
| 687 case kSignedLessThan: | |
| 688 cc = lt; | |
| 689 break; | |
| 690 case kSignedGreaterThanOrEqual: | |
| 691 cc = ge; | |
| 692 break; | |
| 693 case kSignedLessThanOrEqual: | |
| 694 cc = le; | |
| 695 break; | |
| 696 case kSignedGreaterThan: | |
| 697 cc = gt; | |
| 698 break; | |
| 699 case kUnsignedLessThan: | |
| 700 cc = lo; | |
| 701 break; | |
| 702 case kUnsignedGreaterThanOrEqual: | |
| 703 cc = hs; | |
| 704 break; | |
| 705 case kUnsignedLessThanOrEqual: | |
| 706 cc = ls; | |
| 707 break; | |
| 708 case kUnsignedGreaterThan: | |
| 709 cc = hi; | |
| 710 break; | |
| 711 default: | |
| 712 UNSUPPORTED_COND(kMipsCmp, branch->condition); | |
| 713 break; | |
| 714 } | |
| 715 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); | |
| 716 | 734 |
| 717 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. | 735 if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel. |
| 718 | 736 |
| 719 } else if (instr->arch_opcode() == kMipsCmpD) { | 737 } else if (instr->arch_opcode() == kMipsCmpD) { |
| 720 // TODO(dusmil) optimize unordered checks to use fewer instructions | 738 // TODO(dusmil) optimize unordered checks to use fewer instructions |
| 721 // even if we have to unfold BranchF macro. | 739 // even if we have to unfold BranchF macro. |
| 722 Label* nan = flabel; | 740 Label* nan = flabel; |
| 723 switch (branch->condition) { | 741 switch (branch->condition) { |
| 724 case kUnorderedEqual: | 742 case kEqual: |
| 725 cc = eq; | 743 cc = eq; |
| 726 break; | 744 break; |
| 727 case kUnorderedNotEqual: | 745 case kNotEqual: |
| 728 cc = ne; | 746 cc = ne; |
| 729 nan = tlabel; | 747 nan = tlabel; |
| 730 break; | 748 break; |
| 731 case kUnorderedLessThan: | 749 case kUnsignedLessThan: |
| 732 cc = lt; | 750 cc = lt; |
| 733 break; | 751 break; |
| 734 case kUnorderedGreaterThanOrEqual: | 752 case kUnsignedGreaterThanOrEqual: |
| 735 cc = ge; | 753 cc = ge; |
| 736 nan = tlabel; | 754 nan = tlabel; |
| 737 break; | 755 break; |
| 738 case kUnorderedLessThanOrEqual: | 756 case kUnsignedLessThanOrEqual: |
| 739 cc = le; | 757 cc = le; |
| 740 break; | 758 break; |
| 741 case kUnorderedGreaterThan: | 759 case kUnsignedGreaterThan: |
| 742 cc = gt; | 760 cc = gt; |
| 743 nan = tlabel; | 761 nan = tlabel; |
| 744 break; | 762 break; |
| 745 default: | 763 default: |
| 746 UNSUPPORTED_COND(kMipsCmpD, branch->condition); | 764 UNSUPPORTED_COND(kMipsCmpD, branch->condition); |
| 747 break; | 765 break; |
| 748 } | 766 } |
| 749 __ BranchF(tlabel, nan, cc, i.InputDoubleRegister(0), | 767 __ BranchF(tlabel, nan, cc, i.InputDoubleRegister(0), |
| 750 i.InputDoubleRegister(1)); | 768 i.InputDoubleRegister(1)); |
| 751 | 769 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 781 // implemented differently than on the other arch's. The compare operations | 799 // implemented differently than on the other arch's. The compare operations |
| 782 // emit mips psuedo-instructions, which are checked and handled here. | 800 // emit mips psuedo-instructions, which are checked and handled here. |
| 783 | 801 |
| 784 // For materializations, we use delay slot to set the result true, and | 802 // For materializations, we use delay slot to set the result true, and |
| 785 // in the false case, where we fall thru the branch, we reset the result | 803 // in the false case, where we fall thru the branch, we reset the result |
| 786 // false. | 804 // false. |
| 787 | 805 |
| 788 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | 806 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were |
| 789 // not separated by other instructions. | 807 // not separated by other instructions. |
| 790 if (instr->arch_opcode() == kMipsTst) { | 808 if (instr->arch_opcode() == kMipsTst) { |
| 791 switch (condition) { | 809 cc = FlagsConditionToConditionTst(condition); |
| 792 case kNotEqual: | |
| 793 cc = ne; | |
| 794 break; | |
| 795 case kEqual: | |
| 796 cc = eq; | |
| 797 break; | |
| 798 default: | |
| 799 UNSUPPORTED_COND(kMipsTst, condition); | |
| 800 break; | |
| 801 } | |
| 802 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 810 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| 803 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 811 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); |
| 804 __ li(result, Operand(1)); // In delay slot. | 812 __ li(result, Operand(1)); // In delay slot. |
| 805 | 813 |
| 806 } else if (instr->arch_opcode() == kMipsAddOvf || | 814 } else if (instr->arch_opcode() == kMipsAddOvf || |
| 807 instr->arch_opcode() == kMipsSubOvf) { | 815 instr->arch_opcode() == kMipsSubOvf) { |
| 808 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. | 816 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. |
| 809 switch (condition) { | 817 cc = FlagsConditionToConditionOvf(condition); |
| 810 case kOverflow: | |
| 811 cc = lt; | |
| 812 break; | |
| 813 case kNotOverflow: | |
| 814 cc = ge; | |
| 815 break; | |
| 816 default: | |
| 817 UNSUPPORTED_COND(kMipsAddOvf, condition); | |
| 818 break; | |
| 819 } | |
| 820 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); | 818 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); |
| 821 __ li(result, Operand(1)); // In delay slot. | 819 __ li(result, Operand(1)); // In delay slot. |
| 822 | 820 |
| 823 | 821 |
| 824 } else if (instr->arch_opcode() == kMipsCmp) { | 822 } else if (instr->arch_opcode() == kMipsCmp) { |
| 825 Register left = i.InputRegister(0); | 823 Register left = i.InputRegister(0); |
| 826 Operand right = i.InputOperand(1); | 824 Operand right = i.InputOperand(1); |
| 827 switch (condition) { | 825 cc = FlagsConditionToConditionCmp(condition); |
| 828 case kEqual: | |
| 829 cc = eq; | |
| 830 break; | |
| 831 case kNotEqual: | |
| 832 cc = ne; | |
| 833 break; | |
| 834 case kSignedLessThan: | |
| 835 cc = lt; | |
| 836 break; | |
| 837 case kSignedGreaterThanOrEqual: | |
| 838 cc = ge; | |
| 839 break; | |
| 840 case kSignedLessThanOrEqual: | |
| 841 cc = le; | |
| 842 break; | |
| 843 case kSignedGreaterThan: | |
| 844 cc = gt; | |
| 845 break; | |
| 846 case kUnsignedLessThan: | |
| 847 cc = lo; | |
| 848 break; | |
| 849 case kUnsignedGreaterThanOrEqual: | |
| 850 cc = hs; | |
| 851 break; | |
| 852 case kUnsignedLessThanOrEqual: | |
| 853 cc = ls; | |
| 854 break; | |
| 855 case kUnsignedGreaterThan: | |
| 856 cc = hi; | |
| 857 break; | |
| 858 default: | |
| 859 UNSUPPORTED_COND(kMipsCmp, condition); | |
| 860 break; | |
| 861 } | |
| 862 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 826 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); |
| 863 __ li(result, Operand(1)); // In delay slot. | 827 __ li(result, Operand(1)); // In delay slot. |
| 864 | 828 |
| 865 } else if (instr->arch_opcode() == kMipsCmpD) { | 829 } else if (instr->arch_opcode() == kMipsCmpD) { |
| 866 FPURegister left = i.InputDoubleRegister(0); | 830 FPURegister left = i.InputDoubleRegister(0); |
| 867 FPURegister right = i.InputDoubleRegister(1); | 831 FPURegister right = i.InputDoubleRegister(1); |
| 868 // TODO(plind): Provide NaN-testing macro-asm function without need for | 832 // TODO(plind): Provide NaN-testing macro-asm function without need for |
| 869 // BranchF. | 833 // BranchF. |
| 870 FPURegister dummy1 = f0; | 834 FPURegister dummy1 = f0; |
| 871 FPURegister dummy2 = f2; | 835 FPURegister dummy2 = f2; |
| 872 switch (condition) { | 836 switch (condition) { |
| 873 case kUnorderedEqual: | 837 case kEqual: |
| 874 // TODO(plind): improve the NaN testing throughout this function. | 838 // TODO(plind): improve the NaN testing throughout this function. |
| 875 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 839 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
| 876 cc = eq; | 840 cc = eq; |
| 877 break; | 841 break; |
| 878 case kUnorderedNotEqual: | 842 case kNotEqual: |
| 879 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 843 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
| 880 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 844 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
| 881 cc = ne; | 845 cc = ne; |
| 882 break; | 846 break; |
| 883 case kUnorderedLessThan: | 847 case kUnsignedLessThan: |
| 884 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 848 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
| 885 cc = lt; | 849 cc = lt; |
| 886 break; | 850 break; |
| 887 case kUnorderedGreaterThanOrEqual: | 851 case kUnsignedGreaterThanOrEqual: |
| 888 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 852 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
| 889 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 853 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
| 890 cc = ge; | 854 cc = ge; |
| 891 break; | 855 break; |
| 892 case kUnorderedLessThanOrEqual: | 856 case kUnsignedLessThanOrEqual: |
| 893 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 857 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
| 894 cc = le; | 858 cc = le; |
| 895 break; | 859 break; |
| 896 case kUnorderedGreaterThan: | 860 case kUnsignedGreaterThan: |
| 897 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 861 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
| 898 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 862 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
| 899 cc = gt; | 863 cc = gt; |
| 900 break; | 864 break; |
| 901 default: | 865 default: |
| 902 UNSUPPORTED_COND(kMipsCmp, condition); | 866 UNSUPPORTED_COND(kMipsCmp, condition); |
| 903 break; | 867 break; |
| 904 } | 868 } |
| 905 __ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right); | 869 __ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right); |
| 906 __ li(result, Operand(1)); // In delay slot - branch taken returns 1. | 870 __ li(result, Operand(1)); // In delay slot - branch taken returns 1. |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1194 } | 1158 } |
| 1195 } | 1159 } |
| 1196 MarkLazyDeoptSite(); | 1160 MarkLazyDeoptSite(); |
| 1197 } | 1161 } |
| 1198 | 1162 |
| 1199 #undef __ | 1163 #undef __ |
| 1200 | 1164 |
| 1201 } // namespace compiler | 1165 } // namespace compiler |
| 1202 } // namespace internal | 1166 } // namespace internal |
| 1203 } // namespace v8 | 1167 } // namespace v8 |
| OLD | NEW |