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 |