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 <list> | 5 #include <list> |
6 | 6 |
7 #include "test/compiler-unittests/instruction-selector-unittest.h" | 7 #include "test/compiler-unittests/instruction-selector-unittest.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
11 namespace compiler { | 11 namespace compiler { |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
15 typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*); | 15 typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*); |
16 | 16 |
17 struct DPI { | 17 struct DPI { |
18 Constructor constructor; | 18 Constructor constructor; |
19 const char* constructor_name; | 19 const char* constructor_name; |
20 ArchOpcode arch_opcode; | 20 ArchOpcode arch_opcode; |
| 21 MachineType machine_type; |
21 }; | 22 }; |
22 | 23 |
23 | 24 |
24 std::ostream& operator<<(std::ostream& os, const DPI& dpi) { | 25 std::ostream& operator<<(std::ostream& os, const DPI& dpi) { |
25 return os << dpi.constructor_name; | 26 return os << dpi.constructor_name; |
26 } | 27 } |
27 | 28 |
28 | 29 |
29 // ARM64 Logical instructions. | 30 // ARM64 Logical instructions. |
30 static const DPI kLogicalInstructions[] = { | 31 static const DPI kLogicalInstructions[] = { |
31 {&RawMachineAssembler::Word32And, "Word32And", kArm64And32}, | 32 {&RawMachineAssembler::Word32And, "Word32And", kArm64And32, kMachInt32}, |
32 {&RawMachineAssembler::Word64And, "Word64And", kArm64And}, | 33 {&RawMachineAssembler::Word64And, "Word64And", kArm64And, kMachInt64}, |
33 {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32}, | 34 {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32, kMachInt32}, |
34 {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or}, | 35 {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or, kMachInt64}, |
35 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Xor32}, | 36 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Xor32, kMachInt32}, |
36 {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Xor}}; | 37 {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Xor, kMachInt64}}; |
37 | 38 |
38 | 39 |
39 // ARM64 Arithmetic instructions. | 40 // ARM64 Arithmetic instructions. |
40 static const DPI kAddSubInstructions[] = { | 41 static const DPI kAddSubInstructions[] = { |
41 {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32}, | 42 {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32}, |
42 {&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add}, | 43 {&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64}, |
43 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32}, | 44 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32}, |
44 {&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub}}; | 45 {&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64}}; |
45 | 46 |
46 | 47 |
47 // ARM64 Add/Sub immediates. | 48 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12. |
48 // TODO(all): Test only a subset of the immediates, similar to what we do for | 49 // Below is a combination of a random subset and some edge values. |
49 // arm. Unit tests should be really fast! | 50 static const int32_t kAddSubImmediates[] = { |
50 class AddSubImmediates V8_FINAL : public std::list<int32_t> { | 51 0, 1, 69, 493, 599, 701, 719, |
51 public: | 52 768, 818, 842, 945, 1246, 1286, 1429, |
52 AddSubImmediates() { | 53 1669, 2171, 2179, 2182, 2254, 2334, 2338, |
53 for (int32_t imm12 = 0; imm12 < 4096; ++imm12) { | 54 2343, 2396, 2449, 2610, 2732, 2855, 2876, |
54 CHECK(Assembler::IsImmAddSub(imm12)); | 55 2944, 3377, 3458, 3475, 3476, 3540, 3574, |
55 CHECK(Assembler::IsImmAddSub(imm12 << 12)); | 56 3601, 3813, 3871, 3917, 4095, 4096, 16384, |
56 push_back(imm12); | 57 364544, 462848, 970752, 1523712, 1863680, 2363392, 3219456, |
57 push_back(imm12 << 12); | 58 3280896, 4247552, 4526080, 4575232, 4960256, 5505024, 5894144, |
58 } | 59 6004736, 6193152, 6385664, 6795264, 7114752, 7233536, 7348224, |
59 } | 60 7499776, 7573504, 7729152, 8634368, 8937472, 9465856, 10354688, |
60 }; | 61 10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224, |
| 62 15597568, 15892480, 16773120}; |
61 | 63 |
62 | 64 |
63 // ARM64 Mul/Div instructions. | 65 // ARM64 Mul/Div instructions. |
64 static const DPI kMulDivInstructions[] = { | 66 static const DPI kMulDivInstructions[] = { |
65 {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32}, | 67 {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32}, |
66 {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul}, | 68 {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64}, |
67 {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32}, | 69 {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32}, |
68 {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv}, | 70 {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv, kMachInt64}, |
69 {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kArm64Udiv32}, | 71 {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kArm64Udiv32, kMachInt32}, |
70 {&RawMachineAssembler::Int64UDiv, "Int64UDiv", kArm64Udiv}}; | 72 {&RawMachineAssembler::Int64UDiv, "Int64UDiv", kArm64Udiv, kMachInt64}}; |
71 | 73 |
72 } // namespace | 74 } // namespace |
73 | 75 |
74 | 76 |
75 // TODO(all): Use TEST_P, see instruction-selector-arm-unittest.cc. | 77 // ----------------------------------------------------------------------------- |
76 TEST_F(InstructionSelectorTest, LogicalWithParameter) { | 78 // Logical instructions. |
77 TRACED_FOREACH(DPI, dpi, kLogicalInstructions) { | 79 |
78 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 80 |
79 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | 81 typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorLogicalTest; |
| 82 |
| 83 TEST_P(InstructionSelectorLogicalTest, Parameter) { |
| 84 const DPI dpi = GetParam(); |
| 85 const MachineType type = dpi.machine_type; |
| 86 StreamBuilder m(this, type, type, type); |
| 87 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
| 88 Stream s = m.Build(); |
| 89 ASSERT_EQ(1U, s.size()); |
| 90 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 91 EXPECT_EQ(2U, s[0]->InputCount()); |
| 92 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 93 } |
| 94 |
| 95 |
| 96 // TODO(all): add immediate tests. |
| 97 |
| 98 |
| 99 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, |
| 100 ::testing::ValuesIn(kLogicalInstructions)); |
| 101 |
| 102 |
| 103 // ----------------------------------------------------------------------------- |
| 104 // Add and Sub instructions. |
| 105 |
| 106 typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorAddSubTest; |
| 107 |
| 108 TEST_P(InstructionSelectorAddSubTest, Parameter) { |
| 109 const DPI dpi = GetParam(); |
| 110 const MachineType type = dpi.machine_type; |
| 111 StreamBuilder m(this, type, type, type); |
| 112 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
| 113 Stream s = m.Build(); |
| 114 ASSERT_EQ(1U, s.size()); |
| 115 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 116 EXPECT_EQ(2U, s[0]->InputCount()); |
| 117 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 118 } |
| 119 |
| 120 |
| 121 TEST_P(InstructionSelectorAddSubTest, Immediate) { |
| 122 const DPI dpi = GetParam(); |
| 123 const MachineType type = dpi.machine_type; |
| 124 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { |
| 125 StreamBuilder m(this, type, type); |
| 126 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); |
80 Stream s = m.Build(); | 127 Stream s = m.Build(); |
81 ASSERT_EQ(1U, s.size()); | 128 ASSERT_EQ(1U, s.size()); |
82 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 129 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 130 ASSERT_EQ(2U, s[0]->InputCount()); |
| 131 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
| 132 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 133 EXPECT_EQ(1U, s[0]->OutputCount()); |
83 } | 134 } |
84 } | 135 } |
85 | 136 |
86 | 137 |
87 // TODO(all): Use TEST_P, see instruction-selector-arm-unittest.cc. | 138 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest, |
88 TEST_F(InstructionSelectorTest, AddSubWithParameter) { | 139 ::testing::ValuesIn(kAddSubInstructions)); |
89 TRACED_FOREACH(DPI, dpi, kAddSubInstructions) { | 140 |
90 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | 141 |
91 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | 142 // ----------------------------------------------------------------------------- |
92 Stream s = m.Build(); | 143 // Mul and Div instructions. |
93 ASSERT_EQ(1U, s.size()); | 144 |
94 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | 145 |
95 } | 146 typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorMulDivTest; |
| 147 |
| 148 |
| 149 TEST_P(InstructionSelectorMulDivTest, Parameter) { |
| 150 const DPI dpi = GetParam(); |
| 151 const MachineType type = dpi.machine_type; |
| 152 StreamBuilder m(this, type, type, type); |
| 153 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
| 154 Stream s = m.Build(); |
| 155 ASSERT_EQ(1U, s.size()); |
| 156 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 157 EXPECT_EQ(2U, s[0]->InputCount()); |
| 158 EXPECT_EQ(1U, s[0]->OutputCount()); |
96 } | 159 } |
97 | 160 |
98 | 161 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest, |
99 // TODO(all): Use TEST_P, see instruction-selector-arm-unittest.cc. | 162 ::testing::ValuesIn(kMulDivInstructions)); |
100 TEST_F(InstructionSelectorTest, AddSubWithImmediate) { | |
101 AddSubImmediates immediates; | |
102 TRACED_FOREACH(DPI, dpi, kAddSubInstructions) { | |
103 for (AddSubImmediates::const_iterator j = immediates.begin(); | |
104 j != immediates.end(); ++j) { | |
105 int32_t imm = *j; | |
106 SCOPED_TRACE(::testing::Message() << "imm = " << imm); | |
107 StreamBuilder m(this, kMachInt32, kMachInt32); | |
108 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
109 Stream s = m.Build(); | |
110 ASSERT_EQ(1U, s.size()); | |
111 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
112 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
113 } | |
114 } | |
115 } | |
116 | |
117 | |
118 // TODO(all): Use TEST_P, see instruction-selector-arm-unittest.cc. | |
119 TEST_F(InstructionSelectorTest, MulDivWithParameter) { | |
120 TRACED_FOREACH(DPI, dpi, kMulDivInstructions) { | |
121 StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); | |
122 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
123 Stream s = m.Build(); | |
124 ASSERT_EQ(1U, s.size()); | |
125 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
126 } | |
127 } | |
128 | 163 |
129 | 164 |
130 // ----------------------------------------------------------------------------- | 165 // ----------------------------------------------------------------------------- |
131 // Conversions. | 166 // Conversions. |
132 | 167 |
133 | 168 |
134 TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) { | 169 TEST_F(InstructionSelectorTest, ChangeInt32ToInt64WithParameter) { |
135 StreamBuilder m(this, kMachInt64, kMachInt32); | 170 StreamBuilder m(this, kMachInt64, kMachInt32); |
136 m.Return(m.ChangeInt32ToInt64(m.Parameter(0))); | 171 m.Return(m.ChangeInt32ToInt64(m.Parameter(0))); |
137 Stream s = m.Build(); | 172 Stream s = m.Build(); |
(...skipping 15 matching lines...) Expand all Loading... |
153 StreamBuilder m(this, kMachInt32, kMachInt64); | 188 StreamBuilder m(this, kMachInt32, kMachInt64); |
154 m.Return(m.TruncateInt64ToInt32(m.Parameter(0))); | 189 m.Return(m.TruncateInt64ToInt32(m.Parameter(0))); |
155 Stream s = m.Build(); | 190 Stream s = m.Build(); |
156 ASSERT_EQ(1U, s.size()); | 191 ASSERT_EQ(1U, s.size()); |
157 EXPECT_EQ(kArm64Mov32, s[0]->arch_opcode()); | 192 EXPECT_EQ(kArm64Mov32, s[0]->arch_opcode()); |
158 } | 193 } |
159 | 194 |
160 } // namespace compiler | 195 } // namespace compiler |
161 } // namespace internal | 196 } // namespace internal |
162 } // namespace v8 | 197 } // namespace v8 |
OLD | NEW |