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/compiler-unittests/instruction-selector-unittest.h" | 5 #include "test/compiler-unittests/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 class InstructionSelectorARMTest : public InstructionSelectorTest {}; | 11 namespace { |
12 | 12 |
13 | 13 typedef RawMachineAssembler::Label MLabel; |
14 TARGET_TEST_F(InstructionSelectorARMTest, Int32AddP) { | 14 typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*); |
15 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); | 15 |
16 m.Return(m.Int32Add(m.Parameter(0), m.Parameter(1))); | 16 |
| 17 // Data processing instructions. |
| 18 struct DPI { |
| 19 Constructor constructor; |
| 20 const char* constructor_name; |
| 21 ArchOpcode arch_opcode; |
| 22 ArchOpcode reverse_arch_opcode; |
| 23 ArchOpcode test_arch_opcode; |
| 24 }; |
| 25 |
| 26 |
| 27 std::ostream& operator<<(std::ostream& os, const DPI& dpi) { |
| 28 return os << dpi.constructor_name; |
| 29 } |
| 30 |
| 31 |
| 32 static const DPI kDPIs[] = { |
| 33 {&RawMachineAssembler::Word32And, "Word32And", kArmAnd, kArmAnd, kArmTst}, |
| 34 {&RawMachineAssembler::Word32Or, "Word32Or", kArmOrr, kArmOrr, kArmOrr}, |
| 35 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArmEor, kArmEor, kArmTeq}, |
| 36 {&RawMachineAssembler::Int32Add, "Int32Add", kArmAdd, kArmAdd, kArmCmn}, |
| 37 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArmSub, kArmRsb, kArmCmp}}; |
| 38 |
| 39 |
| 40 // Data processing instructions with overflow. |
| 41 struct ODPI { |
| 42 Constructor constructor; |
| 43 const char* constructor_name; |
| 44 ArchOpcode arch_opcode; |
| 45 ArchOpcode reverse_arch_opcode; |
| 46 }; |
| 47 |
| 48 |
| 49 std::ostream& operator<<(std::ostream& os, const ODPI& odpi) { |
| 50 return os << odpi.constructor_name; |
| 51 } |
| 52 |
| 53 |
| 54 static const ODPI kODPIs[] = {{&RawMachineAssembler::Int32AddWithOverflow, |
| 55 "Int32AddWithOverflow", kArmAdd, kArmAdd}, |
| 56 {&RawMachineAssembler::Int32SubWithOverflow, |
| 57 "Int32SubWithOverflow", kArmSub, kArmRsb}}; |
| 58 |
| 59 |
| 60 // Shifts. |
| 61 struct Shift { |
| 62 Constructor constructor; |
| 63 const char* constructor_name; |
| 64 int32_t i_low; // lowest possible immediate |
| 65 int32_t i_high; // highest possible immediate |
| 66 AddressingMode i_mode; // Operand2_R_<shift>_I |
| 67 AddressingMode r_mode; // Operand2_R_<shift>_R |
| 68 }; |
| 69 |
| 70 |
| 71 std::ostream& operator<<(std::ostream& os, const Shift& shift) { |
| 72 return os << shift.constructor_name; |
| 73 } |
| 74 |
| 75 |
| 76 static const Shift kShifts[] = { |
| 77 {&RawMachineAssembler::Word32Sar, "Word32Sar", 1, 32, |
| 78 kMode_Operand2_R_ASR_I, kMode_Operand2_R_ASR_R}, |
| 79 {&RawMachineAssembler::Word32Shl, "Word32Shl", 0, 31, |
| 80 kMode_Operand2_R_LSL_I, kMode_Operand2_R_LSL_R}, |
| 81 {&RawMachineAssembler::Word32Shr, "Word32Shr", 1, 32, |
| 82 kMode_Operand2_R_LSR_I, kMode_Operand2_R_LSR_R}, |
| 83 {&RawMachineAssembler::Word32Ror, "Word32Ror", 1, 31, |
| 84 kMode_Operand2_R_ROR_I, kMode_Operand2_R_ROR_R}}; |
| 85 |
| 86 |
| 87 // Immediates (random subset). |
| 88 static const int32_t kImmediates[] = { |
| 89 -2147483617, -2147483606, -2113929216, -2080374784, -1996488704, |
| 90 -1879048192, -1459617792, -1358954496, -1342177265, -1275068414, |
| 91 -1073741818, -1073741777, -855638016, -805306368, -402653184, |
| 92 -268435444, -16777216, 0, 35, 61, |
| 93 105, 116, 171, 245, 255, |
| 94 692, 1216, 1248, 1520, 1600, |
| 95 1888, 3744, 4080, 5888, 8384, |
| 96 9344, 9472, 9792, 13312, 15040, |
| 97 15360, 20736, 22272, 23296, 32000, |
| 98 33536, 37120, 45824, 47872, 56320, |
| 99 59392, 65280, 72704, 101376, 147456, |
| 100 161792, 164864, 167936, 173056, 195584, |
| 101 209920, 212992, 356352, 655360, 704512, |
| 102 716800, 851968, 901120, 1044480, 1523712, |
| 103 2572288, 3211264, 3588096, 3833856, 3866624, |
| 104 4325376, 5177344, 6488064, 7012352, 7471104, |
| 105 14090240, 16711680, 19398656, 22282240, 28573696, |
| 106 30408704, 30670848, 43253760, 54525952, 55312384, |
| 107 56623104, 68157440, 115343360, 131072000, 187695104, |
| 108 188743680, 195035136, 197132288, 203423744, 218103808, |
| 109 267386880, 268435470, 285212672, 402653185, 415236096, |
| 110 595591168, 603979776, 603979778, 629145600, 1073741835, |
| 111 1073741855, 1073741861, 1073741884, 1157627904, 1476395008, |
| 112 1476395010, 1610612741, 2030043136, 2080374785, 2097152000}; |
| 113 |
| 114 } // namespace |
| 115 |
| 116 |
| 117 // ----------------------------------------------------------------------------- |
| 118 // Data processing instructions. |
| 119 |
| 120 |
| 121 typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorDPITest; |
| 122 |
| 123 |
| 124 TEST_P(InstructionSelectorDPITest, Parameters) { |
| 125 const DPI dpi = GetParam(); |
| 126 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 127 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
17 Stream s = m.Build(); | 128 Stream s = m.Build(); |
18 ASSERT_EQ(1U, s.size()); | 129 ASSERT_EQ(1U, s.size()); |
19 EXPECT_EQ(kArmAdd, s[0]->arch_opcode()); | 130 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
20 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); | 131 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
21 EXPECT_EQ(2U, s[0]->InputCount()); | 132 EXPECT_EQ(2U, s[0]->InputCount()); |
22 EXPECT_EQ(1U, s[0]->OutputCount()); | 133 EXPECT_EQ(1U, s[0]->OutputCount()); |
23 } | 134 } |
24 | 135 |
| 136 |
| 137 TEST_P(InstructionSelectorDPITest, Immediate) { |
| 138 const DPI dpi = GetParam(); |
| 139 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 140 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 141 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); |
| 142 Stream s = m.Build(); |
| 143 ASSERT_EQ(1U, s.size()); |
| 144 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 145 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 146 ASSERT_EQ(2U, s[0]->InputCount()); |
| 147 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 148 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 149 } |
| 150 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 151 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 152 m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0))); |
| 153 Stream s = m.Build(); |
| 154 ASSERT_EQ(1U, s.size()); |
| 155 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 156 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 157 ASSERT_EQ(2U, s[0]->InputCount()); |
| 158 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 159 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 160 } |
| 161 } |
| 162 |
| 163 |
| 164 TEST_P(InstructionSelectorDPITest, ShiftByParameter) { |
| 165 const DPI dpi = GetParam(); |
| 166 TRACED_FOREACH(Shift, shift, kShifts) { |
| 167 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 168 kMachineWord32); |
| 169 m.Return((m.*dpi.constructor)( |
| 170 m.Parameter(0), |
| 171 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))); |
| 172 Stream s = m.Build(); |
| 173 ASSERT_EQ(1U, s.size()); |
| 174 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 175 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 176 EXPECT_EQ(3U, s[0]->InputCount()); |
| 177 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 178 } |
| 179 TRACED_FOREACH(Shift, shift, kShifts) { |
| 180 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 181 kMachineWord32); |
| 182 m.Return((m.*dpi.constructor)( |
| 183 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), |
| 184 m.Parameter(2))); |
| 185 Stream s = m.Build(); |
| 186 ASSERT_EQ(1U, s.size()); |
| 187 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 188 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 189 EXPECT_EQ(3U, s[0]->InputCount()); |
| 190 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 191 } |
| 192 } |
| 193 |
| 194 |
| 195 TEST_P(InstructionSelectorDPITest, ShiftByImmediate) { |
| 196 const DPI dpi = GetParam(); |
| 197 TRACED_FOREACH(Shift, shift, kShifts) { |
| 198 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 199 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 200 m.Return((m.*dpi.constructor)( |
| 201 m.Parameter(0), |
| 202 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)))); |
| 203 Stream s = m.Build(); |
| 204 ASSERT_EQ(1U, s.size()); |
| 205 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| 206 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 207 ASSERT_EQ(3U, s[0]->InputCount()); |
| 208 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 209 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 210 } |
| 211 } |
| 212 TRACED_FOREACH(Shift, shift, kShifts) { |
| 213 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 214 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 215 m.Return((m.*dpi.constructor)( |
| 216 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)), |
| 217 m.Parameter(1))); |
| 218 Stream s = m.Build(); |
| 219 ASSERT_EQ(1U, s.size()); |
| 220 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 221 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 222 ASSERT_EQ(3U, s[0]->InputCount()); |
| 223 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 224 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 225 } |
| 226 } |
| 227 } |
| 228 |
| 229 |
| 230 TEST_P(InstructionSelectorDPITest, BranchWithParameters) { |
| 231 const DPI dpi = GetParam(); |
| 232 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 233 MLabel a, b; |
| 234 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b); |
| 235 m.Bind(&a); |
| 236 m.Return(m.Int32Constant(1)); |
| 237 m.Bind(&b); |
| 238 m.Return(m.Int32Constant(0)); |
| 239 Stream s = m.Build(); |
| 240 ASSERT_EQ(1U, s.size()); |
| 241 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 242 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 243 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 244 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 245 } |
| 246 |
| 247 |
| 248 TEST_P(InstructionSelectorDPITest, BranchWithImmediate) { |
| 249 const DPI dpi = GetParam(); |
| 250 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 251 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 252 MLabel a, b; |
| 253 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), &a, |
| 254 &b); |
| 255 m.Bind(&a); |
| 256 m.Return(m.Int32Constant(1)); |
| 257 m.Bind(&b); |
| 258 m.Return(m.Int32Constant(0)); |
| 259 Stream s = m.Build(); |
| 260 ASSERT_EQ(1U, s.size()); |
| 261 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 262 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 263 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 264 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 265 } |
| 266 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 267 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 268 MLabel a, b; |
| 269 m.Branch((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), &a, |
| 270 &b); |
| 271 m.Bind(&a); |
| 272 m.Return(m.Int32Constant(1)); |
| 273 m.Bind(&b); |
| 274 m.Return(m.Int32Constant(0)); |
| 275 Stream s = m.Build(); |
| 276 ASSERT_EQ(1U, s.size()); |
| 277 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 278 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 279 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 280 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 281 } |
| 282 } |
| 283 |
| 284 |
| 285 TEST_P(InstructionSelectorDPITest, BranchWithShiftByParameter) { |
| 286 const DPI dpi = GetParam(); |
| 287 TRACED_FOREACH(Shift, shift, kShifts) { |
| 288 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 289 kMachineWord32); |
| 290 MLabel a, b; |
| 291 m.Branch((m.*dpi.constructor)( |
| 292 m.Parameter(0), |
| 293 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))), |
| 294 &a, &b); |
| 295 m.Bind(&a); |
| 296 m.Return(m.Int32Constant(1)); |
| 297 m.Bind(&b); |
| 298 m.Return(m.Int32Constant(0)); |
| 299 Stream s = m.Build(); |
| 300 ASSERT_EQ(1U, s.size()); |
| 301 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 302 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 303 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 304 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 305 } |
| 306 TRACED_FOREACH(Shift, shift, kShifts) { |
| 307 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 308 kMachineWord32); |
| 309 MLabel a, b; |
| 310 m.Branch((m.*dpi.constructor)( |
| 311 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), |
| 312 m.Parameter(2)), |
| 313 &a, &b); |
| 314 m.Bind(&a); |
| 315 m.Return(m.Int32Constant(1)); |
| 316 m.Bind(&b); |
| 317 m.Return(m.Int32Constant(0)); |
| 318 Stream s = m.Build(); |
| 319 ASSERT_EQ(1U, s.size()); |
| 320 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 321 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 322 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 323 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 324 } |
| 325 } |
| 326 |
| 327 |
| 328 TEST_P(InstructionSelectorDPITest, BranchWithShiftByImmediate) { |
| 329 const DPI dpi = GetParam(); |
| 330 TRACED_FOREACH(Shift, shift, kShifts) { |
| 331 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 332 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 333 MLabel a, b; |
| 334 m.Branch((m.*dpi.constructor)(m.Parameter(0), |
| 335 (m.*shift.constructor)( |
| 336 m.Parameter(1), m.Int32Constant(imm))), |
| 337 &a, &b); |
| 338 m.Bind(&a); |
| 339 m.Return(m.Int32Constant(1)); |
| 340 m.Bind(&b); |
| 341 m.Return(m.Int32Constant(0)); |
| 342 Stream s = m.Build(); |
| 343 ASSERT_EQ(1U, s.size()); |
| 344 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 345 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 346 ASSERT_EQ(5U, s[0]->InputCount()); |
| 347 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 348 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 349 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 350 } |
| 351 } |
| 352 TRACED_FOREACH(Shift, shift, kShifts) { |
| 353 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 354 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 355 MLabel a, b; |
| 356 m.Branch((m.*dpi.constructor)( |
| 357 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)), |
| 358 m.Parameter(1)), |
| 359 &a, &b); |
| 360 m.Bind(&a); |
| 361 m.Return(m.Int32Constant(1)); |
| 362 m.Bind(&b); |
| 363 m.Return(m.Int32Constant(0)); |
| 364 Stream s = m.Build(); |
| 365 ASSERT_EQ(1U, s.size()); |
| 366 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 367 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 368 ASSERT_EQ(5U, s[0]->InputCount()); |
| 369 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 370 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 371 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 372 } |
| 373 } |
| 374 } |
| 375 |
| 376 |
| 377 TEST_P(InstructionSelectorDPITest, BranchIfZeroWithParameters) { |
| 378 const DPI dpi = GetParam(); |
| 379 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 380 MLabel a, b; |
| 381 m.Branch(m.Word32Equal((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), |
| 382 m.Int32Constant(0)), |
| 383 &a, &b); |
| 384 m.Bind(&a); |
| 385 m.Return(m.Int32Constant(1)); |
| 386 m.Bind(&b); |
| 387 m.Return(m.Int32Constant(0)); |
| 388 Stream s = m.Build(); |
| 389 ASSERT_EQ(1U, s.size()); |
| 390 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 391 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 392 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 393 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 394 } |
| 395 |
| 396 |
| 397 TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithParameters) { |
| 398 const DPI dpi = GetParam(); |
| 399 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 400 MLabel a, b; |
| 401 m.Branch( |
| 402 m.Word32NotEqual((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), |
| 403 m.Int32Constant(0)), |
| 404 &a, &b); |
| 405 m.Bind(&a); |
| 406 m.Return(m.Int32Constant(1)); |
| 407 m.Bind(&b); |
| 408 m.Return(m.Int32Constant(0)); |
| 409 Stream s = m.Build(); |
| 410 ASSERT_EQ(1U, s.size()); |
| 411 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 412 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 413 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 414 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 415 } |
| 416 |
| 417 |
| 418 TEST_P(InstructionSelectorDPITest, BranchIfZeroWithImmediate) { |
| 419 const DPI dpi = GetParam(); |
| 420 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 421 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 422 MLabel a, b; |
| 423 m.Branch(m.Word32Equal( |
| 424 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), |
| 425 m.Int32Constant(0)), |
| 426 &a, &b); |
| 427 m.Bind(&a); |
| 428 m.Return(m.Int32Constant(1)); |
| 429 m.Bind(&b); |
| 430 m.Return(m.Int32Constant(0)); |
| 431 Stream s = m.Build(); |
| 432 ASSERT_EQ(1U, s.size()); |
| 433 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 434 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 435 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 436 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 437 } |
| 438 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 439 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 440 MLabel a, b; |
| 441 m.Branch(m.Word32Equal( |
| 442 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), |
| 443 m.Int32Constant(0)), |
| 444 &a, &b); |
| 445 m.Bind(&a); |
| 446 m.Return(m.Int32Constant(1)); |
| 447 m.Bind(&b); |
| 448 m.Return(m.Int32Constant(0)); |
| 449 Stream s = m.Build(); |
| 450 ASSERT_EQ(1U, s.size()); |
| 451 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 452 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 453 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 454 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 455 } |
| 456 } |
| 457 |
| 458 |
| 459 TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithImmediate) { |
| 460 const DPI dpi = GetParam(); |
| 461 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 462 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 463 MLabel a, b; |
| 464 m.Branch(m.Word32NotEqual( |
| 465 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), |
| 466 m.Int32Constant(0)), |
| 467 &a, &b); |
| 468 m.Bind(&a); |
| 469 m.Return(m.Int32Constant(1)); |
| 470 m.Bind(&b); |
| 471 m.Return(m.Int32Constant(0)); |
| 472 Stream s = m.Build(); |
| 473 ASSERT_EQ(1U, s.size()); |
| 474 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 475 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 476 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 477 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 478 } |
| 479 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 480 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 481 MLabel a, b; |
| 482 m.Branch(m.Word32NotEqual( |
| 483 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), |
| 484 m.Int32Constant(0)), |
| 485 &a, &b); |
| 486 m.Bind(&a); |
| 487 m.Return(m.Int32Constant(1)); |
| 488 m.Bind(&b); |
| 489 m.Return(m.Int32Constant(0)); |
| 490 Stream s = m.Build(); |
| 491 ASSERT_EQ(1U, s.size()); |
| 492 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); |
| 493 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 494 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 495 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); |
| 496 } |
| 497 } |
| 498 |
| 499 |
| 500 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorDPITest, |
| 501 ::testing::ValuesIn(kDPIs)); |
| 502 |
| 503 |
| 504 // ----------------------------------------------------------------------------- |
| 505 // Data processing instructions with overflow. |
| 506 |
| 507 |
| 508 typedef InstructionSelectorTestWithParam<ODPI> InstructionSelectorODPITest; |
| 509 |
| 510 |
| 511 TEST_P(InstructionSelectorODPITest, OvfWithParameters) { |
| 512 const ODPI odpi = GetParam(); |
| 513 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 514 m.Return( |
| 515 m.Projection(1, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)))); |
| 516 Stream s = m.Build(); |
| 517 ASSERT_EQ(1U, s.size()); |
| 518 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 519 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 520 EXPECT_EQ(2U, s[0]->InputCount()); |
| 521 EXPECT_LE(1U, s[0]->OutputCount()); |
| 522 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 523 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 524 } |
| 525 |
| 526 |
| 527 TEST_P(InstructionSelectorODPITest, OvfWithImmediate) { |
| 528 const ODPI odpi = GetParam(); |
| 529 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 530 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 531 m.Return(m.Projection( |
| 532 1, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)))); |
| 533 Stream s = m.Build(); |
| 534 ASSERT_EQ(1U, s.size()); |
| 535 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 536 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 537 ASSERT_EQ(2U, s[0]->InputCount()); |
| 538 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 539 EXPECT_LE(1U, s[0]->OutputCount()); |
| 540 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 541 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 542 } |
| 543 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 544 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 545 m.Return(m.Projection( |
| 546 1, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)))); |
| 547 Stream s = m.Build(); |
| 548 ASSERT_EQ(1U, s.size()); |
| 549 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 550 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 551 ASSERT_EQ(2U, s[0]->InputCount()); |
| 552 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 553 EXPECT_LE(1U, s[0]->OutputCount()); |
| 554 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 555 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 556 } |
| 557 } |
| 558 |
| 559 |
| 560 TEST_P(InstructionSelectorODPITest, OvfWithShiftByParameter) { |
| 561 const ODPI odpi = GetParam(); |
| 562 TRACED_FOREACH(Shift, shift, kShifts) { |
| 563 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 564 kMachineWord32); |
| 565 m.Return(m.Projection( |
| 566 1, (m.*odpi.constructor)( |
| 567 m.Parameter(0), |
| 568 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))))); |
| 569 Stream s = m.Build(); |
| 570 ASSERT_EQ(1U, s.size()); |
| 571 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 572 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 573 EXPECT_EQ(3U, s[0]->InputCount()); |
| 574 EXPECT_LE(1U, s[0]->OutputCount()); |
| 575 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 576 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 577 } |
| 578 TRACED_FOREACH(Shift, shift, kShifts) { |
| 579 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 580 kMachineWord32); |
| 581 m.Return(m.Projection( |
| 582 1, (m.*odpi.constructor)( |
| 583 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), |
| 584 m.Parameter(0)))); |
| 585 Stream s = m.Build(); |
| 586 ASSERT_EQ(1U, s.size()); |
| 587 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 588 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 589 EXPECT_EQ(3U, s[0]->InputCount()); |
| 590 EXPECT_LE(1U, s[0]->OutputCount()); |
| 591 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 592 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 593 } |
| 594 } |
| 595 |
| 596 |
| 597 TEST_P(InstructionSelectorODPITest, OvfWithShiftByImmediate) { |
| 598 const ODPI odpi = GetParam(); |
| 599 TRACED_FOREACH(Shift, shift, kShifts) { |
| 600 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 601 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 602 m.Return(m.Projection( |
| 603 1, (m.*odpi.constructor)(m.Parameter(0), |
| 604 (m.*shift.constructor)( |
| 605 m.Parameter(1), m.Int32Constant(imm))))); |
| 606 Stream s = m.Build(); |
| 607 ASSERT_EQ(1U, s.size()); |
| 608 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 609 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 610 ASSERT_EQ(3U, s[0]->InputCount()); |
| 611 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 612 EXPECT_LE(1U, s[0]->OutputCount()); |
| 613 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 614 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 615 } |
| 616 } |
| 617 TRACED_FOREACH(Shift, shift, kShifts) { |
| 618 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 619 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 620 m.Return(m.Projection( |
| 621 1, (m.*odpi.constructor)( |
| 622 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)), |
| 623 m.Parameter(0)))); |
| 624 Stream s = m.Build(); |
| 625 ASSERT_EQ(1U, s.size()); |
| 626 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 627 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 628 ASSERT_EQ(3U, s[0]->InputCount()); |
| 629 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 630 EXPECT_LE(1U, s[0]->OutputCount()); |
| 631 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 632 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 633 } |
| 634 } |
| 635 } |
| 636 |
| 637 |
| 638 TEST_P(InstructionSelectorODPITest, ValWithParameters) { |
| 639 const ODPI odpi = GetParam(); |
| 640 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 641 m.Return( |
| 642 m.Projection(0, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)))); |
| 643 Stream s = m.Build(); |
| 644 ASSERT_EQ(1U, s.size()); |
| 645 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 646 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 647 EXPECT_EQ(2U, s[0]->InputCount()); |
| 648 EXPECT_LE(1U, s[0]->OutputCount()); |
| 649 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 650 } |
| 651 |
| 652 |
| 653 TEST_P(InstructionSelectorODPITest, ValWithImmediate) { |
| 654 const ODPI odpi = GetParam(); |
| 655 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 656 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 657 m.Return(m.Projection( |
| 658 0, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)))); |
| 659 Stream s = m.Build(); |
| 660 ASSERT_EQ(1U, s.size()); |
| 661 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 662 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 663 ASSERT_EQ(2U, s[0]->InputCount()); |
| 664 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 665 EXPECT_LE(1U, s[0]->OutputCount()); |
| 666 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 667 } |
| 668 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 669 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 670 m.Return(m.Projection( |
| 671 0, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)))); |
| 672 Stream s = m.Build(); |
| 673 ASSERT_EQ(1U, s.size()); |
| 674 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 675 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 676 ASSERT_EQ(2U, s[0]->InputCount()); |
| 677 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 678 EXPECT_LE(1U, s[0]->OutputCount()); |
| 679 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 680 } |
| 681 } |
| 682 |
| 683 |
| 684 TEST_P(InstructionSelectorODPITest, ValWithShiftByParameter) { |
| 685 const ODPI odpi = GetParam(); |
| 686 TRACED_FOREACH(Shift, shift, kShifts) { |
| 687 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 688 kMachineWord32); |
| 689 m.Return(m.Projection( |
| 690 0, (m.*odpi.constructor)( |
| 691 m.Parameter(0), |
| 692 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))))); |
| 693 Stream s = m.Build(); |
| 694 ASSERT_EQ(1U, s.size()); |
| 695 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 696 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 697 EXPECT_EQ(3U, s[0]->InputCount()); |
| 698 EXPECT_LE(1U, s[0]->OutputCount()); |
| 699 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 700 } |
| 701 TRACED_FOREACH(Shift, shift, kShifts) { |
| 702 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 703 kMachineWord32); |
| 704 m.Return(m.Projection( |
| 705 0, (m.*odpi.constructor)( |
| 706 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), |
| 707 m.Parameter(0)))); |
| 708 Stream s = m.Build(); |
| 709 ASSERT_EQ(1U, s.size()); |
| 710 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 711 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 712 EXPECT_EQ(3U, s[0]->InputCount()); |
| 713 EXPECT_LE(1U, s[0]->OutputCount()); |
| 714 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 715 } |
| 716 } |
| 717 |
| 718 |
| 719 TEST_P(InstructionSelectorODPITest, ValWithShiftByImmediate) { |
| 720 const ODPI odpi = GetParam(); |
| 721 TRACED_FOREACH(Shift, shift, kShifts) { |
| 722 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 723 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 724 m.Return(m.Projection( |
| 725 0, (m.*odpi.constructor)(m.Parameter(0), |
| 726 (m.*shift.constructor)( |
| 727 m.Parameter(1), m.Int32Constant(imm))))); |
| 728 Stream s = m.Build(); |
| 729 ASSERT_EQ(1U, s.size()); |
| 730 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 731 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 732 ASSERT_EQ(3U, s[0]->InputCount()); |
| 733 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 734 EXPECT_LE(1U, s[0]->OutputCount()); |
| 735 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 736 } |
| 737 } |
| 738 TRACED_FOREACH(Shift, shift, kShifts) { |
| 739 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 740 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 741 m.Return(m.Projection( |
| 742 0, (m.*odpi.constructor)( |
| 743 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)), |
| 744 m.Parameter(0)))); |
| 745 Stream s = m.Build(); |
| 746 ASSERT_EQ(1U, s.size()); |
| 747 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 748 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 749 ASSERT_EQ(3U, s[0]->InputCount()); |
| 750 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 751 EXPECT_LE(1U, s[0]->OutputCount()); |
| 752 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
| 753 } |
| 754 } |
| 755 } |
| 756 |
| 757 |
| 758 TEST_P(InstructionSelectorODPITest, BothWithParameters) { |
| 759 const ODPI odpi = GetParam(); |
| 760 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 761 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); |
| 762 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
| 763 Stream s = m.Build(); |
| 764 ASSERT_LE(1U, s.size()); |
| 765 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 766 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 767 EXPECT_EQ(2U, s[0]->InputCount()); |
| 768 EXPECT_EQ(2U, s[0]->OutputCount()); |
| 769 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 770 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 771 } |
| 772 |
| 773 |
| 774 TEST_P(InstructionSelectorODPITest, BothWithImmediate) { |
| 775 const ODPI odpi = GetParam(); |
| 776 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 777 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 778 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); |
| 779 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
| 780 Stream s = m.Build(); |
| 781 ASSERT_LE(1U, s.size()); |
| 782 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 783 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 784 ASSERT_EQ(2U, s[0]->InputCount()); |
| 785 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 786 EXPECT_EQ(2U, s[0]->OutputCount()); |
| 787 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 788 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 789 } |
| 790 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 791 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 792 Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)); |
| 793 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
| 794 Stream s = m.Build(); |
| 795 ASSERT_LE(1U, s.size()); |
| 796 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 797 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 798 ASSERT_EQ(2U, s[0]->InputCount()); |
| 799 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 800 EXPECT_EQ(2U, s[0]->OutputCount()); |
| 801 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 802 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 803 } |
| 804 } |
| 805 |
| 806 |
| 807 TEST_P(InstructionSelectorODPITest, BothWithShiftByParameter) { |
| 808 const ODPI odpi = GetParam(); |
| 809 TRACED_FOREACH(Shift, shift, kShifts) { |
| 810 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 811 kMachineWord32); |
| 812 Node* n = (m.*odpi.constructor)( |
| 813 m.Parameter(0), (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))); |
| 814 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
| 815 Stream s = m.Build(); |
| 816 ASSERT_LE(1U, s.size()); |
| 817 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 818 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 819 EXPECT_EQ(3U, s[0]->InputCount()); |
| 820 EXPECT_EQ(2U, s[0]->OutputCount()); |
| 821 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 822 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 823 } |
| 824 TRACED_FOREACH(Shift, shift, kShifts) { |
| 825 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 826 kMachineWord32); |
| 827 Node* n = (m.*odpi.constructor)( |
| 828 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), m.Parameter(2)); |
| 829 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
| 830 Stream s = m.Build(); |
| 831 ASSERT_LE(1U, s.size()); |
| 832 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 833 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 834 EXPECT_EQ(3U, s[0]->InputCount()); |
| 835 EXPECT_EQ(2U, s[0]->OutputCount()); |
| 836 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 837 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 838 } |
| 839 } |
| 840 |
| 841 |
| 842 TEST_P(InstructionSelectorODPITest, BothWithShiftByImmediate) { |
| 843 const ODPI odpi = GetParam(); |
| 844 TRACED_FOREACH(Shift, shift, kShifts) { |
| 845 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 846 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 847 Node* n = (m.*odpi.constructor)( |
| 848 m.Parameter(0), |
| 849 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm))); |
| 850 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
| 851 Stream s = m.Build(); |
| 852 ASSERT_LE(1U, s.size()); |
| 853 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 854 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 855 ASSERT_EQ(3U, s[0]->InputCount()); |
| 856 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 857 EXPECT_EQ(2U, s[0]->OutputCount()); |
| 858 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 859 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 860 } |
| 861 } |
| 862 TRACED_FOREACH(Shift, shift, kShifts) { |
| 863 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 864 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 865 Node* n = (m.*odpi.constructor)( |
| 866 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)), |
| 867 m.Parameter(1)); |
| 868 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); |
| 869 Stream s = m.Build(); |
| 870 ASSERT_LE(1U, s.size()); |
| 871 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 872 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 873 ASSERT_EQ(3U, s[0]->InputCount()); |
| 874 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 875 EXPECT_EQ(2U, s[0]->OutputCount()); |
| 876 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 877 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 878 } |
| 879 } |
| 880 } |
| 881 |
| 882 |
| 883 TEST_P(InstructionSelectorODPITest, BranchWithParameters) { |
| 884 const ODPI odpi = GetParam(); |
| 885 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 886 MLabel a, b; |
| 887 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); |
| 888 m.Branch(m.Projection(1, n), &a, &b); |
| 889 m.Bind(&a); |
| 890 m.Return(m.Int32Constant(0)); |
| 891 m.Bind(&b); |
| 892 m.Return(m.Projection(0, n)); |
| 893 Stream s = m.Build(); |
| 894 ASSERT_EQ(1U, s.size()); |
| 895 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 896 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 897 EXPECT_EQ(4U, s[0]->InputCount()); |
| 898 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 899 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 900 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 901 } |
| 902 |
| 903 |
| 904 TEST_P(InstructionSelectorODPITest, BranchWithImmediate) { |
| 905 const ODPI odpi = GetParam(); |
| 906 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 907 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 908 MLabel a, b; |
| 909 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); |
| 910 m.Branch(m.Projection(1, n), &a, &b); |
| 911 m.Bind(&a); |
| 912 m.Return(m.Int32Constant(0)); |
| 913 m.Bind(&b); |
| 914 m.Return(m.Projection(0, n)); |
| 915 Stream s = m.Build(); |
| 916 ASSERT_EQ(1U, s.size()); |
| 917 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 918 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 919 ASSERT_EQ(4U, s[0]->InputCount()); |
| 920 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 921 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 922 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 923 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 924 } |
| 925 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 926 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 927 MLabel a, b; |
| 928 Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)); |
| 929 m.Branch(m.Projection(1, n), &a, &b); |
| 930 m.Bind(&a); |
| 931 m.Return(m.Int32Constant(0)); |
| 932 m.Bind(&b); |
| 933 m.Return(m.Projection(0, n)); |
| 934 Stream s = m.Build(); |
| 935 ASSERT_EQ(1U, s.size()); |
| 936 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); |
| 937 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 938 ASSERT_EQ(4U, s[0]->InputCount()); |
| 939 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 940 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 941 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 942 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 943 } |
| 944 } |
| 945 |
| 946 |
| 947 TEST_P(InstructionSelectorODPITest, BranchIfZeroWithParameters) { |
| 948 const ODPI odpi = GetParam(); |
| 949 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 950 MLabel a, b; |
| 951 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); |
| 952 m.Branch(m.Word32Equal(m.Projection(1, n), m.Int32Constant(0)), &a, &b); |
| 953 m.Bind(&a); |
| 954 m.Return(m.Projection(0, n)); |
| 955 m.Bind(&b); |
| 956 m.Return(m.Int32Constant(0)); |
| 957 Stream s = m.Build(); |
| 958 ASSERT_EQ(1U, s.size()); |
| 959 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 960 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 961 EXPECT_EQ(4U, s[0]->InputCount()); |
| 962 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 963 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 964 EXPECT_EQ(kNotOverflow, s[0]->flags_condition()); |
| 965 } |
| 966 |
| 967 |
| 968 TEST_P(InstructionSelectorODPITest, BranchIfNotZeroWithParameters) { |
| 969 const ODPI odpi = GetParam(); |
| 970 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 971 MLabel a, b; |
| 972 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); |
| 973 m.Branch(m.Word32NotEqual(m.Projection(1, n), m.Int32Constant(0)), &a, &b); |
| 974 m.Bind(&a); |
| 975 m.Return(m.Projection(0, n)); |
| 976 m.Bind(&b); |
| 977 m.Return(m.Int32Constant(0)); |
| 978 Stream s = m.Build(); |
| 979 ASSERT_EQ(1U, s.size()); |
| 980 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); |
| 981 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 982 EXPECT_EQ(4U, s[0]->InputCount()); |
| 983 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 984 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); |
| 985 EXPECT_EQ(kOverflow, s[0]->flags_condition()); |
| 986 } |
| 987 |
| 988 |
| 989 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorODPITest, |
| 990 ::testing::ValuesIn(kODPIs)); |
| 991 |
| 992 |
| 993 // ----------------------------------------------------------------------------- |
| 994 // Shifts. |
| 995 |
| 996 |
| 997 typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest; |
| 998 |
| 999 |
| 1000 TEST_P(InstructionSelectorShiftTest, Parameters) { |
| 1001 const Shift shift = GetParam(); |
| 1002 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1003 m.Return((m.*shift.constructor)(m.Parameter(0), m.Parameter(1))); |
| 1004 Stream s = m.Build(); |
| 1005 ASSERT_EQ(1U, s.size()); |
| 1006 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); |
| 1007 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 1008 EXPECT_EQ(2U, s[0]->InputCount()); |
| 1009 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1010 } |
| 1011 |
| 1012 |
| 1013 TEST_P(InstructionSelectorShiftTest, Immediates) { |
| 1014 const Shift shift = GetParam(); |
| 1015 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 1016 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1017 m.Return((m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))); |
| 1018 Stream s = m.Build(); |
| 1019 ASSERT_EQ(1U, s.size()); |
| 1020 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); |
| 1021 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 1022 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1023 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 1024 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1025 } |
| 1026 } |
| 1027 |
| 1028 |
| 1029 TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameter) { |
| 1030 const Shift shift = GetParam(); |
| 1031 { |
| 1032 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 1033 kMachineWord32); |
| 1034 m.Return( |
| 1035 m.Word32Equal(m.Parameter(0), |
| 1036 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))); |
| 1037 Stream s = m.Build(); |
| 1038 ASSERT_EQ(1U, s.size()); |
| 1039 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); |
| 1040 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 1041 EXPECT_EQ(3U, s[0]->InputCount()); |
| 1042 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1043 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1044 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1045 } |
| 1046 { |
| 1047 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 1048 kMachineWord32); |
| 1049 m.Return( |
| 1050 m.Word32Equal((m.*shift.constructor)(m.Parameter(1), m.Parameter(2)), |
| 1051 m.Parameter(0))); |
| 1052 Stream s = m.Build(); |
| 1053 ASSERT_EQ(1U, s.size()); |
| 1054 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); |
| 1055 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 1056 EXPECT_EQ(3U, s[0]->InputCount()); |
| 1057 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1058 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1059 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1060 } |
| 1061 } |
| 1062 |
| 1063 |
| 1064 TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameterAndImmediate) { |
| 1065 const Shift shift = GetParam(); |
| 1066 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 1067 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1068 m.Return(m.Word32Equal( |
| 1069 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)), |
| 1070 m.Parameter(0))); |
| 1071 Stream s = m.Build(); |
| 1072 ASSERT_EQ(1U, s.size()); |
| 1073 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); |
| 1074 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 1075 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1076 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 1077 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1078 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1079 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1080 } |
| 1081 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 1082 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1083 m.Return(m.Word32Equal( |
| 1084 m.Parameter(0), |
| 1085 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)))); |
| 1086 Stream s = m.Build(); |
| 1087 ASSERT_EQ(1U, s.size()); |
| 1088 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); |
| 1089 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 1090 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1091 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 1092 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1093 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1094 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1095 } |
| 1096 } |
| 1097 |
| 1098 |
| 1099 TEST_P(InstructionSelectorShiftTest, Word32NotWithParameters) { |
| 1100 const Shift shift = GetParam(); |
| 1101 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1102 m.Return(m.Word32Not((m.*shift.constructor)(m.Parameter(0), m.Parameter(1)))); |
| 1103 Stream s = m.Build(); |
| 1104 ASSERT_EQ(1U, s.size()); |
| 1105 EXPECT_EQ(kArmMvn, s[0]->arch_opcode()); |
| 1106 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 1107 EXPECT_EQ(2U, s[0]->InputCount()); |
| 1108 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1109 } |
| 1110 |
| 1111 |
| 1112 TEST_P(InstructionSelectorShiftTest, Word32NotWithImmediate) { |
| 1113 const Shift shift = GetParam(); |
| 1114 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 1115 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1116 m.Return(m.Word32Not( |
| 1117 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)))); |
| 1118 Stream s = m.Build(); |
| 1119 ASSERT_EQ(1U, s.size()); |
| 1120 EXPECT_EQ(kArmMvn, s[0]->arch_opcode()); |
| 1121 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 1122 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1123 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 1124 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1125 } |
| 1126 } |
| 1127 |
| 1128 |
| 1129 TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithParameters) { |
| 1130 const Shift shift = GetParam(); |
| 1131 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 1132 kMachineWord32); |
| 1133 m.Return(m.Word32And(m.Parameter(0), m.Word32Not((m.*shift.constructor)( |
| 1134 m.Parameter(1), m.Parameter(2))))); |
| 1135 Stream s = m.Build(); |
| 1136 ASSERT_EQ(1U, s.size()); |
| 1137 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); |
| 1138 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); |
| 1139 EXPECT_EQ(3U, s[0]->InputCount()); |
| 1140 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1141 } |
| 1142 |
| 1143 |
| 1144 TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithImmediate) { |
| 1145 const Shift shift = GetParam(); |
| 1146 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { |
| 1147 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1148 m.Return(m.Word32And(m.Parameter(0), |
| 1149 m.Word32Not((m.*shift.constructor)( |
| 1150 m.Parameter(1), m.Int32Constant(imm))))); |
| 1151 Stream s = m.Build(); |
| 1152 ASSERT_EQ(1U, s.size()); |
| 1153 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); |
| 1154 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); |
| 1155 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1156 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); |
| 1157 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1158 } |
| 1159 } |
| 1160 |
| 1161 |
| 1162 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, |
| 1163 ::testing::ValuesIn(kShifts)); |
| 1164 |
| 1165 |
| 1166 // ----------------------------------------------------------------------------- |
| 1167 // Miscellaneous. |
| 1168 |
| 1169 |
| 1170 TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) { |
| 1171 { |
| 1172 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 1173 kMachineWord32); |
| 1174 m.Return( |
| 1175 m.Int32Add(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2)))); |
| 1176 Stream s = m.Build(); |
| 1177 ASSERT_EQ(1U, s.size()); |
| 1178 EXPECT_EQ(kArmMla, s[0]->arch_opcode()); |
| 1179 EXPECT_EQ(3U, s[0]->InputCount()); |
| 1180 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1181 } |
| 1182 { |
| 1183 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 1184 kMachineWord32); |
| 1185 m.Return( |
| 1186 m.Int32Add(m.Int32Mul(m.Parameter(1), m.Parameter(2)), m.Parameter(0))); |
| 1187 Stream s = m.Build(); |
| 1188 ASSERT_EQ(1U, s.size()); |
| 1189 EXPECT_EQ(kArmMla, s[0]->arch_opcode()); |
| 1190 EXPECT_EQ(3U, s[0]->InputCount()); |
| 1191 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1192 } |
| 1193 } |
| 1194 |
| 1195 |
| 1196 TEST_F(InstructionSelectorTest, Int32DivWithParameters) { |
| 1197 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1198 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1))); |
| 1199 Stream s = m.Build(); |
| 1200 ASSERT_EQ(4U, s.size()); |
| 1201 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode()); |
| 1202 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1203 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode()); |
| 1204 ASSERT_EQ(1U, s[1]->OutputCount()); |
| 1205 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); |
| 1206 ASSERT_EQ(2U, s[2]->InputCount()); |
| 1207 ASSERT_EQ(1U, s[2]->OutputCount()); |
| 1208 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); |
| 1209 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); |
| 1210 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode()); |
| 1211 ASSERT_EQ(1U, s[3]->InputCount()); |
| 1212 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); |
| 1213 } |
| 1214 |
| 1215 |
| 1216 TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) { |
| 1217 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1218 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1))); |
| 1219 Stream s = m.Build(SUDIV); |
| 1220 ASSERT_EQ(1U, s.size()); |
| 1221 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode()); |
| 1222 } |
| 1223 |
| 1224 |
| 1225 TEST_F(InstructionSelectorTest, Int32ModWithParameters) { |
| 1226 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1227 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1))); |
| 1228 Stream s = m.Build(); |
| 1229 ASSERT_EQ(6U, s.size()); |
| 1230 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode()); |
| 1231 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1232 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode()); |
| 1233 ASSERT_EQ(1U, s[1]->OutputCount()); |
| 1234 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); |
| 1235 ASSERT_EQ(2U, s[2]->InputCount()); |
| 1236 ASSERT_EQ(1U, s[2]->OutputCount()); |
| 1237 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); |
| 1238 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); |
| 1239 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode()); |
| 1240 ASSERT_EQ(1U, s[3]->InputCount()); |
| 1241 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); |
| 1242 EXPECT_EQ(kArmMul, s[4]->arch_opcode()); |
| 1243 ASSERT_EQ(1U, s[4]->OutputCount()); |
| 1244 ASSERT_EQ(2U, s[4]->InputCount()); |
| 1245 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0))); |
| 1246 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1))); |
| 1247 EXPECT_EQ(kArmSub, s[5]->arch_opcode()); |
| 1248 ASSERT_EQ(1U, s[5]->OutputCount()); |
| 1249 ASSERT_EQ(2U, s[5]->InputCount()); |
| 1250 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0))); |
| 1251 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1))); |
| 1252 } |
| 1253 |
| 1254 |
| 1255 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) { |
| 1256 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1257 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1))); |
| 1258 Stream s = m.Build(SUDIV); |
| 1259 ASSERT_EQ(3U, s.size()); |
| 1260 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode()); |
| 1261 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1262 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1263 EXPECT_EQ(kArmMul, s[1]->arch_opcode()); |
| 1264 ASSERT_EQ(1U, s[1]->OutputCount()); |
| 1265 ASSERT_EQ(2U, s[1]->InputCount()); |
| 1266 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); |
| 1267 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); |
| 1268 EXPECT_EQ(kArmSub, s[2]->arch_opcode()); |
| 1269 ASSERT_EQ(1U, s[2]->OutputCount()); |
| 1270 ASSERT_EQ(2U, s[2]->InputCount()); |
| 1271 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0))); |
| 1272 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); |
| 1273 } |
| 1274 |
| 1275 |
| 1276 TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) { |
| 1277 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1278 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1))); |
| 1279 Stream s = m.Build(MLS, SUDIV); |
| 1280 ASSERT_EQ(2U, s.size()); |
| 1281 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode()); |
| 1282 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1283 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1284 EXPECT_EQ(kArmMls, s[1]->arch_opcode()); |
| 1285 ASSERT_EQ(1U, s[1]->OutputCount()); |
| 1286 ASSERT_EQ(3U, s[1]->InputCount()); |
| 1287 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); |
| 1288 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); |
| 1289 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2))); |
| 1290 } |
| 1291 |
| 1292 |
| 1293 TEST_F(InstructionSelectorTest, Int32MulWithParameters) { |
| 1294 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1295 m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1))); |
| 1296 Stream s = m.Build(); |
| 1297 ASSERT_EQ(1U, s.size()); |
| 1298 EXPECT_EQ(kArmMul, s[0]->arch_opcode()); |
| 1299 EXPECT_EQ(2U, s[0]->InputCount()); |
| 1300 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1301 } |
| 1302 |
| 1303 |
| 1304 TEST_F(InstructionSelectorTest, Int32MulWithImmediate) { |
| 1305 // x * (2^k + 1) -> x + (x >> k) |
| 1306 TRACED_FORRANGE(int32_t, k, 1, 30) { |
| 1307 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1308 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1))); |
| 1309 Stream s = m.Build(); |
| 1310 ASSERT_EQ(1U, s.size()); |
| 1311 EXPECT_EQ(kArmAdd, s[0]->arch_opcode()); |
| 1312 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); |
| 1313 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1314 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); |
| 1315 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); |
| 1316 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1317 } |
| 1318 // x * (2^k - 1) -> -x + (x >> k) |
| 1319 TRACED_FORRANGE(int32_t, k, 3, 30) { |
| 1320 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1321 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1))); |
| 1322 Stream s = m.Build(); |
| 1323 ASSERT_EQ(1U, s.size()); |
| 1324 EXPECT_EQ(kArmRsb, s[0]->arch_opcode()); |
| 1325 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); |
| 1326 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1327 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); |
| 1328 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); |
| 1329 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1330 } |
| 1331 // (2^k + 1) * x -> x + (x >> k) |
| 1332 TRACED_FORRANGE(int32_t, k, 1, 30) { |
| 1333 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1334 m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0))); |
| 1335 Stream s = m.Build(); |
| 1336 ASSERT_EQ(1U, s.size()); |
| 1337 EXPECT_EQ(kArmAdd, s[0]->arch_opcode()); |
| 1338 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); |
| 1339 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1340 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); |
| 1341 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); |
| 1342 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1343 } |
| 1344 // x * (2^k - 1) -> -x + (x >> k) |
| 1345 TRACED_FORRANGE(int32_t, k, 3, 30) { |
| 1346 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1347 m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0))); |
| 1348 Stream s = m.Build(); |
| 1349 ASSERT_EQ(1U, s.size()); |
| 1350 EXPECT_EQ(kArmRsb, s[0]->arch_opcode()); |
| 1351 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); |
| 1352 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1353 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); |
| 1354 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); |
| 1355 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1356 } |
| 1357 } |
| 1358 |
| 1359 |
| 1360 TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) { |
| 1361 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 1362 kMachineWord32); |
| 1363 m.Return( |
| 1364 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2)))); |
| 1365 Stream s = m.Build(); |
| 1366 ASSERT_EQ(2U, s.size()); |
| 1367 EXPECT_EQ(kArmMul, s[0]->arch_opcode()); |
| 1368 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1369 EXPECT_EQ(kArmSub, s[1]->arch_opcode()); |
| 1370 ASSERT_EQ(2U, s[1]->InputCount()); |
| 1371 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1))); |
| 1372 } |
| 1373 |
| 1374 |
| 1375 TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) { |
| 1376 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32, |
| 1377 kMachineWord32); |
| 1378 m.Return( |
| 1379 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2)))); |
| 1380 Stream s = m.Build(MLS); |
| 1381 ASSERT_EQ(1U, s.size()); |
| 1382 EXPECT_EQ(kArmMls, s[0]->arch_opcode()); |
| 1383 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1384 EXPECT_EQ(3U, s[0]->InputCount()); |
| 1385 } |
| 1386 |
| 1387 |
| 1388 TEST_F(InstructionSelectorTest, Int32UDivWithParameters) { |
| 1389 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1390 m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1))); |
| 1391 Stream s = m.Build(); |
| 1392 ASSERT_EQ(4U, s.size()); |
| 1393 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode()); |
| 1394 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1395 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode()); |
| 1396 ASSERT_EQ(1U, s[1]->OutputCount()); |
| 1397 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); |
| 1398 ASSERT_EQ(2U, s[2]->InputCount()); |
| 1399 ASSERT_EQ(1U, s[2]->OutputCount()); |
| 1400 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); |
| 1401 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); |
| 1402 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode()); |
| 1403 ASSERT_EQ(1U, s[3]->InputCount()); |
| 1404 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); |
| 1405 } |
| 1406 |
| 1407 |
| 1408 TEST_F(InstructionSelectorTest, Int32UDivWithParametersForSUDIV) { |
| 1409 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1410 m.Return(m.Int32UDiv(m.Parameter(0), m.Parameter(1))); |
| 1411 Stream s = m.Build(SUDIV); |
| 1412 ASSERT_EQ(1U, s.size()); |
| 1413 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode()); |
| 1414 } |
| 1415 |
| 1416 |
| 1417 TEST_F(InstructionSelectorTest, Int32UModWithParameters) { |
| 1418 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1419 m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1))); |
| 1420 Stream s = m.Build(); |
| 1421 ASSERT_EQ(6U, s.size()); |
| 1422 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode()); |
| 1423 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1424 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode()); |
| 1425 ASSERT_EQ(1U, s[1]->OutputCount()); |
| 1426 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); |
| 1427 ASSERT_EQ(2U, s[2]->InputCount()); |
| 1428 ASSERT_EQ(1U, s[2]->OutputCount()); |
| 1429 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); |
| 1430 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); |
| 1431 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode()); |
| 1432 ASSERT_EQ(1U, s[3]->InputCount()); |
| 1433 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); |
| 1434 EXPECT_EQ(kArmMul, s[4]->arch_opcode()); |
| 1435 ASSERT_EQ(1U, s[4]->OutputCount()); |
| 1436 ASSERT_EQ(2U, s[4]->InputCount()); |
| 1437 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0))); |
| 1438 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1))); |
| 1439 EXPECT_EQ(kArmSub, s[5]->arch_opcode()); |
| 1440 ASSERT_EQ(1U, s[5]->OutputCount()); |
| 1441 ASSERT_EQ(2U, s[5]->InputCount()); |
| 1442 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0))); |
| 1443 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1))); |
| 1444 } |
| 1445 |
| 1446 |
| 1447 TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIV) { |
| 1448 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1449 m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1))); |
| 1450 Stream s = m.Build(SUDIV); |
| 1451 ASSERT_EQ(3U, s.size()); |
| 1452 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode()); |
| 1453 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1454 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1455 EXPECT_EQ(kArmMul, s[1]->arch_opcode()); |
| 1456 ASSERT_EQ(1U, s[1]->OutputCount()); |
| 1457 ASSERT_EQ(2U, s[1]->InputCount()); |
| 1458 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); |
| 1459 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); |
| 1460 EXPECT_EQ(kArmSub, s[2]->arch_opcode()); |
| 1461 ASSERT_EQ(1U, s[2]->OutputCount()); |
| 1462 ASSERT_EQ(2U, s[2]->InputCount()); |
| 1463 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0))); |
| 1464 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); |
| 1465 } |
| 1466 |
| 1467 |
| 1468 TEST_F(InstructionSelectorTest, Int32UModWithParametersForSUDIVAndMLS) { |
| 1469 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1470 m.Return(m.Int32UMod(m.Parameter(0), m.Parameter(1))); |
| 1471 Stream s = m.Build(MLS, SUDIV); |
| 1472 ASSERT_EQ(2U, s.size()); |
| 1473 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode()); |
| 1474 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1475 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1476 EXPECT_EQ(kArmMls, s[1]->arch_opcode()); |
| 1477 ASSERT_EQ(1U, s[1]->OutputCount()); |
| 1478 ASSERT_EQ(3U, s[1]->InputCount()); |
| 1479 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); |
| 1480 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); |
| 1481 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2))); |
| 1482 } |
| 1483 |
| 1484 |
| 1485 TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) { |
| 1486 TRACED_FORRANGE(int32_t, width, 1, 32) { |
| 1487 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1488 m.Return(m.Word32And(m.Parameter(0), |
| 1489 m.Int32Constant(0xffffffffu >> (32 - width)))); |
| 1490 Stream s = m.Build(ARMv7); |
| 1491 ASSERT_EQ(1U, s.size()); |
| 1492 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); |
| 1493 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1494 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); |
| 1495 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 1496 } |
| 1497 TRACED_FORRANGE(int32_t, width, 1, 32) { |
| 1498 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1499 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)), |
| 1500 m.Parameter(0))); |
| 1501 Stream s = m.Build(ARMv7); |
| 1502 ASSERT_EQ(1U, s.size()); |
| 1503 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); |
| 1504 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1505 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); |
| 1506 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 1507 } |
| 1508 } |
| 1509 |
| 1510 |
| 1511 TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) { |
| 1512 TRACED_FORRANGE(int32_t, lsb, 0, 31) { |
| 1513 TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) { |
| 1514 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1515 m.Return(m.Word32And( |
| 1516 m.Parameter(0), |
| 1517 m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)))); |
| 1518 Stream s = m.Build(ARMv7); |
| 1519 ASSERT_EQ(1U, s.size()); |
| 1520 EXPECT_EQ(kArmBfc, s[0]->arch_opcode()); |
| 1521 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1522 EXPECT_TRUE( |
| 1523 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); |
| 1524 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1525 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 1526 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 1527 } |
| 1528 } |
| 1529 TRACED_FORRANGE(int32_t, lsb, 0, 31) { |
| 1530 TRACED_FORRANGE(int32_t, width, 1, (32 - lsb) - 1) { |
| 1531 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1532 m.Return( |
| 1533 m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)), |
| 1534 m.Parameter(0))); |
| 1535 Stream s = m.Build(ARMv7); |
| 1536 ASSERT_EQ(1U, s.size()); |
| 1537 EXPECT_EQ(kArmBfc, s[0]->arch_opcode()); |
| 1538 ASSERT_EQ(1U, s[0]->OutputCount()); |
| 1539 EXPECT_TRUE( |
| 1540 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); |
| 1541 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1542 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 1543 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 1544 } |
| 1545 } |
| 1546 } |
| 1547 |
| 1548 |
| 1549 TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) { |
| 1550 TRACED_FORRANGE(int32_t, lsb, 0, 31) { |
| 1551 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { |
| 1552 uint32_t max = 1 << lsb; |
| 1553 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1; |
| 1554 uint32_t jnk = rng()->NextInt(max); |
| 1555 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; |
| 1556 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1557 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)), |
| 1558 m.Int32Constant(lsb))); |
| 1559 Stream s = m.Build(ARMv7); |
| 1560 ASSERT_EQ(1U, s.size()); |
| 1561 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); |
| 1562 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1563 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 1564 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 1565 } |
| 1566 } |
| 1567 TRACED_FORRANGE(int32_t, lsb, 0, 31) { |
| 1568 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { |
| 1569 uint32_t max = 1 << lsb; |
| 1570 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1; |
| 1571 uint32_t jnk = rng()->NextInt(max); |
| 1572 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; |
| 1573 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1574 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)), |
| 1575 m.Int32Constant(lsb))); |
| 1576 Stream s = m.Build(ARMv7); |
| 1577 ASSERT_EQ(1U, s.size()); |
| 1578 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); |
| 1579 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1580 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 1581 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 1582 } |
| 1583 } |
| 1584 } |
| 1585 |
| 1586 |
| 1587 TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) { |
| 1588 { |
| 1589 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1590 m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1)))); |
| 1591 Stream s = m.Build(); |
| 1592 ASSERT_EQ(1U, s.size()); |
| 1593 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); |
| 1594 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 1595 EXPECT_EQ(2U, s[0]->InputCount()); |
| 1596 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1597 } |
| 1598 { |
| 1599 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1600 m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1))); |
| 1601 Stream s = m.Build(); |
| 1602 ASSERT_EQ(1U, s.size()); |
| 1603 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); |
| 1604 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 1605 EXPECT_EQ(2U, s[0]->InputCount()); |
| 1606 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1607 } |
| 1608 } |
| 1609 |
| 1610 |
| 1611 TEST_F(InstructionSelectorTest, Word32EqualWithParameters) { |
| 1612 StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32); |
| 1613 m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1))); |
| 1614 Stream s = m.Build(); |
| 1615 ASSERT_EQ(1U, s.size()); |
| 1616 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); |
| 1617 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 1618 EXPECT_EQ(2U, s[0]->InputCount()); |
| 1619 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1620 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1621 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1622 } |
| 1623 |
| 1624 |
| 1625 TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) { |
| 1626 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 1627 if (imm == 0) continue; |
| 1628 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1629 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm))); |
| 1630 Stream s = m.Build(); |
| 1631 ASSERT_EQ(1U, s.size()); |
| 1632 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); |
| 1633 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 1634 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1635 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 1636 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1637 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1638 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1639 } |
| 1640 TRACED_FOREACH(int32_t, imm, kImmediates) { |
| 1641 if (imm == 0) continue; |
| 1642 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1643 m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0))); |
| 1644 Stream s = m.Build(); |
| 1645 ASSERT_EQ(1U, s.size()); |
| 1646 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); |
| 1647 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); |
| 1648 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1649 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| 1650 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1651 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1652 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1653 } |
| 1654 } |
| 1655 |
| 1656 |
| 1657 TEST_F(InstructionSelectorTest, Word32EqualWithZero) { |
| 1658 { |
| 1659 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1660 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0))); |
| 1661 Stream s = m.Build(); |
| 1662 ASSERT_EQ(1U, s.size()); |
| 1663 EXPECT_EQ(kArmTst, s[0]->arch_opcode()); |
| 1664 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 1665 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1666 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); |
| 1667 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1668 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1669 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1670 } |
| 1671 { |
| 1672 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1673 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0))); |
| 1674 Stream s = m.Build(); |
| 1675 ASSERT_EQ(1U, s.size()); |
| 1676 EXPECT_EQ(kArmTst, s[0]->arch_opcode()); |
| 1677 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 1678 ASSERT_EQ(2U, s[0]->InputCount()); |
| 1679 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); |
| 1680 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1681 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| 1682 EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| 1683 } |
| 1684 } |
| 1685 |
| 1686 |
| 1687 TEST_F(InstructionSelectorTest, Word32NotWithParameter) { |
| 1688 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1689 m.Return(m.Word32Not(m.Parameter(0))); |
| 1690 Stream s = m.Build(); |
| 1691 ASSERT_EQ(1U, s.size()); |
| 1692 EXPECT_EQ(kArmMvn, s[0]->arch_opcode()); |
| 1693 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); |
| 1694 EXPECT_EQ(1U, s[0]->InputCount()); |
| 1695 EXPECT_EQ(1U, s[0]->OutputCount()); |
| 1696 } |
| 1697 |
| 1698 |
| 1699 TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) { |
| 1700 TRACED_FORRANGE(int32_t, lsb, 0, 31) { |
| 1701 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { |
| 1702 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1703 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)), |
| 1704 m.Int32Constant(0xffffffffu >> (32 - width)))); |
| 1705 Stream s = m.Build(ARMv7); |
| 1706 ASSERT_EQ(1U, s.size()); |
| 1707 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); |
| 1708 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1709 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 1710 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 1711 } |
| 1712 } |
| 1713 TRACED_FORRANGE(int32_t, lsb, 0, 31) { |
| 1714 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { |
| 1715 StreamBuilder m(this, kMachineWord32, kMachineWord32); |
| 1716 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)), |
| 1717 m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)))); |
| 1718 Stream s = m.Build(ARMv7); |
| 1719 ASSERT_EQ(1U, s.size()); |
| 1720 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); |
| 1721 ASSERT_EQ(3U, s[0]->InputCount()); |
| 1722 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); |
| 1723 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); |
| 1724 } |
| 1725 } |
| 1726 } |
| 1727 |
25 } // namespace compiler | 1728 } // namespace compiler |
26 } // namespace internal | 1729 } // namespace internal |
27 } // namespace v8 | 1730 } // namespace v8 |
OLD | NEW |