| 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 "test/unittests/compiler/instruction-selector-unittest.h" | 5 #include "test/unittests/compiler/instruction-selector-unittest.h" |
| 6 | 6 |
| 7 namespace v8 { | 7 namespace v8 { |
| 8 namespace internal { | 8 namespace internal { |
| 9 namespace compiler { | 9 namespace compiler { |
| 10 | 10 |
| 11 namespace { | 11 namespace { |
| 12 | 12 |
| 13 typedef RawMachineAssembler::Label MLabel; | |
| 14 | |
| 15 template <typename T> | 13 template <typename T> |
| 16 struct MachInst { | 14 struct MachInst { |
| 17 T constructor; | 15 T constructor; |
| 18 const char* constructor_name; | 16 const char* constructor_name; |
| 19 ArchOpcode arch_opcode; | 17 ArchOpcode arch_opcode; |
| 20 MachineType machine_type; | 18 MachineType machine_type; |
| 21 }; | 19 }; |
| 22 | 20 |
| 23 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; | 21 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; |
| 24 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; | 22 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 | 868 |
| 871 | 869 |
| 872 typedef InstructionSelectorTestWithParam<MachInst2> | 870 typedef InstructionSelectorTestWithParam<MachInst2> |
| 873 InstructionSelectorDPFlagSetTest; | 871 InstructionSelectorDPFlagSetTest; |
| 874 | 872 |
| 875 | 873 |
| 876 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) { | 874 TEST_P(InstructionSelectorDPFlagSetTest, BranchWithParameters) { |
| 877 const MachInst2 dpi = GetParam(); | 875 const MachInst2 dpi = GetParam(); |
| 878 const MachineType type = dpi.machine_type; | 876 const MachineType type = dpi.machine_type; |
| 879 StreamBuilder m(this, type, type, type); | 877 StreamBuilder m(this, type, type, type); |
| 880 MLabel a, b; | 878 RawLabel a, b; |
| 881 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b); | 879 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b); |
| 882 m.Bind(&a); | 880 m.Bind(&a); |
| 883 m.Return(m.Int32Constant(1)); | 881 m.Return(m.Int32Constant(1)); |
| 884 m.Bind(&b); | 882 m.Bind(&b); |
| 885 m.Return(m.Int32Constant(0)); | 883 m.Return(m.Int32Constant(0)); |
| 886 Stream s = m.Build(); | 884 Stream s = m.Build(); |
| 887 ASSERT_EQ(1U, s.size()); | 885 ASSERT_EQ(1U, s.size()); |
| 888 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 886 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 889 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | 887 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 890 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 888 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 891 } | 889 } |
| 892 | 890 |
| 893 | 891 |
| 894 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | 892 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| 895 InstructionSelectorDPFlagSetTest, | 893 InstructionSelectorDPFlagSetTest, |
| 896 ::testing::ValuesIn(kDPFlagSetInstructions)); | 894 ::testing::ValuesIn(kDPFlagSetInstructions)); |
| 897 | 895 |
| 898 | 896 |
| 899 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnRight) { | 897 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnRight) { |
| 900 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) { | 898 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) { |
| 901 // Skip the cases where the instruction selector would use tbz/tbnz. | 899 // Skip the cases where the instruction selector would use tbz/tbnz. |
| 902 if (base::bits::CountPopulation32(imm) == 1) continue; | 900 if (base::bits::CountPopulation32(imm) == 1) continue; |
| 903 | 901 |
| 904 StreamBuilder m(this, kMachInt32, kMachInt32); | 902 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 905 MLabel a, b; | 903 RawLabel a, b; |
| 906 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b); | 904 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(imm)), &a, &b); |
| 907 m.Bind(&a); | 905 m.Bind(&a); |
| 908 m.Return(m.Int32Constant(1)); | 906 m.Return(m.Int32Constant(1)); |
| 909 m.Bind(&b); | 907 m.Bind(&b); |
| 910 m.Return(m.Int32Constant(0)); | 908 m.Return(m.Int32Constant(0)); |
| 911 Stream s = m.Build(); | 909 Stream s = m.Build(); |
| 912 ASSERT_EQ(1U, s.size()); | 910 ASSERT_EQ(1U, s.size()); |
| 913 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode()); | 911 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode()); |
| 914 EXPECT_EQ(4U, s[0]->InputCount()); | 912 EXPECT_EQ(4U, s[0]->InputCount()); |
| 915 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 913 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 916 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | 914 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 917 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 915 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 918 } | 916 } |
| 919 } | 917 } |
| 920 | 918 |
| 921 | 919 |
| 922 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnRight) { | 920 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnRight) { |
| 923 TRACED_FOREACH(int64_t, imm, kLogical64Immediates) { | 921 TRACED_FOREACH(int64_t, imm, kLogical64Immediates) { |
| 924 // Skip the cases where the instruction selector would use tbz/tbnz. | 922 // Skip the cases where the instruction selector would use tbz/tbnz. |
| 925 if (base::bits::CountPopulation64(imm) == 1) continue; | 923 if (base::bits::CountPopulation64(imm) == 1) continue; |
| 926 | 924 |
| 927 StreamBuilder m(this, kMachInt64, kMachInt64); | 925 StreamBuilder m(this, kMachInt64, kMachInt64); |
| 928 MLabel a, b; | 926 RawLabel a, b; |
| 929 m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(imm)), &a, &b); | 927 m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(imm)), &a, &b); |
| 930 m.Bind(&a); | 928 m.Bind(&a); |
| 931 m.Return(m.Int32Constant(1)); | 929 m.Return(m.Int32Constant(1)); |
| 932 m.Bind(&b); | 930 m.Bind(&b); |
| 933 m.Return(m.Int32Constant(0)); | 931 m.Return(m.Int32Constant(0)); |
| 934 Stream s = m.Build(); | 932 Stream s = m.Build(); |
| 935 ASSERT_EQ(1U, s.size()); | 933 ASSERT_EQ(1U, s.size()); |
| 936 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode()); | 934 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode()); |
| 937 EXPECT_EQ(4U, s[0]->InputCount()); | 935 EXPECT_EQ(4U, s[0]->InputCount()); |
| 938 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 936 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 939 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | 937 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 940 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 938 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 941 } | 939 } |
| 942 } | 940 } |
| 943 | 941 |
| 944 | 942 |
| 945 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) { | 943 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnRight) { |
| 946 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | 944 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 947 StreamBuilder m(this, kMachInt32, kMachInt32); | 945 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 948 MLabel a, b; | 946 RawLabel a, b; |
| 949 m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b); | 947 m.Branch(m.Int32Add(m.Parameter(0), m.Int32Constant(imm)), &a, &b); |
| 950 m.Bind(&a); | 948 m.Bind(&a); |
| 951 m.Return(m.Int32Constant(1)); | 949 m.Return(m.Int32Constant(1)); |
| 952 m.Bind(&b); | 950 m.Bind(&b); |
| 953 m.Return(m.Int32Constant(0)); | 951 m.Return(m.Int32Constant(0)); |
| 954 Stream s = m.Build(); | 952 Stream s = m.Build(); |
| 955 ASSERT_EQ(1U, s.size()); | 953 ASSERT_EQ(1U, s.size()); |
| 956 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode()); | 954 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode()); |
| 957 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | 955 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 958 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 956 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 959 } | 957 } |
| 960 } | 958 } |
| 961 | 959 |
| 962 | 960 |
| 963 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) { | 961 TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) { |
| 964 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | 962 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 965 StreamBuilder m(this, kMachInt32, kMachInt32); | 963 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 966 MLabel a, b; | 964 RawLabel a, b; |
| 967 m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b); | 965 m.Branch(m.Int32Sub(m.Parameter(0), m.Int32Constant(imm)), &a, &b); |
| 968 m.Bind(&a); | 966 m.Bind(&a); |
| 969 m.Return(m.Int32Constant(1)); | 967 m.Return(m.Int32Constant(1)); |
| 970 m.Bind(&b); | 968 m.Bind(&b); |
| 971 m.Return(m.Int32Constant(0)); | 969 m.Return(m.Int32Constant(0)); |
| 972 Stream s = m.Build(); | 970 Stream s = m.Build(); |
| 973 ASSERT_EQ(1U, s.size()); | 971 ASSERT_EQ(1U, s.size()); |
| 974 EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); | 972 EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode()); |
| 975 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | 973 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 976 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 974 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 977 } | 975 } |
| 978 } | 976 } |
| 979 | 977 |
| 980 | 978 |
| 981 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnLeft) { | 979 TEST_F(InstructionSelectorTest, Word32AndBranchWithImmediateOnLeft) { |
| 982 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) { | 980 TRACED_FOREACH(int32_t, imm, kLogical32Immediates) { |
| 983 // Skip the cases where the instruction selector would use tbz/tbnz. | 981 // Skip the cases where the instruction selector would use tbz/tbnz. |
| 984 if (base::bits::CountPopulation32(imm) == 1) continue; | 982 if (base::bits::CountPopulation32(imm) == 1) continue; |
| 985 | 983 |
| 986 StreamBuilder m(this, kMachInt32, kMachInt32); | 984 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 987 MLabel a, b; | 985 RawLabel a, b; |
| 988 m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b); | 986 m.Branch(m.Word32And(m.Int32Constant(imm), m.Parameter(0)), &a, &b); |
| 989 m.Bind(&a); | 987 m.Bind(&a); |
| 990 m.Return(m.Int32Constant(1)); | 988 m.Return(m.Int32Constant(1)); |
| 991 m.Bind(&b); | 989 m.Bind(&b); |
| 992 m.Return(m.Int32Constant(0)); | 990 m.Return(m.Int32Constant(0)); |
| 993 Stream s = m.Build(); | 991 Stream s = m.Build(); |
| 994 ASSERT_EQ(1U, s.size()); | 992 ASSERT_EQ(1U, s.size()); |
| 995 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode()); | 993 EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode()); |
| 996 EXPECT_EQ(4U, s[0]->InputCount()); | 994 EXPECT_EQ(4U, s[0]->InputCount()); |
| 997 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 995 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 998 ASSERT_LE(1U, s[0]->InputCount()); | 996 ASSERT_LE(1U, s[0]->InputCount()); |
| 999 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | 997 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 1000 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 998 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 1001 } | 999 } |
| 1002 } | 1000 } |
| 1003 | 1001 |
| 1004 | 1002 |
| 1005 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnLeft) { | 1003 TEST_F(InstructionSelectorTest, Word64AndBranchWithImmediateOnLeft) { |
| 1006 TRACED_FOREACH(int64_t, imm, kLogical64Immediates) { | 1004 TRACED_FOREACH(int64_t, imm, kLogical64Immediates) { |
| 1007 // Skip the cases where the instruction selector would use tbz/tbnz. | 1005 // Skip the cases where the instruction selector would use tbz/tbnz. |
| 1008 if (base::bits::CountPopulation64(imm) == 1) continue; | 1006 if (base::bits::CountPopulation64(imm) == 1) continue; |
| 1009 | 1007 |
| 1010 StreamBuilder m(this, kMachInt64, kMachInt64); | 1008 StreamBuilder m(this, kMachInt64, kMachInt64); |
| 1011 MLabel a, b; | 1009 RawLabel a, b; |
| 1012 m.Branch(m.Word64And(m.Int64Constant(imm), m.Parameter(0)), &a, &b); | 1010 m.Branch(m.Word64And(m.Int64Constant(imm), m.Parameter(0)), &a, &b); |
| 1013 m.Bind(&a); | 1011 m.Bind(&a); |
| 1014 m.Return(m.Int32Constant(1)); | 1012 m.Return(m.Int32Constant(1)); |
| 1015 m.Bind(&b); | 1013 m.Bind(&b); |
| 1016 m.Return(m.Int32Constant(0)); | 1014 m.Return(m.Int32Constant(0)); |
| 1017 Stream s = m.Build(); | 1015 Stream s = m.Build(); |
| 1018 ASSERT_EQ(1U, s.size()); | 1016 ASSERT_EQ(1U, s.size()); |
| 1019 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode()); | 1017 EXPECT_EQ(kArm64Tst, s[0]->arch_opcode()); |
| 1020 EXPECT_EQ(4U, s[0]->InputCount()); | 1018 EXPECT_EQ(4U, s[0]->InputCount()); |
| 1021 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 1019 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 1022 ASSERT_LE(1U, s[0]->InputCount()); | 1020 ASSERT_LE(1U, s[0]->InputCount()); |
| 1023 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | 1021 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 1024 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 1022 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 1025 } | 1023 } |
| 1026 } | 1024 } |
| 1027 | 1025 |
| 1028 | 1026 |
| 1029 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) { | 1027 TEST_F(InstructionSelectorTest, AddBranchWithImmediateOnLeft) { |
| 1030 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | 1028 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 1031 StreamBuilder m(this, kMachInt32, kMachInt32); | 1029 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 1032 MLabel a, b; | 1030 RawLabel a, b; |
| 1033 m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b); | 1031 m.Branch(m.Int32Add(m.Int32Constant(imm), m.Parameter(0)), &a, &b); |
| 1034 m.Bind(&a); | 1032 m.Bind(&a); |
| 1035 m.Return(m.Int32Constant(1)); | 1033 m.Return(m.Int32Constant(1)); |
| 1036 m.Bind(&b); | 1034 m.Bind(&b); |
| 1037 m.Return(m.Int32Constant(0)); | 1035 m.Return(m.Int32Constant(0)); |
| 1038 Stream s = m.Build(); | 1036 Stream s = m.Build(); |
| 1039 ASSERT_EQ(1U, s.size()); | 1037 ASSERT_EQ(1U, s.size()); |
| 1040 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode()); | 1038 EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode()); |
| 1041 ASSERT_LE(1U, s[0]->InputCount()); | 1039 ASSERT_LE(1U, s[0]->InputCount()); |
| 1042 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | 1040 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 1043 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 1041 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 1044 } | 1042 } |
| 1045 } | 1043 } |
| 1046 | 1044 |
| 1047 | 1045 |
| 1048 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) { | 1046 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) { |
| 1049 TRACED_FORRANGE(int, bit, 0, 31) { | 1047 TRACED_FORRANGE(int, bit, 0, 31) { |
| 1050 uint32_t mask = 1 << bit; | 1048 uint32_t mask = 1 << bit; |
| 1051 StreamBuilder m(this, kMachInt32, kMachInt32); | 1049 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 1052 MLabel a, b; | 1050 RawLabel a, b; |
| 1053 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(mask)), &a, &b); | 1051 m.Branch(m.Word32And(m.Parameter(0), m.Int32Constant(mask)), &a, &b); |
| 1054 m.Bind(&a); | 1052 m.Bind(&a); |
| 1055 m.Return(m.Int32Constant(1)); | 1053 m.Return(m.Int32Constant(1)); |
| 1056 m.Bind(&b); | 1054 m.Bind(&b); |
| 1057 m.Return(m.Int32Constant(0)); | 1055 m.Return(m.Int32Constant(0)); |
| 1058 Stream s = m.Build(); | 1056 Stream s = m.Build(); |
| 1059 ASSERT_EQ(1U, s.size()); | 1057 ASSERT_EQ(1U, s.size()); |
| 1060 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode()); | 1058 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode()); |
| 1061 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 1059 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 1062 EXPECT_EQ(4U, s[0]->InputCount()); | 1060 EXPECT_EQ(4U, s[0]->InputCount()); |
| 1063 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 1061 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 1064 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1))); | 1062 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1))); |
| 1065 } | 1063 } |
| 1066 | 1064 |
| 1067 TRACED_FORRANGE(int, bit, 0, 31) { | 1065 TRACED_FORRANGE(int, bit, 0, 31) { |
| 1068 uint32_t mask = 1 << bit; | 1066 uint32_t mask = 1 << bit; |
| 1069 StreamBuilder m(this, kMachInt32, kMachInt32); | 1067 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 1070 MLabel a, b; | 1068 RawLabel a, b; |
| 1071 m.Branch( | 1069 m.Branch( |
| 1072 m.Word32BinaryNot(m.Word32And(m.Parameter(0), m.Int32Constant(mask))), | 1070 m.Word32BinaryNot(m.Word32And(m.Parameter(0), m.Int32Constant(mask))), |
| 1073 &a, &b); | 1071 &a, &b); |
| 1074 m.Bind(&a); | 1072 m.Bind(&a); |
| 1075 m.Return(m.Int32Constant(1)); | 1073 m.Return(m.Int32Constant(1)); |
| 1076 m.Bind(&b); | 1074 m.Bind(&b); |
| 1077 m.Return(m.Int32Constant(0)); | 1075 m.Return(m.Int32Constant(0)); |
| 1078 Stream s = m.Build(); | 1076 Stream s = m.Build(); |
| 1079 ASSERT_EQ(1U, s.size()); | 1077 ASSERT_EQ(1U, s.size()); |
| 1080 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode()); | 1078 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode()); |
| 1081 EXPECT_EQ(kEqual, s[0]->flags_condition()); | 1079 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1082 EXPECT_EQ(4U, s[0]->InputCount()); | 1080 EXPECT_EQ(4U, s[0]->InputCount()); |
| 1083 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 1081 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 1084 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1))); | 1082 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1))); |
| 1085 } | 1083 } |
| 1086 } | 1084 } |
| 1087 | 1085 |
| 1088 | 1086 |
| 1089 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) { | 1087 TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) { |
| 1090 TRACED_FORRANGE(int, bit, 0, 31) { | 1088 TRACED_FORRANGE(int, bit, 0, 31) { |
| 1091 uint32_t mask = 1 << bit; | 1089 uint32_t mask = 1 << bit; |
| 1092 StreamBuilder m(this, kMachInt32, kMachInt32); | 1090 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 1093 MLabel a, b; | 1091 RawLabel a, b; |
| 1094 m.Branch(m.Word32And(m.Int32Constant(mask), m.Parameter(0)), &a, &b); | 1092 m.Branch(m.Word32And(m.Int32Constant(mask), m.Parameter(0)), &a, &b); |
| 1095 m.Bind(&a); | 1093 m.Bind(&a); |
| 1096 m.Return(m.Int32Constant(1)); | 1094 m.Return(m.Int32Constant(1)); |
| 1097 m.Bind(&b); | 1095 m.Bind(&b); |
| 1098 m.Return(m.Int32Constant(0)); | 1096 m.Return(m.Int32Constant(0)); |
| 1099 Stream s = m.Build(); | 1097 Stream s = m.Build(); |
| 1100 ASSERT_EQ(1U, s.size()); | 1098 ASSERT_EQ(1U, s.size()); |
| 1101 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode()); | 1099 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode()); |
| 1102 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 1100 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 1103 EXPECT_EQ(4U, s[0]->InputCount()); | 1101 EXPECT_EQ(4U, s[0]->InputCount()); |
| 1104 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 1102 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 1105 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1))); | 1103 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1))); |
| 1106 } | 1104 } |
| 1107 | 1105 |
| 1108 TRACED_FORRANGE(int, bit, 0, 31) { | 1106 TRACED_FORRANGE(int, bit, 0, 31) { |
| 1109 uint32_t mask = 1 << bit; | 1107 uint32_t mask = 1 << bit; |
| 1110 StreamBuilder m(this, kMachInt32, kMachInt32); | 1108 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 1111 MLabel a, b; | 1109 RawLabel a, b; |
| 1112 m.Branch( | 1110 m.Branch( |
| 1113 m.Word32BinaryNot(m.Word32And(m.Int32Constant(mask), m.Parameter(0))), | 1111 m.Word32BinaryNot(m.Word32And(m.Int32Constant(mask), m.Parameter(0))), |
| 1114 &a, &b); | 1112 &a, &b); |
| 1115 m.Bind(&a); | 1113 m.Bind(&a); |
| 1116 m.Return(m.Int32Constant(1)); | 1114 m.Return(m.Int32Constant(1)); |
| 1117 m.Bind(&b); | 1115 m.Bind(&b); |
| 1118 m.Return(m.Int32Constant(0)); | 1116 m.Return(m.Int32Constant(0)); |
| 1119 Stream s = m.Build(); | 1117 Stream s = m.Build(); |
| 1120 ASSERT_EQ(1U, s.size()); | 1118 ASSERT_EQ(1U, s.size()); |
| 1121 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode()); | 1119 EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode()); |
| 1122 EXPECT_EQ(kEqual, s[0]->flags_condition()); | 1120 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1123 EXPECT_EQ(4U, s[0]->InputCount()); | 1121 EXPECT_EQ(4U, s[0]->InputCount()); |
| 1124 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 1122 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 1125 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1))); | 1123 EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1))); |
| 1126 } | 1124 } |
| 1127 } | 1125 } |
| 1128 | 1126 |
| 1129 | 1127 |
| 1130 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) { | 1128 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) { |
| 1131 TRACED_FORRANGE(int, bit, 0, 63) { | 1129 TRACED_FORRANGE(int, bit, 0, 63) { |
| 1132 uint64_t mask = 1L << bit; | 1130 uint64_t mask = 1L << bit; |
| 1133 StreamBuilder m(this, kMachInt64, kMachInt64); | 1131 StreamBuilder m(this, kMachInt64, kMachInt64); |
| 1134 MLabel a, b; | 1132 RawLabel a, b; |
| 1135 m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b); | 1133 m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b); |
| 1136 m.Bind(&a); | 1134 m.Bind(&a); |
| 1137 m.Return(m.Int32Constant(1)); | 1135 m.Return(m.Int32Constant(1)); |
| 1138 m.Bind(&b); | 1136 m.Bind(&b); |
| 1139 m.Return(m.Int32Constant(0)); | 1137 m.Return(m.Int32Constant(0)); |
| 1140 Stream s = m.Build(); | 1138 Stream s = m.Build(); |
| 1141 ASSERT_EQ(1U, s.size()); | 1139 ASSERT_EQ(1U, s.size()); |
| 1142 EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode()); | 1140 EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode()); |
| 1143 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 1141 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 1144 EXPECT_EQ(4U, s[0]->InputCount()); | 1142 EXPECT_EQ(4U, s[0]->InputCount()); |
| 1145 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 1143 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 1146 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1))); | 1144 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1))); |
| 1147 } | 1145 } |
| 1148 } | 1146 } |
| 1149 | 1147 |
| 1150 | 1148 |
| 1151 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) { | 1149 TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) { |
| 1152 TRACED_FORRANGE(int, bit, 0, 63) { | 1150 TRACED_FORRANGE(int, bit, 0, 63) { |
| 1153 uint64_t mask = 1L << bit; | 1151 uint64_t mask = 1L << bit; |
| 1154 StreamBuilder m(this, kMachInt64, kMachInt64); | 1152 StreamBuilder m(this, kMachInt64, kMachInt64); |
| 1155 MLabel a, b; | 1153 RawLabel a, b; |
| 1156 m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b); | 1154 m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b); |
| 1157 m.Bind(&a); | 1155 m.Bind(&a); |
| 1158 m.Return(m.Int32Constant(1)); | 1156 m.Return(m.Int32Constant(1)); |
| 1159 m.Bind(&b); | 1157 m.Bind(&b); |
| 1160 m.Return(m.Int32Constant(0)); | 1158 m.Return(m.Int32Constant(0)); |
| 1161 Stream s = m.Build(); | 1159 Stream s = m.Build(); |
| 1162 ASSERT_EQ(1U, s.size()); | 1160 ASSERT_EQ(1U, s.size()); |
| 1163 EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode()); | 1161 EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode()); |
| 1164 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 1162 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 1165 EXPECT_EQ(4U, s[0]->InputCount()); | 1163 EXPECT_EQ(4U, s[0]->InputCount()); |
| 1166 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | 1164 EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| 1167 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1))); | 1165 EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1))); |
| 1168 } | 1166 } |
| 1169 } | 1167 } |
| 1170 | 1168 |
| 1171 | 1169 |
| 1172 TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) { | 1170 TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) { |
| 1173 { | 1171 { |
| 1174 StreamBuilder m(this, kMachInt32, kMachInt32); | 1172 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 1175 MLabel a, b; | 1173 RawLabel a, b; |
| 1176 Node* p0 = m.Parameter(0); | 1174 Node* p0 = m.Parameter(0); |
| 1177 m.Branch(p0, &a, &b); | 1175 m.Branch(p0, &a, &b); |
| 1178 m.Bind(&a); | 1176 m.Bind(&a); |
| 1179 m.Return(m.Int32Constant(1)); | 1177 m.Return(m.Int32Constant(1)); |
| 1180 m.Bind(&b); | 1178 m.Bind(&b); |
| 1181 m.Return(m.Int32Constant(0)); | 1179 m.Return(m.Int32Constant(0)); |
| 1182 Stream s = m.Build(); | 1180 Stream s = m.Build(); |
| 1183 ASSERT_EQ(1U, s.size()); | 1181 ASSERT_EQ(1U, s.size()); |
| 1184 EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode()); | 1182 EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode()); |
| 1185 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); | 1183 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 1186 EXPECT_EQ(3U, s[0]->InputCount()); | 1184 EXPECT_EQ(3U, s[0]->InputCount()); |
| 1187 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 1185 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 1188 } | 1186 } |
| 1189 | 1187 |
| 1190 { | 1188 { |
| 1191 StreamBuilder m(this, kMachInt32, kMachInt32); | 1189 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 1192 MLabel a, b; | 1190 RawLabel a, b; |
| 1193 Node* p0 = m.Parameter(0); | 1191 Node* p0 = m.Parameter(0); |
| 1194 m.Branch(m.Word32BinaryNot(p0), &a, &b); | 1192 m.Branch(m.Word32BinaryNot(p0), &a, &b); |
| 1195 m.Bind(&a); | 1193 m.Bind(&a); |
| 1196 m.Return(m.Int32Constant(1)); | 1194 m.Return(m.Int32Constant(1)); |
| 1197 m.Bind(&b); | 1195 m.Bind(&b); |
| 1198 m.Return(m.Int32Constant(0)); | 1196 m.Return(m.Int32Constant(0)); |
| 1199 Stream s = m.Build(); | 1197 Stream s = m.Build(); |
| 1200 ASSERT_EQ(1U, s.size()); | 1198 ASSERT_EQ(1U, s.size()); |
| 1201 EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode()); | 1199 EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode()); |
| 1202 EXPECT_EQ(kEqual, s[0]->flags_condition()); | 1200 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1314 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | 1312 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1315 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | 1313 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 1316 } | 1314 } |
| 1317 } | 1315 } |
| 1318 | 1316 |
| 1319 | 1317 |
| 1320 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) { | 1318 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithParameters) { |
| 1321 const MachInst2 dpi = GetParam(); | 1319 const MachInst2 dpi = GetParam(); |
| 1322 const MachineType type = dpi.machine_type; | 1320 const MachineType type = dpi.machine_type; |
| 1323 StreamBuilder m(this, type, type, type); | 1321 StreamBuilder m(this, type, type, type); |
| 1324 MLabel a, b; | 1322 RawLabel a, b; |
| 1325 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)); | 1323 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)); |
| 1326 m.Branch(m.Projection(1, n), &a, &b); | 1324 m.Branch(m.Projection(1, n), &a, &b); |
| 1327 m.Bind(&a); | 1325 m.Bind(&a); |
| 1328 m.Return(m.Int32Constant(0)); | 1326 m.Return(m.Int32Constant(0)); |
| 1329 m.Bind(&b); | 1327 m.Bind(&b); |
| 1330 m.Return(m.Projection(0, n)); | 1328 m.Return(m.Projection(0, n)); |
| 1331 Stream s = m.Build(); | 1329 Stream s = m.Build(); |
| 1332 ASSERT_EQ(1U, s.size()); | 1330 ASSERT_EQ(1U, s.size()); |
| 1333 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 1331 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 1334 EXPECT_EQ(4U, s[0]->InputCount()); | 1332 EXPECT_EQ(4U, s[0]->InputCount()); |
| 1335 EXPECT_EQ(1U, s[0]->OutputCount()); | 1333 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1336 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); | 1334 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 1337 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | 1335 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 1338 } | 1336 } |
| 1339 | 1337 |
| 1340 | 1338 |
| 1341 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) { | 1339 TEST_P(InstructionSelectorOvfAddSubTest, BranchWithImmediateOnRight) { |
| 1342 const MachInst2 dpi = GetParam(); | 1340 const MachInst2 dpi = GetParam(); |
| 1343 const MachineType type = dpi.machine_type; | 1341 const MachineType type = dpi.machine_type; |
| 1344 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | 1342 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 1345 StreamBuilder m(this, type, type); | 1343 StreamBuilder m(this, type, type); |
| 1346 MLabel a, b; | 1344 RawLabel a, b; |
| 1347 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); | 1345 Node* n = (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); |
| 1348 m.Branch(m.Projection(1, n), &a, &b); | 1346 m.Branch(m.Projection(1, n), &a, &b); |
| 1349 m.Bind(&a); | 1347 m.Bind(&a); |
| 1350 m.Return(m.Int32Constant(0)); | 1348 m.Return(m.Int32Constant(0)); |
| 1351 m.Bind(&b); | 1349 m.Bind(&b); |
| 1352 m.Return(m.Projection(0, n)); | 1350 m.Return(m.Projection(0, n)); |
| 1353 Stream s = m.Build(); | 1351 Stream s = m.Build(); |
| 1354 ASSERT_EQ(1U, s.size()); | 1352 ASSERT_EQ(1U, s.size()); |
| 1355 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 1353 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 1356 ASSERT_EQ(4U, s[0]->InputCount()); | 1354 ASSERT_EQ(4U, s[0]->InputCount()); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1415 EXPECT_EQ(2U, s[0]->OutputCount()); | 1413 EXPECT_EQ(2U, s[0]->OutputCount()); |
| 1416 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | 1414 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1417 EXPECT_EQ(kOverflow, s[0]->flags_condition()); | 1415 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 1418 } | 1416 } |
| 1419 } | 1417 } |
| 1420 | 1418 |
| 1421 | 1419 |
| 1422 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) { | 1420 TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) { |
| 1423 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | 1421 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 1424 StreamBuilder m(this, kMachInt32, kMachInt32); | 1422 StreamBuilder m(this, kMachInt32, kMachInt32); |
| 1425 MLabel a, b; | 1423 RawLabel a, b; |
| 1426 Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0)); | 1424 Node* n = m.Int32AddWithOverflow(m.Int32Constant(imm), m.Parameter(0)); |
| 1427 m.Branch(m.Projection(1, n), &a, &b); | 1425 m.Branch(m.Projection(1, n), &a, &b); |
| 1428 m.Bind(&a); | 1426 m.Bind(&a); |
| 1429 m.Return(m.Int32Constant(0)); | 1427 m.Return(m.Int32Constant(0)); |
| 1430 m.Bind(&b); | 1428 m.Bind(&b); |
| 1431 m.Return(m.Projection(0, n)); | 1429 m.Return(m.Projection(0, n)); |
| 1432 Stream s = m.Build(); | 1430 Stream s = m.Build(); |
| 1433 | 1431 |
| 1434 ASSERT_EQ(1U, s.size()); | 1432 ASSERT_EQ(1U, s.size()); |
| 1435 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); | 1433 EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); |
| (...skipping 1811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3247 ASSERT_EQ(2U, s[0]->InputCount()); | 3245 ASSERT_EQ(2U, s[0]->InputCount()); |
| 3248 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); | 3246 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
| 3249 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); | 3247 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); |
| 3250 ASSERT_EQ(1U, s[0]->OutputCount()); | 3248 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 3251 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); | 3249 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
| 3252 } | 3250 } |
| 3253 | 3251 |
| 3254 } // namespace compiler | 3252 } // namespace compiler |
| 3255 } // namespace internal | 3253 } // namespace internal |
| 3256 } // namespace v8 | 3254 } // namespace v8 |
| OLD | NEW |