| 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/base/bits.h" | 5 #include "src/base/bits.h" |
| 6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
| 7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
| 8 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 case kMips64Xor: | 50 case kMips64Xor: |
| 51 return is_uint16(value); | 51 return is_uint16(value); |
| 52 case kMips64Ldc1: | 52 case kMips64Ldc1: |
| 53 case kMips64Sdc1: | 53 case kMips64Sdc1: |
| 54 return is_int16(value + kIntSize); | 54 return is_int16(value + kIntSize); |
| 55 default: | 55 default: |
| 56 return is_int16(value); | 56 return is_int16(value); |
| 57 } | 57 } |
| 58 } | 58 } |
| 59 | 59 |
| 60 | |
| 61 bool CanBeImmediate(Node* node, InstructionCode opcode, | |
| 62 FlagsContinuation* cont) { | |
| 63 int64_t value; | |
| 64 if (node->opcode() == IrOpcode::kInt32Constant) | |
| 65 value = OpParameter<int32_t>(node); | |
| 66 else if (node->opcode() == IrOpcode::kInt64Constant) | |
| 67 value = OpParameter<int64_t>(node); | |
| 68 else | |
| 69 return false; | |
| 70 switch (ArchOpcodeField::decode(opcode)) { | |
| 71 case kMips64Cmp32: | |
| 72 switch (cont->condition()) { | |
| 73 case kUnsignedLessThan: | |
| 74 case kUnsignedGreaterThanOrEqual: | |
| 75 case kUnsignedLessThanOrEqual: | |
| 76 case kUnsignedGreaterThan: | |
| 77 // Immediate operands for unsigned 32-bit compare operations | |
| 78 // should not be sign-extended. | |
| 79 return is_uint15(value); | |
| 80 default: | |
| 81 return false; | |
| 82 } | |
| 83 default: | |
| 84 return is_int16(value); | |
| 85 } | |
| 86 } | |
| 87 | |
| 88 | |
| 89 private: | 60 private: |
| 90 bool ImmediateFitsAddrMode1Instruction(int32_t imm) const { | 61 bool ImmediateFitsAddrMode1Instruction(int32_t imm) const { |
| 91 TRACE_UNIMPL(); | 62 TRACE_UNIMPL(); |
| 92 return false; | 63 return false; |
| 93 } | 64 } |
| 94 }; | 65 }; |
| 95 | 66 |
| 96 | 67 |
| 97 static void VisitRR(InstructionSelector* selector, ArchOpcode opcode, | 68 static void VisitRR(InstructionSelector* selector, ArchOpcode opcode, |
| 98 Node* node) { | 69 Node* node) { |
| (...skipping 724 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 | 794 |
| 824 // Shared routine for multiple word compare operations. | 795 // Shared routine for multiple word compare operations. |
| 825 void VisitWordCompare(InstructionSelector* selector, Node* node, | 796 void VisitWordCompare(InstructionSelector* selector, Node* node, |
| 826 InstructionCode opcode, FlagsContinuation* cont, | 797 InstructionCode opcode, FlagsContinuation* cont, |
| 827 bool commutative) { | 798 bool commutative) { |
| 828 Mips64OperandGenerator g(selector); | 799 Mips64OperandGenerator g(selector); |
| 829 Node* left = node->InputAt(0); | 800 Node* left = node->InputAt(0); |
| 830 Node* right = node->InputAt(1); | 801 Node* right = node->InputAt(1); |
| 831 | 802 |
| 832 // Match immediates on left or right side of comparison. | 803 // Match immediates on left or right side of comparison. |
| 833 if (g.CanBeImmediate(right, opcode, cont)) { | 804 if (g.CanBeImmediate(right, opcode)) { |
| 834 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), | 805 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right), |
| 835 cont); | 806 cont); |
| 836 } else if (g.CanBeImmediate(left, opcode, cont)) { | 807 } else if (g.CanBeImmediate(left, opcode)) { |
| 837 if (!commutative) cont->Commute(); | 808 if (!commutative) cont->Commute(); |
| 838 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), | 809 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left), |
| 839 cont); | 810 cont); |
| 840 } else { | 811 } else { |
| 841 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), | 812 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right), |
| 842 cont); | 813 cont); |
| 843 } | 814 } |
| 844 } | 815 } |
| 845 | 816 |
| 846 | 817 |
| 847 void VisitWord32Compare(InstructionSelector* selector, Node* node, | 818 void VisitWord32Compare(InstructionSelector* selector, Node* node, |
| 848 FlagsContinuation* cont) { | 819 FlagsContinuation* cont) { |
| 849 VisitWordCompare(selector, node, kMips64Cmp32, cont, false); | 820 VisitWordCompare(selector, node, kMips64Cmp, cont, false); |
| 850 } | 821 } |
| 851 | 822 |
| 852 | 823 |
| 853 void VisitWord64Compare(InstructionSelector* selector, Node* node, | 824 void VisitWord64Compare(InstructionSelector* selector, Node* node, |
| 854 FlagsContinuation* cont) { | 825 FlagsContinuation* cont) { |
| 855 VisitWordCompare(selector, node, kMips64Cmp, cont, false); | 826 VisitWordCompare(selector, node, kMips64Cmp, cont, false); |
| 856 } | 827 } |
| 857 | 828 |
| 858 } // namespace | 829 } // namespace |
| 859 | 830 |
| 860 | 831 |
| 861 void EmitWordCompareZero(InstructionSelector* selector, InstructionCode opcode, | 832 void EmitWordCompareZero(InstructionSelector* selector, Node* value, |
| 862 Node* value, FlagsContinuation* cont) { | 833 FlagsContinuation* cont) { |
| 863 Mips64OperandGenerator g(selector); | 834 Mips64OperandGenerator g(selector); |
| 864 opcode = cont->Encode(opcode); | 835 InstructionCode opcode = cont->Encode(kMips64Cmp); |
| 865 InstructionOperand const value_operand = g.UseRegister(value); | 836 InstructionOperand const value_operand = g.UseRegister(value); |
| 866 if (cont->IsBranch()) { | 837 if (cont->IsBranch()) { |
| 867 selector->Emit(opcode, g.NoOutput(), value_operand, g.TempImmediate(0), | 838 selector->Emit(opcode, g.NoOutput(), value_operand, g.TempImmediate(0), |
| 868 g.Label(cont->true_block()), | 839 g.Label(cont->true_block()), |
| 869 g.Label(cont->false_block()))->MarkAsControl(); | 840 g.Label(cont->false_block()))->MarkAsControl(); |
| 870 } else { | 841 } else { |
| 871 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, | 842 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, |
| 872 g.TempImmediate(0)); | 843 g.TempImmediate(0)); |
| 873 } | 844 } |
| 874 } | 845 } |
| 875 | 846 |
| 876 | 847 |
| 877 // Shared routine for word comparisons against zero. | 848 // Shared routine for word comparisons against zero. |
| 878 void VisitWordCompareZero(InstructionSelector* selector, Node* user, | 849 void VisitWordCompareZero(InstructionSelector* selector, Node* user, |
| 879 Node* value, FlagsContinuation* cont) { | 850 Node* value, FlagsContinuation* cont) { |
| 880 // Initially set comparison against 0 to be 64-bit variant for branches that | |
| 881 // cannot combine. | |
| 882 InstructionCode opcode = kMips64Cmp; | |
| 883 while (selector->CanCover(user, value)) { | 851 while (selector->CanCover(user, value)) { |
| 884 if (user->opcode() == IrOpcode::kWord32Equal) { | |
| 885 opcode = kMips64Cmp32; | |
| 886 } | |
| 887 switch (value->opcode()) { | 852 switch (value->opcode()) { |
| 888 case IrOpcode::kWord32Equal: { | 853 case IrOpcode::kWord32Equal: { |
| 889 // Combine with comparisons against 0 by simply inverting the | 854 // Combine with comparisons against 0 by simply inverting the |
| 890 // continuation. | 855 // continuation. |
| 891 Int32BinopMatcher m(value); | 856 Int32BinopMatcher m(value); |
| 892 if (m.right().Is(0)) { | 857 if (m.right().Is(0)) { |
| 893 user = value; | 858 user = value; |
| 894 value = m.left().node(); | 859 value = m.left().node(); |
| 895 cont->Negate(); | 860 cont->Negate(); |
| 896 opcode = kMips64Cmp32; | |
| 897 continue; | 861 continue; |
| 898 } | 862 } |
| 899 cont->OverwriteAndNegateIfEqual(kEqual); | 863 cont->OverwriteAndNegateIfEqual(kEqual); |
| 900 return VisitWord32Compare(selector, value, cont); | 864 return VisitWord32Compare(selector, value, cont); |
| 901 } | 865 } |
| 902 case IrOpcode::kInt32LessThan: | 866 case IrOpcode::kInt32LessThan: |
| 903 cont->OverwriteAndNegateIfEqual(kSignedLessThan); | 867 cont->OverwriteAndNegateIfEqual(kSignedLessThan); |
| 904 return VisitWord32Compare(selector, value, cont); | 868 return VisitWord32Compare(selector, value, cont); |
| 905 case IrOpcode::kInt32LessThanOrEqual: | 869 case IrOpcode::kInt32LessThanOrEqual: |
| 906 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); | 870 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 case IrOpcode::kInt32SubWithOverflow: | 925 case IrOpcode::kInt32SubWithOverflow: |
| 962 cont->OverwriteAndNegateIfEqual(kOverflow); | 926 cont->OverwriteAndNegateIfEqual(kOverflow); |
| 963 return VisitBinop(selector, node, kMips64Dsub, cont); | 927 return VisitBinop(selector, node, kMips64Dsub, cont); |
| 964 default: | 928 default: |
| 965 break; | 929 break; |
| 966 } | 930 } |
| 967 } | 931 } |
| 968 } | 932 } |
| 969 break; | 933 break; |
| 970 case IrOpcode::kWord32And: | 934 case IrOpcode::kWord32And: |
| 971 return VisitWordCompare(selector, value, kMips64Tst32, cont, true); | |
| 972 case IrOpcode::kWord64And: | 935 case IrOpcode::kWord64And: |
| 973 return VisitWordCompare(selector, value, kMips64Tst, cont, true); | 936 return VisitWordCompare(selector, value, kMips64Tst, cont, true); |
| 974 default: | 937 default: |
| 975 break; | 938 break; |
| 976 } | 939 } |
| 977 break; | 940 break; |
| 978 } | 941 } |
| 979 | 942 |
| 980 // Continuation could not be combined with a compare, emit compare against 0. | 943 // Continuation could not be combined with a compare, emit compare against 0. |
| 981 EmitWordCompareZero(selector, opcode, value, cont); | 944 EmitWordCompareZero(selector, value, cont); |
| 982 } | 945 } |
| 983 | 946 |
| 984 | 947 |
| 985 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 948 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
| 986 BasicBlock* fbranch) { | 949 BasicBlock* fbranch) { |
| 987 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 950 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
| 988 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); | 951 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); |
| 989 } | 952 } |
| 990 | 953 |
| 991 | 954 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1187 // static | 1150 // static |
| 1188 MachineOperatorBuilder::Flags | 1151 MachineOperatorBuilder::Flags |
| 1189 InstructionSelector::SupportedMachineOperatorFlags() { | 1152 InstructionSelector::SupportedMachineOperatorFlags() { |
| 1190 return MachineOperatorBuilder::kFloat64RoundDown | | 1153 return MachineOperatorBuilder::kFloat64RoundDown | |
| 1191 MachineOperatorBuilder::kFloat64RoundTruncate; | 1154 MachineOperatorBuilder::kFloat64RoundTruncate; |
| 1192 } | 1155 } |
| 1193 | 1156 |
| 1194 } // namespace compiler | 1157 } // namespace compiler |
| 1195 } // namespace internal | 1158 } // namespace internal |
| 1196 } // namespace v8 | 1159 } // namespace v8 |
| OLD | NEW |