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/instruction-selector-impl.h" | 5 #include "src/compiler/instruction-selector-impl.h" |
6 #include "src/compiler/node-matchers.h" | 6 #include "src/compiler/node-matchers.h" |
7 #include "src/compiler/node-properties.h" | 7 #include "src/compiler/node-properties.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 if (m.right().HasValue() && (m.right().Value() < 0) && | 277 if (m.right().HasValue() && (m.right().Value() < 0) && |
278 g.CanBeImmediate(-m.right().Value(), kArithmeticImm)) { | 278 g.CanBeImmediate(-m.right().Value(), kArithmeticImm)) { |
279 selector->Emit(negate_opcode, g.DefineAsRegister(node), | 279 selector->Emit(negate_opcode, g.DefineAsRegister(node), |
280 g.UseRegister(m.left().node()), | 280 g.UseRegister(m.left().node()), |
281 g.TempImmediate(static_cast<int32_t>(-m.right().Value()))); | 281 g.TempImmediate(static_cast<int32_t>(-m.right().Value()))); |
282 } else { | 282 } else { |
283 VisitBinop<Matcher>(selector, node, opcode, kArithmeticImm); | 283 VisitBinop<Matcher>(selector, node, opcode, kArithmeticImm); |
284 } | 284 } |
285 } | 285 } |
286 | 286 |
| 287 |
| 288 // For multiplications by immediate of the form x * (2^k + 1), where k > 0, |
| 289 // return the value of k, otherwise return zero. This is used to reduce the |
| 290 // multiplication to addition with left shift: x + (x << k). |
| 291 template <typename Matcher> |
| 292 int32_t LeftShiftForReducedMultiply(Matcher* m) { |
| 293 DCHECK(m->IsInt32Mul() || m->IsInt64Mul()); |
| 294 if (m->right().HasValue() && m->right().Value() >= 3) { |
| 295 uint64_t value_minus_one = m->right().Value() - 1; |
| 296 if (base::bits::IsPowerOfTwo64(value_minus_one)) { |
| 297 return WhichPowerOf2_64(value_minus_one); |
| 298 } |
| 299 } |
| 300 return 0; |
| 301 } |
| 302 |
287 } // namespace | 303 } // namespace |
288 | 304 |
289 | 305 |
290 void InstructionSelector::VisitLoad(Node* node) { | 306 void InstructionSelector::VisitLoad(Node* node) { |
291 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 307 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
292 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 308 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
293 Arm64OperandGenerator g(this); | 309 Arm64OperandGenerator g(this); |
294 Node* base = node->InputAt(0); | 310 Node* base = node->InputAt(0); |
295 Node* index = node->InputAt(1); | 311 Node* index = node->InputAt(1); |
296 ArchOpcode opcode; | 312 ArchOpcode opcode; |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 Emit(kArm64Clz32, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); | 852 Emit(kArm64Clz32, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); |
837 } | 853 } |
838 | 854 |
839 | 855 |
840 void InstructionSelector::VisitInt32Add(Node* node) { | 856 void InstructionSelector::VisitInt32Add(Node* node) { |
841 Arm64OperandGenerator g(this); | 857 Arm64OperandGenerator g(this); |
842 Int32BinopMatcher m(node); | 858 Int32BinopMatcher m(node); |
843 // Select Madd(x, y, z) for Add(Mul(x, y), z). | 859 // Select Madd(x, y, z) for Add(Mul(x, y), z). |
844 if (m.left().IsInt32Mul() && CanCover(node, m.left().node())) { | 860 if (m.left().IsInt32Mul() && CanCover(node, m.left().node())) { |
845 Int32BinopMatcher mleft(m.left().node()); | 861 Int32BinopMatcher mleft(m.left().node()); |
846 Emit(kArm64Madd32, g.DefineAsRegister(node), | 862 // Check multiply can't be later reduced to addition with shift. |
847 g.UseRegister(mleft.left().node()), | 863 if (LeftShiftForReducedMultiply(&mleft) == 0) { |
848 g.UseRegister(mleft.right().node()), g.UseRegister(m.right().node())); | 864 Emit(kArm64Madd32, g.DefineAsRegister(node), |
849 return; | 865 g.UseRegister(mleft.left().node()), |
| 866 g.UseRegister(mleft.right().node()), |
| 867 g.UseRegister(m.right().node())); |
| 868 return; |
| 869 } |
850 } | 870 } |
851 // Select Madd(x, y, z) for Add(x, Mul(x, y)). | 871 // Select Madd(x, y, z) for Add(z, Mul(x, y)). |
852 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { | 872 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { |
853 Int32BinopMatcher mright(m.right().node()); | 873 Int32BinopMatcher mright(m.right().node()); |
854 Emit(kArm64Madd32, g.DefineAsRegister(node), | 874 // Check multiply can't be later reduced to addition with shift. |
855 g.UseRegister(mright.left().node()), | 875 if (LeftShiftForReducedMultiply(&mright) == 0) { |
856 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 876 Emit(kArm64Madd32, g.DefineAsRegister(node), |
857 return; | 877 g.UseRegister(mright.left().node()), |
| 878 g.UseRegister(mright.right().node()), |
| 879 g.UseRegister(m.left().node())); |
| 880 return; |
| 881 } |
858 } | 882 } |
859 VisitAddSub<Int32BinopMatcher>(this, node, kArm64Add32, kArm64Sub32); | 883 VisitAddSub<Int32BinopMatcher>(this, node, kArm64Add32, kArm64Sub32); |
860 } | 884 } |
861 | 885 |
862 | 886 |
863 void InstructionSelector::VisitInt64Add(Node* node) { | 887 void InstructionSelector::VisitInt64Add(Node* node) { |
864 Arm64OperandGenerator g(this); | 888 Arm64OperandGenerator g(this); |
865 Int64BinopMatcher m(node); | 889 Int64BinopMatcher m(node); |
866 // Select Madd(x, y, z) for Add(Mul(x, y), z). | 890 // Select Madd(x, y, z) for Add(Mul(x, y), z). |
867 if (m.left().IsInt64Mul() && CanCover(node, m.left().node())) { | 891 if (m.left().IsInt64Mul() && CanCover(node, m.left().node())) { |
868 Int64BinopMatcher mleft(m.left().node()); | 892 Int64BinopMatcher mleft(m.left().node()); |
869 Emit(kArm64Madd, g.DefineAsRegister(node), | 893 // Check multiply can't be later reduced to addition with shift. |
870 g.UseRegister(mleft.left().node()), | 894 if (LeftShiftForReducedMultiply(&mleft) == 0) { |
871 g.UseRegister(mleft.right().node()), g.UseRegister(m.right().node())); | 895 Emit(kArm64Madd, g.DefineAsRegister(node), |
872 return; | 896 g.UseRegister(mleft.left().node()), |
| 897 g.UseRegister(mleft.right().node()), |
| 898 g.UseRegister(m.right().node())); |
| 899 return; |
| 900 } |
873 } | 901 } |
874 // Select Madd(x, y, z) for Add(x, Mul(x, y)). | 902 // Select Madd(x, y, z) for Add(z, Mul(x, y)). |
875 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { | 903 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { |
876 Int64BinopMatcher mright(m.right().node()); | 904 Int64BinopMatcher mright(m.right().node()); |
877 Emit(kArm64Madd, g.DefineAsRegister(node), | 905 // Check multiply can't be later reduced to addition with shift. |
878 g.UseRegister(mright.left().node()), | 906 if (LeftShiftForReducedMultiply(&mright) == 0) { |
879 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 907 Emit(kArm64Madd, g.DefineAsRegister(node), |
880 return; | 908 g.UseRegister(mright.left().node()), |
| 909 g.UseRegister(mright.right().node()), |
| 910 g.UseRegister(m.left().node())); |
| 911 return; |
| 912 } |
881 } | 913 } |
882 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Add, kArm64Sub); | 914 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Add, kArm64Sub); |
883 } | 915 } |
884 | 916 |
885 | 917 |
886 void InstructionSelector::VisitInt32Sub(Node* node) { | 918 void InstructionSelector::VisitInt32Sub(Node* node) { |
887 Arm64OperandGenerator g(this); | 919 Arm64OperandGenerator g(this); |
888 Int32BinopMatcher m(node); | 920 Int32BinopMatcher m(node); |
889 | 921 |
890 // Select Msub(a, x, y) for Sub(a, Mul(x, y)). | 922 // Select Msub(x, y, a) for Sub(a, Mul(x, y)). |
891 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { | 923 if (m.right().IsInt32Mul() && CanCover(node, m.right().node())) { |
892 Int32BinopMatcher mright(m.right().node()); | 924 Int32BinopMatcher mright(m.right().node()); |
893 Emit(kArm64Msub32, g.DefineAsRegister(node), | 925 // Check multiply can't be later reduced to addition with shift. |
894 g.UseRegister(mright.left().node()), | 926 if (LeftShiftForReducedMultiply(&mright) == 0) { |
895 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 927 Emit(kArm64Msub32, g.DefineAsRegister(node), |
896 return; | 928 g.UseRegister(mright.left().node()), |
| 929 g.UseRegister(mright.right().node()), |
| 930 g.UseRegister(m.left().node())); |
| 931 return; |
| 932 } |
897 } | 933 } |
898 | 934 |
899 if (m.left().Is(0)) { | 935 if (m.left().Is(0)) { |
900 Emit(kArm64Neg32, g.DefineAsRegister(node), | 936 Emit(kArm64Neg32, g.DefineAsRegister(node), |
901 g.UseRegister(m.right().node())); | 937 g.UseRegister(m.right().node())); |
902 } else { | 938 } else { |
903 VisitAddSub<Int32BinopMatcher>(this, node, kArm64Sub32, kArm64Add32); | 939 VisitAddSub<Int32BinopMatcher>(this, node, kArm64Sub32, kArm64Add32); |
904 } | 940 } |
905 } | 941 } |
906 | 942 |
907 | 943 |
908 void InstructionSelector::VisitInt64Sub(Node* node) { | 944 void InstructionSelector::VisitInt64Sub(Node* node) { |
909 Arm64OperandGenerator g(this); | 945 Arm64OperandGenerator g(this); |
910 Int64BinopMatcher m(node); | 946 Int64BinopMatcher m(node); |
911 | 947 |
912 // Select Msub(a, x, y) for Sub(a, Mul(x, y)). | 948 // Select Msub(x, y, a) for Sub(a, Mul(x, y)). |
913 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { | 949 if (m.right().IsInt64Mul() && CanCover(node, m.right().node())) { |
914 Int64BinopMatcher mright(m.right().node()); | 950 Int64BinopMatcher mright(m.right().node()); |
915 Emit(kArm64Msub, g.DefineAsRegister(node), | 951 // Check multiply can't be later reduced to addition with shift. |
916 g.UseRegister(mright.left().node()), | 952 if (LeftShiftForReducedMultiply(&mright) == 0) { |
917 g.UseRegister(mright.right().node()), g.UseRegister(m.left().node())); | 953 Emit(kArm64Msub, g.DefineAsRegister(node), |
918 return; | 954 g.UseRegister(mright.left().node()), |
| 955 g.UseRegister(mright.right().node()), |
| 956 g.UseRegister(m.left().node())); |
| 957 return; |
| 958 } |
919 } | 959 } |
920 | 960 |
921 if (m.left().Is(0)) { | 961 if (m.left().Is(0)) { |
922 Emit(kArm64Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node())); | 962 Emit(kArm64Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node())); |
923 } else { | 963 } else { |
924 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Sub, kArm64Add); | 964 VisitAddSub<Int64BinopMatcher>(this, node, kArm64Sub, kArm64Add); |
925 } | 965 } |
926 } | 966 } |
927 | 967 |
928 | 968 |
929 void InstructionSelector::VisitInt32Mul(Node* node) { | 969 void InstructionSelector::VisitInt32Mul(Node* node) { |
930 Arm64OperandGenerator g(this); | 970 Arm64OperandGenerator g(this); |
931 Int32BinopMatcher m(node); | 971 Int32BinopMatcher m(node); |
932 | 972 |
| 973 // First, try to reduce the multiplication to addition with left shift. |
| 974 // x * (2^k + 1) -> x + (x << k) |
| 975 int32_t shift = LeftShiftForReducedMultiply(&m); |
| 976 if (shift > 0) { |
| 977 Emit(kArm64Add32 | AddressingModeField::encode(kMode_Operand2_R_LSL_I), |
| 978 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 979 g.UseRegister(m.left().node()), g.TempImmediate(shift)); |
| 980 return; |
| 981 } |
| 982 |
933 if (m.left().IsInt32Sub() && CanCover(node, m.left().node())) { | 983 if (m.left().IsInt32Sub() && CanCover(node, m.left().node())) { |
934 Int32BinopMatcher mleft(m.left().node()); | 984 Int32BinopMatcher mleft(m.left().node()); |
935 | 985 |
936 // Select Mneg(x, y) for Mul(Sub(0, x), y). | 986 // Select Mneg(x, y) for Mul(Sub(0, x), y). |
937 if (mleft.left().Is(0)) { | 987 if (mleft.left().Is(0)) { |
938 Emit(kArm64Mneg32, g.DefineAsRegister(node), | 988 Emit(kArm64Mneg32, g.DefineAsRegister(node), |
939 g.UseRegister(mleft.right().node()), | 989 g.UseRegister(mleft.right().node()), |
940 g.UseRegister(m.right().node())); | 990 g.UseRegister(m.right().node())); |
941 return; | 991 return; |
942 } | 992 } |
943 } | 993 } |
944 | 994 |
945 if (m.right().IsInt32Sub() && CanCover(node, m.right().node())) { | 995 if (m.right().IsInt32Sub() && CanCover(node, m.right().node())) { |
946 Int32BinopMatcher mright(m.right().node()); | 996 Int32BinopMatcher mright(m.right().node()); |
947 | 997 |
948 // Select Mneg(x, y) for Mul(x, Sub(0, y)). | 998 // Select Mneg(x, y) for Mul(x, Sub(0, y)). |
949 if (mright.left().Is(0)) { | 999 if (mright.left().Is(0)) { |
950 Emit(kArm64Mneg32, g.DefineAsRegister(node), | 1000 Emit(kArm64Mneg32, g.DefineAsRegister(node), |
951 g.UseRegister(m.left().node()), | 1001 g.UseRegister(m.left().node()), |
952 g.UseRegister(mright.right().node())); | 1002 g.UseRegister(mright.right().node())); |
953 return; | 1003 return; |
954 } | 1004 } |
955 } | 1005 } |
956 | 1006 |
957 // x * (2^k + 1) -> x + (x << k) | |
958 if (m.right().HasValue() && m.right().Value() > 0) { | |
959 int32_t value = m.right().Value(); | |
960 if (base::bits::IsPowerOfTwo32(value - 1)) { | |
961 Emit(kArm64Add32 | AddressingModeField::encode(kMode_Operand2_R_LSL_I), | |
962 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | |
963 g.UseRegister(m.left().node()), | |
964 g.TempImmediate(WhichPowerOf2(value - 1))); | |
965 return; | |
966 } | |
967 } | |
968 | |
969 VisitRRR(this, kArm64Mul32, node); | 1007 VisitRRR(this, kArm64Mul32, node); |
970 } | 1008 } |
971 | 1009 |
972 | 1010 |
973 void InstructionSelector::VisitInt64Mul(Node* node) { | 1011 void InstructionSelector::VisitInt64Mul(Node* node) { |
974 Arm64OperandGenerator g(this); | 1012 Arm64OperandGenerator g(this); |
975 Int64BinopMatcher m(node); | 1013 Int64BinopMatcher m(node); |
976 | 1014 |
| 1015 // First, try to reduce the multiplication to addition with left shift. |
| 1016 // x * (2^k + 1) -> x + (x << k) |
| 1017 int32_t shift = LeftShiftForReducedMultiply(&m); |
| 1018 if (shift > 0) { |
| 1019 Emit(kArm64Add | AddressingModeField::encode(kMode_Operand2_R_LSL_I), |
| 1020 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 1021 g.UseRegister(m.left().node()), g.TempImmediate(shift)); |
| 1022 return; |
| 1023 } |
| 1024 |
977 if (m.left().IsInt64Sub() && CanCover(node, m.left().node())) { | 1025 if (m.left().IsInt64Sub() && CanCover(node, m.left().node())) { |
978 Int64BinopMatcher mleft(m.left().node()); | 1026 Int64BinopMatcher mleft(m.left().node()); |
979 | 1027 |
980 // Select Mneg(x, y) for Mul(Sub(0, x), y). | 1028 // Select Mneg(x, y) for Mul(Sub(0, x), y). |
981 if (mleft.left().Is(0)) { | 1029 if (mleft.left().Is(0)) { |
982 Emit(kArm64Mneg, g.DefineAsRegister(node), | 1030 Emit(kArm64Mneg, g.DefineAsRegister(node), |
983 g.UseRegister(mleft.right().node()), | 1031 g.UseRegister(mleft.right().node()), |
984 g.UseRegister(m.right().node())); | 1032 g.UseRegister(m.right().node())); |
985 return; | 1033 return; |
986 } | 1034 } |
987 } | 1035 } |
988 | 1036 |
989 if (m.right().IsInt64Sub() && CanCover(node, m.right().node())) { | 1037 if (m.right().IsInt64Sub() && CanCover(node, m.right().node())) { |
990 Int64BinopMatcher mright(m.right().node()); | 1038 Int64BinopMatcher mright(m.right().node()); |
991 | 1039 |
992 // Select Mneg(x, y) for Mul(x, Sub(0, y)). | 1040 // Select Mneg(x, y) for Mul(x, Sub(0, y)). |
993 if (mright.left().Is(0)) { | 1041 if (mright.left().Is(0)) { |
994 Emit(kArm64Mneg, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 1042 Emit(kArm64Mneg, g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
995 g.UseRegister(mright.right().node())); | 1043 g.UseRegister(mright.right().node())); |
996 return; | 1044 return; |
997 } | 1045 } |
998 } | 1046 } |
999 | 1047 |
1000 // x * (2^k + 1) -> x + (x << k) | |
1001 if (m.right().HasValue() && m.right().Value() > 0) { | |
1002 int64_t value = m.right().Value(); | |
1003 if (base::bits::IsPowerOfTwo64(value - 1)) { | |
1004 Emit(kArm64Add | AddressingModeField::encode(kMode_Operand2_R_LSL_I), | |
1005 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | |
1006 g.UseRegister(m.left().node()), | |
1007 g.TempImmediate(WhichPowerOf2_64(value - 1))); | |
1008 return; | |
1009 } | |
1010 } | |
1011 | |
1012 VisitRRR(this, kArm64Mul, node); | 1048 VisitRRR(this, kArm64Mul, node); |
1013 } | 1049 } |
1014 | 1050 |
1015 | 1051 |
1016 void InstructionSelector::VisitInt32MulHigh(Node* node) { | 1052 void InstructionSelector::VisitInt32MulHigh(Node* node) { |
1017 Arm64OperandGenerator g(this); | 1053 Arm64OperandGenerator g(this); |
1018 InstructionOperand const smull_operand = g.TempRegister(); | 1054 InstructionOperand const smull_operand = g.TempRegister(); |
1019 Emit(kArm64Smull, smull_operand, g.UseRegister(node->InputAt(0)), | 1055 Emit(kArm64Smull, smull_operand, g.UseRegister(node->InputAt(0)), |
1020 g.UseRegister(node->InputAt(1))); | 1056 g.UseRegister(node->InputAt(1))); |
1021 Emit(kArm64Asr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32)); | 1057 Emit(kArm64Asr, g.DefineAsRegister(node), smull_operand, g.TempImmediate(32)); |
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1968 MachineOperatorBuilder::kFloat64RoundTruncate | | 2004 MachineOperatorBuilder::kFloat64RoundTruncate | |
1969 MachineOperatorBuilder::kFloat64RoundTiesAway | | 2005 MachineOperatorBuilder::kFloat64RoundTiesAway | |
1970 MachineOperatorBuilder::kWord32ShiftIsSafe | | 2006 MachineOperatorBuilder::kWord32ShiftIsSafe | |
1971 MachineOperatorBuilder::kInt32DivIsSafe | | 2007 MachineOperatorBuilder::kInt32DivIsSafe | |
1972 MachineOperatorBuilder::kUint32DivIsSafe; | 2008 MachineOperatorBuilder::kUint32DivIsSafe; |
1973 } | 2009 } |
1974 | 2010 |
1975 } // namespace compiler | 2011 } // namespace compiler |
1976 } // namespace internal | 2012 } // namespace internal |
1977 } // namespace v8 | 2013 } // namespace v8 |
OLD | NEW |