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 3// found in the LICENSE file. 4 5#include <limits> 6 7#include "test/unittests/compiler/instruction-selector-unittest.h" 8 9namespace v8 { 10namespace internal { 11namespace compiler { 12 13namespace { 14 15typedef Node* (RawMachineAssembler::*Constructor)(Node*, Node*); 16 17 18// Data processing instructions. 19struct DPI { 20 Constructor constructor; 21 const char* constructor_name; 22 ArchOpcode arch_opcode; 23 ArchOpcode reverse_arch_opcode; 24 ArchOpcode test_arch_opcode; 25}; 26 27 28std::ostream& operator<<(std::ostream& os, const DPI& dpi) { 29 return os << dpi.constructor_name; 30} 31 32 33const DPI kDPIs[] = { 34 {&RawMachineAssembler::Word32And, "Word32And", kArmAnd, kArmAnd, kArmTst}, 35 {&RawMachineAssembler::Word32Or, "Word32Or", kArmOrr, kArmOrr, kArmOrr}, 36 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArmEor, kArmEor, kArmTeq}, 37 {&RawMachineAssembler::Int32Add, "Int32Add", kArmAdd, kArmAdd, kArmCmn}, 38 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArmSub, kArmRsb, kArmCmp}}; 39 40 41// Floating point arithmetic instructions. 42struct FAI { 43 Constructor constructor; 44 const char* constructor_name; 45 MachineType machine_type; 46 ArchOpcode arch_opcode; 47}; 48 49 50std::ostream& operator<<(std::ostream& os, const FAI& fai) { 51 return os << fai.constructor_name; 52} 53 54 55const FAI kFAIs[] = {{&RawMachineAssembler::Float32Add, "Float32Add", 56 MachineType::Float32(), kArmVaddF32}, 57 {&RawMachineAssembler::Float64Add, "Float64Add", 58 MachineType::Float64(), kArmVaddF64}, 59 {&RawMachineAssembler::Float32Sub, "Float32Sub", 60 MachineType::Float32(), kArmVsubF32}, 61 {&RawMachineAssembler::Float64Sub, "Float64Sub", 62 MachineType::Float64(), kArmVsubF64}, 63 {&RawMachineAssembler::Float32Mul, "Float32Mul", 64 MachineType::Float32(), kArmVmulF32}, 65 {&RawMachineAssembler::Float64Mul, "Float64Mul", 66 MachineType::Float64(), kArmVmulF64}, 67 {&RawMachineAssembler::Float32Div, "Float32Div", 68 MachineType::Float32(), kArmVdivF32}, 69 {&RawMachineAssembler::Float64Div, "Float64Div", 70 MachineType::Float64(), kArmVdivF64}}; 71 72 73// Data processing instructions with overflow. 74struct ODPI { 75 Constructor constructor; 76 const char* constructor_name; 77 ArchOpcode arch_opcode; 78 ArchOpcode reverse_arch_opcode; 79}; 80 81 82std::ostream& operator<<(std::ostream& os, const ODPI& odpi) { 83 return os << odpi.constructor_name; 84} 85 86 87const ODPI kODPIs[] = {{&RawMachineAssembler::Int32AddWithOverflow, 88 "Int32AddWithOverflow", kArmAdd, kArmAdd}, 89 {&RawMachineAssembler::Int32SubWithOverflow, 90 "Int32SubWithOverflow", kArmSub, kArmRsb}}; 91 92 93// Shifts. 94struct Shift { 95 Constructor constructor; 96 const char* constructor_name; 97 int32_t i_low; // lowest possible immediate 98 int32_t i_high; // highest possible immediate 99 AddressingMode i_mode; // Operand2_R_<shift>_I 100 AddressingMode r_mode; // Operand2_R_<shift>_R 101}; 102 103 104std::ostream& operator<<(std::ostream& os, const Shift& shift) { 105 return os << shift.constructor_name; 106} 107 108 109const Shift kShifts[] = {{&RawMachineAssembler::Word32Sar, "Word32Sar", 1, 32, 110 kMode_Operand2_R_ASR_I, kMode_Operand2_R_ASR_R}, 111 {&RawMachineAssembler::Word32Shl, "Word32Shl", 0, 31, 112 kMode_Operand2_R_LSL_I, kMode_Operand2_R_LSL_R}, 113 {&RawMachineAssembler::Word32Shr, "Word32Shr", 1, 32, 114 kMode_Operand2_R_LSR_I, kMode_Operand2_R_LSR_R}, 115 {&RawMachineAssembler::Word32Ror, "Word32Ror", 1, 31, 116 kMode_Operand2_R_ROR_I, kMode_Operand2_R_ROR_R}}; 117 118 119// Immediates (random subset). 120const int32_t kImmediates[] = { 121 std::numeric_limits<int32_t>::min(), -2147483617, -2147483606, -2113929216, 122 -2080374784, -1996488704, -1879048192, -1459617792, -1358954496, 123 -1342177265, -1275068414, -1073741818, -1073741777, -855638016, -805306368, 124 -402653184, -268435444, -16777216, 0, 35, 61, 105, 116, 171, 245, 255, 692, 125 1216, 1248, 1520, 1600, 1888, 3744, 4080, 5888, 8384, 9344, 9472, 9792, 126 13312, 15040, 15360, 20736, 22272, 23296, 32000, 33536, 37120, 45824, 47872, 127 56320, 59392, 65280, 72704, 101376, 147456, 161792, 164864, 167936, 173056, 128 195584, 209920, 212992, 356352, 655360, 704512, 716800, 851968, 901120, 129 1044480, 1523712, 2572288, 3211264, 3588096, 3833856, 3866624, 4325376, 130 5177344, 6488064, 7012352, 7471104, 14090240, 16711680, 19398656, 22282240, 131 28573696, 30408704, 30670848, 43253760, 54525952, 55312384, 56623104, 132 68157440, 115343360, 131072000, 187695104, 188743680, 195035136, 197132288, 133 203423744, 218103808, 267386880, 268435470, 285212672, 402653185, 415236096, 134 595591168, 603979776, 603979778, 629145600, 1073741835, 1073741855, 135 1073741861, 1073741884, 1157627904, 1476395008, 1476395010, 1610612741, 136 2030043136, 2080374785, 2097152000}; 137 138} // namespace 139 140 141// ----------------------------------------------------------------------------- 142// Data processing instructions. 143 144 145typedef InstructionSelectorTestWithParam<DPI> InstructionSelectorDPITest; 146 147 148TEST_P(InstructionSelectorDPITest, Parameters) { 149 const DPI dpi = GetParam(); 150 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 151 MachineType::Int32()); 152 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); 153 Stream s = m.Build(); 154 ASSERT_EQ(1U, s.size()); 155 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); 156 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 157 EXPECT_EQ(2U, s[0]->InputCount()); 158 EXPECT_EQ(1U, s[0]->OutputCount()); 159} 160 161 162TEST_P(InstructionSelectorDPITest, Immediate) { 163 const DPI dpi = GetParam(); 164 TRACED_FOREACH(int32_t, imm, kImmediates) { 165 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 166 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); 167 Stream s = m.Build(); 168 ASSERT_EQ(1U, s.size()); 169 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); 170 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 171 ASSERT_EQ(2U, s[0]->InputCount()); 172 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 173 EXPECT_EQ(1U, s[0]->OutputCount()); 174 } 175 TRACED_FOREACH(int32_t, imm, kImmediates) { 176 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 177 m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0))); 178 Stream s = m.Build(); 179 ASSERT_EQ(1U, s.size()); 180 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode()); 181 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 182 ASSERT_EQ(2U, s[0]->InputCount()); 183 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 184 EXPECT_EQ(1U, s[0]->OutputCount()); 185 } 186} 187 188 189TEST_P(InstructionSelectorDPITest, ShiftByParameter) { 190 const DPI dpi = GetParam(); 191 TRACED_FOREACH(Shift, shift, kShifts) { 192 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 193 MachineType::Int32(), MachineType::Int32()); 194 m.Return((m.*dpi.constructor)( 195 m.Parameter(0), 196 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))); 197 Stream s = m.Build(); 198 ASSERT_EQ(1U, s.size()); 199 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); 200 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 201 EXPECT_EQ(3U, s[0]->InputCount()); 202 EXPECT_EQ(1U, s[0]->OutputCount()); 203 } 204 TRACED_FOREACH(Shift, shift, kShifts) { 205 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 206 MachineType::Int32(), MachineType::Int32()); 207 m.Return((m.*dpi.constructor)( 208 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), 209 m.Parameter(2))); 210 Stream s = m.Build(); 211 ASSERT_EQ(1U, s.size()); 212 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode()); 213 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 214 EXPECT_EQ(3U, s[0]->InputCount()); 215 EXPECT_EQ(1U, s[0]->OutputCount()); 216 } 217} 218 219 220TEST_P(InstructionSelectorDPITest, ShiftByImmediate) { 221 const DPI dpi = GetParam(); 222 TRACED_FOREACH(Shift, shift, kShifts) { 223 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 224 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 225 MachineType::Int32()); 226 m.Return((m.*dpi.constructor)( 227 m.Parameter(0), 228 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)))); 229 Stream s = m.Build(); 230 ASSERT_EQ(1U, s.size()); 231 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); 232 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 233 ASSERT_EQ(3U, s[0]->InputCount()); 234 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 235 EXPECT_EQ(1U, s[0]->OutputCount()); 236 } 237 } 238 TRACED_FOREACH(Shift, shift, kShifts) { 239 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 240 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 241 MachineType::Int32()); 242 m.Return((m.*dpi.constructor)( 243 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)), 244 m.Parameter(1))); 245 Stream s = m.Build(); 246 ASSERT_EQ(1U, s.size()); 247 EXPECT_EQ(dpi.reverse_arch_opcode, s[0]->arch_opcode()); 248 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 249 ASSERT_EQ(3U, s[0]->InputCount()); 250 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 251 EXPECT_EQ(1U, s[0]->OutputCount()); 252 } 253 } 254} 255 256 257TEST_P(InstructionSelectorDPITest, BranchWithParameters) { 258 const DPI dpi = GetParam(); 259 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 260 MachineType::Int32()); 261 RawMachineLabel a, b; 262 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), &a, &b); 263 m.Bind(&a); 264 m.Return(m.Int32Constant(1)); 265 m.Bind(&b); 266 m.Return(m.Int32Constant(0)); 267 Stream s = m.Build(); 268 ASSERT_EQ(1U, s.size()); 269 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 270 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 271 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 272 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 273} 274 275 276TEST_P(InstructionSelectorDPITest, BranchWithImmediate) { 277 const DPI dpi = GetParam(); 278 TRACED_FOREACH(int32_t, imm, kImmediates) { 279 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 280 RawMachineLabel a, b; 281 m.Branch((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), &a, 282 &b); 283 m.Bind(&a); 284 m.Return(m.Int32Constant(1)); 285 m.Bind(&b); 286 m.Return(m.Int32Constant(0)); 287 Stream s = m.Build(); 288 ASSERT_EQ(1U, s.size()); 289 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 290 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 291 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 292 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 293 } 294 TRACED_FOREACH(int32_t, imm, kImmediates) { 295 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 296 RawMachineLabel a, b; 297 m.Branch((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), &a, 298 &b); 299 m.Bind(&a); 300 m.Return(m.Int32Constant(1)); 301 m.Bind(&b); 302 m.Return(m.Int32Constant(0)); 303 Stream s = m.Build(); 304 ASSERT_EQ(1U, s.size()); 305 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 306 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 307 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 308 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 309 } 310} 311 312 313TEST_P(InstructionSelectorDPITest, BranchWithShiftByParameter) { 314 const DPI dpi = GetParam(); 315 TRACED_FOREACH(Shift, shift, kShifts) { 316 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 317 MachineType::Int32(), MachineType::Int32()); 318 RawMachineLabel a, b; 319 m.Branch((m.*dpi.constructor)( 320 m.Parameter(0), 321 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))), 322 &a, &b); 323 m.Bind(&a); 324 m.Return(m.Int32Constant(1)); 325 m.Bind(&b); 326 m.Return(m.Int32Constant(0)); 327 Stream s = m.Build(); 328 ASSERT_EQ(1U, s.size()); 329 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 330 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 331 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 332 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 333 } 334 TRACED_FOREACH(Shift, shift, kShifts) { 335 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 336 MachineType::Int32(), MachineType::Int32()); 337 RawMachineLabel a, b; 338 m.Branch((m.*dpi.constructor)( 339 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), 340 m.Parameter(2)), 341 &a, &b); 342 m.Bind(&a); 343 m.Return(m.Int32Constant(1)); 344 m.Bind(&b); 345 m.Return(m.Int32Constant(0)); 346 Stream s = m.Build(); 347 ASSERT_EQ(1U, s.size()); 348 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 349 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 350 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 351 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 352 } 353} 354 355 356TEST_P(InstructionSelectorDPITest, BranchWithShiftByImmediate) { 357 const DPI dpi = GetParam(); 358 TRACED_FOREACH(Shift, shift, kShifts) { 359 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 360 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 361 MachineType::Int32()); 362 RawMachineLabel a, b; 363 m.Branch((m.*dpi.constructor)(m.Parameter(0), 364 (m.*shift.constructor)( 365 m.Parameter(1), m.Int32Constant(imm))), 366 &a, &b); 367 m.Bind(&a); 368 m.Return(m.Int32Constant(1)); 369 m.Bind(&b); 370 m.Return(m.Int32Constant(0)); 371 Stream s = m.Build(); 372 ASSERT_EQ(1U, s.size()); 373 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 374 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 375 ASSERT_EQ(5U, s[0]->InputCount()); 376 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 377 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 378 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 379 } 380 } 381 TRACED_FOREACH(Shift, shift, kShifts) { 382 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 383 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 384 MachineType::Int32()); 385 RawMachineLabel a, b; 386 m.Branch((m.*dpi.constructor)( 387 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)), 388 m.Parameter(1)), 389 &a, &b); 390 m.Bind(&a); 391 m.Return(m.Int32Constant(1)); 392 m.Bind(&b); 393 m.Return(m.Int32Constant(0)); 394 Stream s = m.Build(); 395 ASSERT_EQ(1U, s.size()); 396 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 397 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 398 ASSERT_EQ(5U, s[0]->InputCount()); 399 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 400 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 401 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 402 } 403 } 404} 405 406 407TEST_P(InstructionSelectorDPITest, BranchIfZeroWithParameters) { 408 const DPI dpi = GetParam(); 409 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 410 MachineType::Int32()); 411 RawMachineLabel a, b; 412 m.Branch(m.Word32Equal((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), 413 m.Int32Constant(0)), 414 &a, &b); 415 m.Bind(&a); 416 m.Return(m.Int32Constant(1)); 417 m.Bind(&b); 418 m.Return(m.Int32Constant(0)); 419 Stream s = m.Build(); 420 ASSERT_EQ(1U, s.size()); 421 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 422 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 423 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 424 EXPECT_EQ(kEqual, s[0]->flags_condition()); 425} 426 427 428TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithParameters) { 429 const DPI dpi = GetParam(); 430 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 431 MachineType::Int32()); 432 RawMachineLabel a, b; 433 m.Branch( 434 m.Word32NotEqual((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1)), 435 m.Int32Constant(0)), 436 &a, &b); 437 m.Bind(&a); 438 m.Return(m.Int32Constant(1)); 439 m.Bind(&b); 440 m.Return(m.Int32Constant(0)); 441 Stream s = m.Build(); 442 ASSERT_EQ(1U, s.size()); 443 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 444 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 445 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 446 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 447} 448 449 450TEST_P(InstructionSelectorDPITest, BranchIfZeroWithImmediate) { 451 const DPI dpi = GetParam(); 452 TRACED_FOREACH(int32_t, imm, kImmediates) { 453 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 454 RawMachineLabel a, b; 455 m.Branch(m.Word32Equal( 456 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), 457 m.Int32Constant(0)), 458 &a, &b); 459 m.Bind(&a); 460 m.Return(m.Int32Constant(1)); 461 m.Bind(&b); 462 m.Return(m.Int32Constant(0)); 463 Stream s = m.Build(); 464 ASSERT_EQ(1U, s.size()); 465 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 466 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 467 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 468 EXPECT_EQ(kEqual, s[0]->flags_condition()); 469 } 470 TRACED_FOREACH(int32_t, imm, kImmediates) { 471 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 472 RawMachineLabel a, b; 473 m.Branch(m.Word32Equal( 474 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), 475 m.Int32Constant(0)), 476 &a, &b); 477 m.Bind(&a); 478 m.Return(m.Int32Constant(1)); 479 m.Bind(&b); 480 m.Return(m.Int32Constant(0)); 481 Stream s = m.Build(); 482 ASSERT_EQ(1U, s.size()); 483 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 484 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 485 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 486 EXPECT_EQ(kEqual, s[0]->flags_condition()); 487 } 488} 489 490 491TEST_P(InstructionSelectorDPITest, BranchIfNotZeroWithImmediate) { 492 const DPI dpi = GetParam(); 493 TRACED_FOREACH(int32_t, imm, kImmediates) { 494 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 495 RawMachineLabel a, b; 496 m.Branch(m.Word32NotEqual( 497 (m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm)), 498 m.Int32Constant(0)), 499 &a, &b); 500 m.Bind(&a); 501 m.Return(m.Int32Constant(1)); 502 m.Bind(&b); 503 m.Return(m.Int32Constant(0)); 504 Stream s = m.Build(); 505 ASSERT_EQ(1U, s.size()); 506 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 507 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 508 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 509 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 510 } 511 TRACED_FOREACH(int32_t, imm, kImmediates) { 512 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 513 RawMachineLabel a, b; 514 m.Branch(m.Word32NotEqual( 515 (m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0)), 516 m.Int32Constant(0)), 517 &a, &b); 518 m.Bind(&a); 519 m.Return(m.Int32Constant(1)); 520 m.Bind(&b); 521 m.Return(m.Int32Constant(0)); 522 Stream s = m.Build(); 523 ASSERT_EQ(1U, s.size()); 524 EXPECT_EQ(dpi.test_arch_opcode, s[0]->arch_opcode()); 525 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 526 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 527 EXPECT_EQ(kNotEqual, s[0]->flags_condition()); 528 } 529} 530 531 532INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorDPITest, 533 ::testing::ValuesIn(kDPIs)); 534 535 536// ----------------------------------------------------------------------------- 537// Data processing instructions with overflow. 538 539 540typedef InstructionSelectorTestWithParam<ODPI> InstructionSelectorODPITest; 541 542 543TEST_P(InstructionSelectorODPITest, OvfWithParameters) { 544 const ODPI odpi = GetParam(); 545 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 546 MachineType::Int32()); 547 m.Return( 548 m.Projection(1, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)))); 549 Stream s = m.Build(); 550 ASSERT_EQ(1U, s.size()); 551 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 552 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 553 EXPECT_EQ(2U, s[0]->InputCount()); 554 EXPECT_LE(1U, s[0]->OutputCount()); 555 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 556 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 557} 558 559 560TEST_P(InstructionSelectorODPITest, OvfWithImmediate) { 561 const ODPI odpi = GetParam(); 562 TRACED_FOREACH(int32_t, imm, kImmediates) { 563 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 564 m.Return(m.Projection( 565 1, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)))); 566 Stream s = m.Build(); 567 ASSERT_EQ(1U, s.size()); 568 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 569 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 570 ASSERT_EQ(2U, s[0]->InputCount()); 571 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 572 EXPECT_LE(1U, s[0]->OutputCount()); 573 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 574 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 575 } 576 TRACED_FOREACH(int32_t, imm, kImmediates) { 577 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 578 m.Return(m.Projection( 579 1, (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)))); 580 Stream s = m.Build(); 581 ASSERT_EQ(1U, s.size()); 582 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); 583 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 584 ASSERT_EQ(2U, s[0]->InputCount()); 585 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 586 EXPECT_LE(1U, s[0]->OutputCount()); 587 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 588 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 589 } 590} 591 592 593TEST_P(InstructionSelectorODPITest, OvfWithShiftByParameter) { 594 const ODPI odpi = GetParam(); 595 TRACED_FOREACH(Shift, shift, kShifts) { 596 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 597 MachineType::Int32(), MachineType::Int32()); 598 m.Return(m.Projection( 599 1, (m.*odpi.constructor)( 600 m.Parameter(0), 601 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))))); 602 Stream s = m.Build(); 603 ASSERT_EQ(1U, s.size()); 604 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 605 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 606 EXPECT_EQ(3U, s[0]->InputCount()); 607 EXPECT_LE(1U, s[0]->OutputCount()); 608 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 609 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 610 } 611 TRACED_FOREACH(Shift, shift, kShifts) { 612 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 613 MachineType::Int32(), MachineType::Int32()); 614 m.Return(m.Projection( 615 1, (m.*odpi.constructor)( 616 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), 617 m.Parameter(0)))); 618 Stream s = m.Build(); 619 ASSERT_EQ(1U, s.size()); 620 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); 621 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 622 EXPECT_EQ(3U, s[0]->InputCount()); 623 EXPECT_LE(1U, s[0]->OutputCount()); 624 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 625 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 626 } 627} 628 629 630TEST_P(InstructionSelectorODPITest, OvfWithShiftByImmediate) { 631 const ODPI odpi = GetParam(); 632 TRACED_FOREACH(Shift, shift, kShifts) { 633 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 634 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 635 MachineType::Int32()); 636 m.Return(m.Projection( 637 1, (m.*odpi.constructor)(m.Parameter(0), 638 (m.*shift.constructor)( 639 m.Parameter(1), m.Int32Constant(imm))))); 640 Stream s = m.Build(); 641 ASSERT_EQ(1U, s.size()); 642 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 643 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 644 ASSERT_EQ(3U, s[0]->InputCount()); 645 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 646 EXPECT_LE(1U, s[0]->OutputCount()); 647 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 648 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 649 } 650 } 651 TRACED_FOREACH(Shift, shift, kShifts) { 652 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 653 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 654 MachineType::Int32()); 655 m.Return(m.Projection( 656 1, (m.*odpi.constructor)( 657 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)), 658 m.Parameter(0)))); 659 Stream s = m.Build(); 660 ASSERT_EQ(1U, s.size()); 661 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); 662 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 663 ASSERT_EQ(3U, s[0]->InputCount()); 664 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 665 EXPECT_LE(1U, s[0]->OutputCount()); 666 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 667 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 668 } 669 } 670} 671 672 673TEST_P(InstructionSelectorODPITest, ValWithParameters) { 674 const ODPI odpi = GetParam(); 675 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 676 MachineType::Int32()); 677 m.Return( 678 m.Projection(0, (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)))); 679 Stream s = m.Build(); 680 ASSERT_EQ(1U, s.size()); 681 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 682 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 683 EXPECT_EQ(2U, s[0]->InputCount()); 684 EXPECT_LE(1U, s[0]->OutputCount()); 685 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 686} 687 688 689TEST_P(InstructionSelectorODPITest, ValWithImmediate) { 690 const ODPI odpi = GetParam(); 691 TRACED_FOREACH(int32_t, imm, kImmediates) { 692 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 693 m.Return(m.Projection( 694 0, (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)))); 695 Stream s = m.Build(); 696 ASSERT_EQ(1U, s.size()); 697 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 698 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 699 ASSERT_EQ(2U, s[0]->InputCount()); 700 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 701 EXPECT_LE(1U, s[0]->OutputCount()); 702 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 703 } 704 TRACED_FOREACH(int32_t, imm, kImmediates) { 705 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 706 m.Return(m.Projection( 707 0, (m.*odpi.constructor)(m.Int32Constant(imm), 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(kMode_Operand2_I, s[0]->addressing_mode()); 712 ASSERT_EQ(2U, s[0]->InputCount()); 713 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 714 EXPECT_LE(1U, s[0]->OutputCount()); 715 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 716 } 717} 718 719 720TEST_P(InstructionSelectorODPITest, ValWithShiftByParameter) { 721 const ODPI odpi = GetParam(); 722 TRACED_FOREACH(Shift, shift, kShifts) { 723 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 724 MachineType::Int32(), MachineType::Int32()); 725 m.Return(m.Projection( 726 0, (m.*odpi.constructor)( 727 m.Parameter(0), 728 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))))); 729 Stream s = m.Build(); 730 ASSERT_EQ(1U, s.size()); 731 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 732 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 733 EXPECT_EQ(3U, s[0]->InputCount()); 734 EXPECT_LE(1U, s[0]->OutputCount()); 735 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 736 } 737 TRACED_FOREACH(Shift, shift, kShifts) { 738 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 739 MachineType::Int32(), MachineType::Int32()); 740 m.Return(m.Projection( 741 0, (m.*odpi.constructor)( 742 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), 743 m.Parameter(0)))); 744 Stream s = m.Build(); 745 ASSERT_EQ(1U, s.size()); 746 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); 747 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 748 EXPECT_EQ(3U, s[0]->InputCount()); 749 EXPECT_LE(1U, s[0]->OutputCount()); 750 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 751 } 752} 753 754 755TEST_P(InstructionSelectorODPITest, ValWithShiftByImmediate) { 756 const ODPI odpi = GetParam(); 757 TRACED_FOREACH(Shift, shift, kShifts) { 758 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 759 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 760 MachineType::Int32()); 761 m.Return(m.Projection( 762 0, (m.*odpi.constructor)(m.Parameter(0), 763 (m.*shift.constructor)( 764 m.Parameter(1), m.Int32Constant(imm))))); 765 Stream s = m.Build(); 766 ASSERT_EQ(1U, s.size()); 767 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 768 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 769 ASSERT_EQ(3U, s[0]->InputCount()); 770 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 771 EXPECT_LE(1U, s[0]->OutputCount()); 772 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 773 } 774 } 775 TRACED_FOREACH(Shift, shift, kShifts) { 776 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 777 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 778 MachineType::Int32()); 779 m.Return(m.Projection( 780 0, (m.*odpi.constructor)( 781 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)), 782 m.Parameter(0)))); 783 Stream s = m.Build(); 784 ASSERT_EQ(1U, s.size()); 785 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); 786 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 787 ASSERT_EQ(3U, s[0]->InputCount()); 788 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 789 EXPECT_LE(1U, s[0]->OutputCount()); 790 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 791 } 792 } 793} 794 795 796TEST_P(InstructionSelectorODPITest, BothWithParameters) { 797 const ODPI odpi = GetParam(); 798 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 799 MachineType::Int32()); 800 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); 801 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); 802 Stream s = m.Build(); 803 ASSERT_LE(1U, s.size()); 804 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 805 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 806 EXPECT_EQ(2U, s[0]->InputCount()); 807 EXPECT_EQ(2U, s[0]->OutputCount()); 808 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 809 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 810} 811 812 813TEST_P(InstructionSelectorODPITest, BothWithImmediate) { 814 const ODPI odpi = GetParam(); 815 TRACED_FOREACH(int32_t, imm, kImmediates) { 816 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 817 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); 818 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); 819 Stream s = m.Build(); 820 ASSERT_LE(1U, s.size()); 821 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 822 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 823 ASSERT_EQ(2U, s[0]->InputCount()); 824 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 825 EXPECT_EQ(2U, s[0]->OutputCount()); 826 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 827 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 828 } 829 TRACED_FOREACH(int32_t, imm, kImmediates) { 830 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 831 Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)); 832 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); 833 Stream s = m.Build(); 834 ASSERT_LE(1U, s.size()); 835 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); 836 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 837 ASSERT_EQ(2U, s[0]->InputCount()); 838 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 839 EXPECT_EQ(2U, s[0]->OutputCount()); 840 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 841 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 842 } 843} 844 845 846TEST_P(InstructionSelectorODPITest, BothWithShiftByParameter) { 847 const ODPI odpi = GetParam(); 848 TRACED_FOREACH(Shift, shift, kShifts) { 849 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 850 MachineType::Int32(), MachineType::Int32()); 851 Node* n = (m.*odpi.constructor)( 852 m.Parameter(0), (m.*shift.constructor)(m.Parameter(1), m.Parameter(2))); 853 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); 854 Stream s = m.Build(); 855 ASSERT_LE(1U, s.size()); 856 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 857 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 858 EXPECT_EQ(3U, s[0]->InputCount()); 859 EXPECT_EQ(2U, s[0]->OutputCount()); 860 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 861 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 862 } 863 TRACED_FOREACH(Shift, shift, kShifts) { 864 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 865 MachineType::Int32(), MachineType::Int32()); 866 Node* n = (m.*odpi.constructor)( 867 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)), m.Parameter(2)); 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.r_mode, s[0]->addressing_mode()); 873 EXPECT_EQ(3U, s[0]->InputCount()); 874 EXPECT_EQ(2U, s[0]->OutputCount()); 875 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 876 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 877 } 878} 879 880 881TEST_P(InstructionSelectorODPITest, BothWithShiftByImmediate) { 882 const ODPI odpi = GetParam(); 883 TRACED_FOREACH(Shift, shift, kShifts) { 884 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 885 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 886 MachineType::Int32()); 887 Node* n = (m.*odpi.constructor)( 888 m.Parameter(0), 889 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm))); 890 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); 891 Stream s = m.Build(); 892 ASSERT_LE(1U, s.size()); 893 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 894 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 895 ASSERT_EQ(3U, s[0]->InputCount()); 896 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 897 EXPECT_EQ(2U, s[0]->OutputCount()); 898 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 899 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 900 } 901 } 902 TRACED_FOREACH(Shift, shift, kShifts) { 903 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 904 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 905 MachineType::Int32()); 906 Node* n = (m.*odpi.constructor)( 907 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)), 908 m.Parameter(1)); 909 m.Return(m.Word32Equal(m.Projection(0, n), m.Projection(1, n))); 910 Stream s = m.Build(); 911 ASSERT_LE(1U, s.size()); 912 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); 913 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 914 ASSERT_EQ(3U, s[0]->InputCount()); 915 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 916 EXPECT_EQ(2U, s[0]->OutputCount()); 917 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 918 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 919 } 920 } 921} 922 923 924TEST_P(InstructionSelectorODPITest, BranchWithParameters) { 925 const ODPI odpi = GetParam(); 926 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 927 MachineType::Int32()); 928 RawMachineLabel a, b; 929 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); 930 m.Branch(m.Projection(1, n), &a, &b); 931 m.Bind(&a); 932 m.Return(m.Int32Constant(0)); 933 m.Bind(&b); 934 m.Return(m.Projection(0, n)); 935 Stream s = m.Build(); 936 ASSERT_EQ(1U, s.size()); 937 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 938 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 939 EXPECT_EQ(4U, s[0]->InputCount()); 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 946TEST_P(InstructionSelectorODPITest, BranchWithImmediate) { 947 const ODPI odpi = GetParam(); 948 TRACED_FOREACH(int32_t, imm, kImmediates) { 949 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 950 RawMachineLabel a, b; 951 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Int32Constant(imm)); 952 m.Branch(m.Projection(1, n), &a, &b); 953 m.Bind(&a); 954 m.Return(m.Int32Constant(0)); 955 m.Bind(&b); 956 m.Return(m.Projection(0, n)); 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_I, s[0]->addressing_mode()); 961 ASSERT_EQ(4U, s[0]->InputCount()); 962 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 963 EXPECT_EQ(1U, s[0]->OutputCount()); 964 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 965 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 966 } 967 TRACED_FOREACH(int32_t, imm, kImmediates) { 968 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 969 RawMachineLabel a, b; 970 Node* n = (m.*odpi.constructor)(m.Int32Constant(imm), m.Parameter(0)); 971 m.Branch(m.Projection(1, n), &a, &b); 972 m.Bind(&a); 973 m.Return(m.Int32Constant(0)); 974 m.Bind(&b); 975 m.Return(m.Projection(0, n)); 976 Stream s = m.Build(); 977 ASSERT_EQ(1U, s.size()); 978 EXPECT_EQ(odpi.reverse_arch_opcode, s[0]->arch_opcode()); 979 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 980 ASSERT_EQ(4U, s[0]->InputCount()); 981 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 982 EXPECT_EQ(1U, s[0]->OutputCount()); 983 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 984 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 985 } 986} 987 988 989TEST_P(InstructionSelectorODPITest, BranchIfZeroWithParameters) { 990 const ODPI odpi = GetParam(); 991 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 992 MachineType::Int32()); 993 RawMachineLabel a, b; 994 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); 995 m.Branch(m.Word32Equal(m.Projection(1, n), m.Int32Constant(0)), &a, &b); 996 m.Bind(&a); 997 m.Return(m.Projection(0, n)); 998 m.Bind(&b); 999 m.Return(m.Int32Constant(0)); 1000 Stream s = m.Build(); 1001 ASSERT_EQ(1U, s.size()); 1002 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 1003 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 1004 EXPECT_EQ(4U, s[0]->InputCount()); 1005 EXPECT_EQ(1U, s[0]->OutputCount()); 1006 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 1007 EXPECT_EQ(kNotOverflow, s[0]->flags_condition()); 1008} 1009 1010 1011TEST_P(InstructionSelectorODPITest, BranchIfNotZeroWithParameters) { 1012 const ODPI odpi = GetParam(); 1013 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1014 MachineType::Int32()); 1015 RawMachineLabel a, b; 1016 Node* n = (m.*odpi.constructor)(m.Parameter(0), m.Parameter(1)); 1017 m.Branch(m.Word32NotEqual(m.Projection(1, n), m.Int32Constant(0)), &a, &b); 1018 m.Bind(&a); 1019 m.Return(m.Projection(0, n)); 1020 m.Bind(&b); 1021 m.Return(m.Int32Constant(0)); 1022 Stream s = m.Build(); 1023 ASSERT_EQ(1U, s.size()); 1024 EXPECT_EQ(odpi.arch_opcode, s[0]->arch_opcode()); 1025 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 1026 EXPECT_EQ(4U, s[0]->InputCount()); 1027 EXPECT_EQ(1U, s[0]->OutputCount()); 1028 EXPECT_EQ(kFlags_branch, s[0]->flags_mode()); 1029 EXPECT_EQ(kOverflow, s[0]->flags_condition()); 1030} 1031 1032 1033INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorODPITest, 1034 ::testing::ValuesIn(kODPIs)); 1035 1036 1037// ----------------------------------------------------------------------------- 1038// Shifts. 1039 1040 1041typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest; 1042 1043 1044TEST_P(InstructionSelectorShiftTest, Parameters) { 1045 const Shift shift = GetParam(); 1046 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1047 MachineType::Int32()); 1048 m.Return((m.*shift.constructor)(m.Parameter(0), m.Parameter(1))); 1049 Stream s = m.Build(); 1050 ASSERT_EQ(1U, s.size()); 1051 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); 1052 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 1053 EXPECT_EQ(2U, s[0]->InputCount()); 1054 EXPECT_EQ(1U, s[0]->OutputCount()); 1055} 1056 1057 1058TEST_P(InstructionSelectorShiftTest, Immediate) { 1059 const Shift shift = GetParam(); 1060 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 1061 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 1062 m.Return((m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm))); 1063 Stream s = m.Build(); 1064 ASSERT_EQ(1U, s.size()); 1065 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); 1066 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 1067 ASSERT_EQ(2U, s[0]->InputCount()); 1068 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 1069 EXPECT_EQ(1U, s[0]->OutputCount()); 1070 } 1071} 1072 1073 1074TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameter) { 1075 const Shift shift = GetParam(); 1076 { 1077 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1078 MachineType::Int32(), MachineType::Int32()); 1079 m.Return( 1080 m.Word32Equal(m.Parameter(0), 1081 (m.*shift.constructor)(m.Parameter(1), m.Parameter(2)))); 1082 Stream s = m.Build(); 1083 ASSERT_EQ(1U, s.size()); 1084 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 1085 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 1086 EXPECT_EQ(3U, s[0]->InputCount()); 1087 EXPECT_EQ(1U, s[0]->OutputCount()); 1088 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1089 EXPECT_EQ(kEqual, s[0]->flags_condition()); 1090 } 1091 { 1092 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1093 MachineType::Int32(), MachineType::Int32()); 1094 m.Return( 1095 m.Word32Equal((m.*shift.constructor)(m.Parameter(1), m.Parameter(2)), 1096 m.Parameter(0))); 1097 Stream s = m.Build(); 1098 ASSERT_EQ(1U, s.size()); 1099 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 1100 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 1101 EXPECT_EQ(3U, s[0]->InputCount()); 1102 EXPECT_EQ(1U, s[0]->OutputCount()); 1103 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1104 EXPECT_EQ(kEqual, s[0]->flags_condition()); 1105 } 1106} 1107 1108 1109TEST_P(InstructionSelectorShiftTest, Word32EqualWithParameterAndImmediate) { 1110 const Shift shift = GetParam(); 1111 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 1112 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1113 MachineType::Int32()); 1114 m.Return(m.Word32Equal( 1115 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)), 1116 m.Parameter(0))); 1117 Stream s = m.Build(); 1118 ASSERT_EQ(1U, s.size()); 1119 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 1120 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 1121 ASSERT_EQ(3U, s[0]->InputCount()); 1122 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 1123 EXPECT_EQ(1U, s[0]->OutputCount()); 1124 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1125 EXPECT_EQ(kEqual, s[0]->flags_condition()); 1126 } 1127 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 1128 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1129 MachineType::Int32()); 1130 m.Return(m.Word32Equal( 1131 m.Parameter(0), 1132 (m.*shift.constructor)(m.Parameter(1), m.Int32Constant(imm)))); 1133 Stream s = m.Build(); 1134 ASSERT_EQ(1U, s.size()); 1135 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 1136 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 1137 ASSERT_EQ(3U, s[0]->InputCount()); 1138 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 1139 EXPECT_EQ(1U, s[0]->OutputCount()); 1140 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1141 EXPECT_EQ(kEqual, s[0]->flags_condition()); 1142 } 1143} 1144 1145 1146TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithParameters) { 1147 const Shift shift = GetParam(); 1148 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1149 MachineType::Int32()); 1150 m.Return( 1151 m.Word32Equal(m.Int32Constant(0), 1152 (m.*shift.constructor)(m.Parameter(0), m.Parameter(1)))); 1153 Stream s = m.Build(); 1154 ASSERT_EQ(1U, s.size()); 1155 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); 1156 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 1157 EXPECT_EQ(2U, s[0]->InputCount()); 1158 EXPECT_EQ(2U, s[0]->OutputCount()); 1159 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1160 EXPECT_EQ(kEqual, s[0]->flags_condition()); 1161} 1162 1163 1164TEST_P(InstructionSelectorShiftTest, Word32EqualToZeroWithImmediate) { 1165 const Shift shift = GetParam(); 1166 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 1167 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1168 MachineType::Int32()); 1169 m.Return(m.Word32Equal( 1170 m.Int32Constant(0), 1171 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)))); 1172 Stream s = m.Build(); 1173 ASSERT_EQ(1U, s.size()); 1174 EXPECT_EQ(kArmMov, s[0]->arch_opcode()); 1175 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 1176 ASSERT_EQ(2U, s[0]->InputCount()); 1177 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 1178 EXPECT_EQ(2U, s[0]->OutputCount()); 1179 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1180 EXPECT_EQ(kEqual, s[0]->flags_condition()); 1181 } 1182} 1183 1184 1185TEST_P(InstructionSelectorShiftTest, Word32NotWithParameters) { 1186 const Shift shift = GetParam(); 1187 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1188 MachineType::Int32()); 1189 m.Return(m.Word32Not((m.*shift.constructor)(m.Parameter(0), m.Parameter(1)))); 1190 Stream s = m.Build(); 1191 ASSERT_EQ(1U, s.size()); 1192 EXPECT_EQ(kArmMvn, s[0]->arch_opcode()); 1193 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 1194 EXPECT_EQ(2U, s[0]->InputCount()); 1195 EXPECT_EQ(1U, s[0]->OutputCount()); 1196} 1197 1198 1199TEST_P(InstructionSelectorShiftTest, Word32NotWithImmediate) { 1200 const Shift shift = GetParam(); 1201 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 1202 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 1203 m.Return(m.Word32Not( 1204 (m.*shift.constructor)(m.Parameter(0), m.Int32Constant(imm)))); 1205 Stream s = m.Build(); 1206 ASSERT_EQ(1U, s.size()); 1207 EXPECT_EQ(kArmMvn, s[0]->arch_opcode()); 1208 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 1209 ASSERT_EQ(2U, s[0]->InputCount()); 1210 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 1211 EXPECT_EQ(1U, s[0]->OutputCount()); 1212 } 1213} 1214 1215 1216TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithParameters) { 1217 const Shift shift = GetParam(); 1218 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1219 MachineType::Int32(), MachineType::Int32()); 1220 m.Return(m.Word32And(m.Parameter(0), m.Word32Not((m.*shift.constructor)( 1221 m.Parameter(1), m.Parameter(2))))); 1222 Stream s = m.Build(); 1223 ASSERT_EQ(1U, s.size()); 1224 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); 1225 EXPECT_EQ(shift.r_mode, s[0]->addressing_mode()); 1226 EXPECT_EQ(3U, s[0]->InputCount()); 1227 EXPECT_EQ(1U, s[0]->OutputCount()); 1228} 1229 1230 1231TEST_P(InstructionSelectorShiftTest, Word32AndWithWord32NotWithImmediate) { 1232 const Shift shift = GetParam(); 1233 TRACED_FORRANGE(int32_t, imm, shift.i_low, shift.i_high) { 1234 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1235 MachineType::Int32()); 1236 m.Return(m.Word32And(m.Parameter(0), 1237 m.Word32Not((m.*shift.constructor)( 1238 m.Parameter(1), m.Int32Constant(imm))))); 1239 Stream s = m.Build(); 1240 ASSERT_EQ(1U, s.size()); 1241 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); 1242 EXPECT_EQ(shift.i_mode, s[0]->addressing_mode()); 1243 ASSERT_EQ(3U, s[0]->InputCount()); 1244 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2))); 1245 EXPECT_EQ(1U, s[0]->OutputCount()); 1246 } 1247} 1248 1249 1250INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, 1251 ::testing::ValuesIn(kShifts)); 1252 1253 1254// ----------------------------------------------------------------------------- 1255// Memory access instructions. 1256 1257 1258namespace { 1259 1260struct MemoryAccess { 1261 MachineType type; 1262 ArchOpcode ldr_opcode; 1263 ArchOpcode str_opcode; 1264 bool (InstructionSelectorTest::Stream::*val_predicate)( 1265 const InstructionOperand*) const; 1266 const int32_t immediates[40]; 1267}; 1268 1269 1270std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { 1271 return os << memacc.type; 1272} 1273 1274 1275const MemoryAccess kMemoryAccesses[] = { 1276 {MachineType::Int8(), 1277 kArmLdrsb, 1278 kArmStrb, 1279 &InstructionSelectorTest::Stream::IsInteger, 1280 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, 1281 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, 1282 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, 1283 {MachineType::Uint8(), 1284 kArmLdrb, 1285 kArmStrb, 1286 &InstructionSelectorTest::Stream::IsInteger, 1287 {-4095, -3914, -3536, -3234, -3185, -3169, -1073, -990, -859, -720, -434, 1288 -127, -124, -122, -105, -91, -86, -64, -55, -53, -30, -10, -3, 0, 20, 28, 1289 39, 58, 64, 73, 75, 100, 108, 121, 686, 963, 1363, 2759, 3449, 4095}}, 1290 {MachineType::Int16(), 1291 kArmLdrsh, 1292 kArmStrh, 1293 &InstructionSelectorTest::Stream::IsInteger, 1294 {-255, -251, -232, -220, -144, -138, -130, -126, -116, -115, -102, -101, 1295 -98, -69, -59, -56, -39, -35, -23, -19, -7, 0, 22, 26, 37, 68, 83, 87, 98, 1296 102, 108, 111, 117, 171, 195, 203, 204, 245, 246, 255}}, 1297 {MachineType::Uint16(), 1298 kArmLdrh, 1299 kArmStrh, 1300 &InstructionSelectorTest::Stream::IsInteger, 1301 {-255, -230, -201, -172, -125, -119, -118, -105, -98, -79, -54, -42, -41, 1302 -32, -12, -11, -5, -4, 0, 5, 9, 25, 28, 51, 58, 60, 89, 104, 108, 109, 1303 114, 116, 120, 138, 150, 161, 166, 172, 228, 255}}, 1304 {MachineType::Int32(), 1305 kArmLdr, 1306 kArmStr, 1307 &InstructionSelectorTest::Stream::IsInteger, 1308 {-4095, -1898, -1685, -1562, -1408, -1313, -344, -128, -116, -100, -92, 1309 -80, -72, -71, -56, -25, -21, -11, -9, 0, 3, 5, 27, 28, 42, 52, 63, 88, 1310 93, 97, 125, 846, 1037, 2102, 2403, 2597, 2632, 2997, 3935, 4095}}, 1311 {MachineType::Float32(), 1312 kArmVldrF32, 1313 kArmVstrF32, 1314 &InstructionSelectorTest::Stream::IsDouble, 1315 {-1020, -928, -896, -772, -728, -680, -660, -488, -372, -112, -100, -92, 1316 -84, -80, -72, -64, -60, -56, -52, -48, -36, -32, -20, -8, -4, 0, 8, 20, 1317 24, 40, 64, 112, 204, 388, 516, 852, 856, 976, 988, 1020}}, 1318 {MachineType::Float64(), 1319 kArmVldrF64, 1320 kArmVstrF64, 1321 &InstructionSelectorTest::Stream::IsDouble, 1322 {-1020, -948, -796, -696, -612, -364, -320, -308, -128, -112, -108, -104, 1323 -96, -84, -80, -56, -48, -40, -20, 0, 24, 28, 36, 48, 64, 84, 96, 100, 1324 108, 116, 120, 140, 156, 408, 432, 444, 772, 832, 940, 1020}}}; 1325 1326} // namespace 1327 1328 1329typedef InstructionSelectorTestWithParam<MemoryAccess> 1330 InstructionSelectorMemoryAccessTest; 1331 1332 1333TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { 1334 const MemoryAccess memacc = GetParam(); 1335 StreamBuilder m(this, memacc.type, MachineType::Pointer(), 1336 MachineType::Int32()); 1337 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1))); 1338 Stream s = m.Build(); 1339 ASSERT_EQ(1U, s.size()); 1340 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode()); 1341 EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode()); 1342 EXPECT_EQ(2U, s[0]->InputCount()); 1343 ASSERT_EQ(1U, s[0]->OutputCount()); 1344 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output())); 1345} 1346 1347 1348TEST_P(InstructionSelectorMemoryAccessTest, LoadWithImmediateIndex) { 1349 const MemoryAccess memacc = GetParam(); 1350 TRACED_FOREACH(int32_t, index, memacc.immediates) { 1351 StreamBuilder m(this, memacc.type, MachineType::Pointer()); 1352 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); 1353 Stream s = m.Build(); 1354 ASSERT_EQ(1U, s.size()); 1355 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode()); 1356 EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode()); 1357 ASSERT_EQ(2U, s[0]->InputCount()); 1358 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); 1359 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); 1360 ASSERT_EQ(1U, s[0]->OutputCount()); 1361 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output())); 1362 } 1363} 1364 1365 1366TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { 1367 const MemoryAccess memacc = GetParam(); 1368 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), 1369 MachineType::Int32(), memacc.type); 1370 m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1), 1371 m.Parameter(2), kNoWriteBarrier); 1372 m.Return(m.Int32Constant(0)); 1373 Stream s = m.Build(); 1374 ASSERT_EQ(1U, s.size()); 1375 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode()); 1376 EXPECT_EQ(kMode_Offset_RR, s[0]->addressing_mode()); 1377 EXPECT_EQ(3U, s[0]->InputCount()); 1378 EXPECT_EQ(0U, s[0]->OutputCount()); 1379} 1380 1381 1382TEST_P(InstructionSelectorMemoryAccessTest, StoreWithImmediateIndex) { 1383 const MemoryAccess memacc = GetParam(); 1384 TRACED_FOREACH(int32_t, index, memacc.immediates) { 1385 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), 1386 memacc.type); 1387 m.Store(memacc.type.representation(), m.Parameter(0), 1388 m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier); 1389 m.Return(m.Int32Constant(0)); 1390 Stream s = m.Build(); 1391 ASSERT_EQ(1U, s.size()); 1392 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode()); 1393 EXPECT_EQ(kMode_Offset_RI, s[0]->addressing_mode()); 1394 ASSERT_EQ(3U, s[0]->InputCount()); 1395 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(2)->kind()); 1396 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(2))); 1397 EXPECT_EQ(0U, s[0]->OutputCount()); 1398 } 1399} 1400 1401 1402INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 1403 InstructionSelectorMemoryAccessTest, 1404 ::testing::ValuesIn(kMemoryAccesses)); 1405 1406TEST_F(InstructionSelectorMemoryAccessTest, LoadWithShiftedIndex) { 1407 TRACED_FORRANGE(int, immediate_shift, 1, 31) { 1408 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), 1409 MachineType::Int32()); 1410 Node* const index = 1411 m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift)); 1412 m.Return(m.Load(MachineType::Int32(), m.Parameter(0), index)); 1413 Stream s = m.Build(); 1414 ASSERT_EQ(1U, s.size()); 1415 EXPECT_EQ(kArmLdr, s[0]->arch_opcode()); 1416 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); 1417 EXPECT_EQ(3U, s[0]->InputCount()); 1418 EXPECT_EQ(1U, s[0]->OutputCount()); 1419 } 1420} 1421 1422TEST_F(InstructionSelectorMemoryAccessTest, StoreWithShiftedIndex) { 1423 TRACED_FORRANGE(int, immediate_shift, 1, 31) { 1424 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), 1425 MachineType::Int32(), MachineType::Int32()); 1426 Node* const index = 1427 m.Word32Shl(m.Parameter(1), m.Int32Constant(immediate_shift)); 1428 m.Store(MachineRepresentation::kWord32, m.Parameter(0), index, 1429 m.Parameter(2), kNoWriteBarrier); 1430 m.Return(m.Int32Constant(0)); 1431 Stream s = m.Build(); 1432 ASSERT_EQ(1U, s.size()); 1433 EXPECT_EQ(kArmStr, s[0]->arch_opcode()); 1434 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); 1435 EXPECT_EQ(4U, s[0]->InputCount()); 1436 EXPECT_EQ(0U, s[0]->OutputCount()); 1437 } 1438} 1439 1440// ----------------------------------------------------------------------------- 1441// Conversions. 1442 1443 1444TEST_F(InstructionSelectorTest, ChangeFloat32ToFloat64WithParameter) { 1445 StreamBuilder m(this, MachineType::Float64(), MachineType::Float32()); 1446 m.Return(m.ChangeFloat32ToFloat64(m.Parameter(0))); 1447 Stream s = m.Build(); 1448 ASSERT_EQ(1U, s.size()); 1449 EXPECT_EQ(kArmVcvtF64F32, s[0]->arch_opcode()); 1450 EXPECT_EQ(1U, s[0]->InputCount()); 1451 EXPECT_EQ(1U, s[0]->OutputCount()); 1452} 1453 1454 1455TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) { 1456 StreamBuilder m(this, MachineType::Float32(), MachineType::Float64()); 1457 m.Return(m.TruncateFloat64ToFloat32(m.Parameter(0))); 1458 Stream s = m.Build(); 1459 ASSERT_EQ(1U, s.size()); 1460 EXPECT_EQ(kArmVcvtF32F64, s[0]->arch_opcode()); 1461 EXPECT_EQ(1U, s[0]->InputCount()); 1462 EXPECT_EQ(1U, s[0]->OutputCount()); 1463} 1464 1465 1466// ----------------------------------------------------------------------------- 1467// Comparisons. 1468 1469 1470namespace { 1471 1472struct Comparison { 1473 Constructor constructor; 1474 const char* constructor_name; 1475 FlagsCondition flags_condition; 1476 FlagsCondition negated_flags_condition; 1477 FlagsCondition commuted_flags_condition; 1478}; 1479 1480 1481std::ostream& operator<<(std::ostream& os, const Comparison& cmp) { 1482 return os << cmp.constructor_name; 1483} 1484 1485 1486const Comparison kComparisons[] = { 1487 {&RawMachineAssembler::Word32Equal, "Word32Equal", kEqual, kNotEqual, 1488 kEqual}, 1489 {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kSignedLessThan, 1490 kSignedGreaterThanOrEqual, kSignedGreaterThan}, 1491 {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual", 1492 kSignedLessThanOrEqual, kSignedGreaterThan, kSignedGreaterThanOrEqual}, 1493 {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kUnsignedLessThan, 1494 kUnsignedGreaterThanOrEqual, kUnsignedGreaterThan}, 1495 {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual", 1496 kUnsignedLessThanOrEqual, kUnsignedGreaterThan, 1497 kUnsignedGreaterThanOrEqual}}; 1498 1499} // namespace 1500 1501 1502typedef InstructionSelectorTestWithParam<Comparison> 1503 InstructionSelectorComparisonTest; 1504 1505 1506TEST_P(InstructionSelectorComparisonTest, Parameters) { 1507 const Comparison& cmp = GetParam(); 1508 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1509 MachineType::Int32()); 1510 Node* const p0 = m.Parameter(0); 1511 Node* const p1 = m.Parameter(1); 1512 Node* const r = (m.*cmp.constructor)(p0, p1); 1513 m.Return(r); 1514 Stream const s = m.Build(); 1515 ASSERT_EQ(1U, s.size()); 1516 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 1517 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 1518 ASSERT_EQ(2U, s[0]->InputCount()); 1519 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1520 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 1521 ASSERT_EQ(1U, s[0]->OutputCount()); 1522 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0))); 1523 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1524 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition()); 1525} 1526 1527 1528TEST_P(InstructionSelectorComparisonTest, Word32EqualWithZero) { 1529 { 1530 const Comparison& cmp = GetParam(); 1531 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1532 MachineType::Int32()); 1533 Node* const p0 = m.Parameter(0); 1534 Node* const p1 = m.Parameter(1); 1535 Node* const r = 1536 m.Word32Equal((m.*cmp.constructor)(p0, p1), m.Int32Constant(0)); 1537 m.Return(r); 1538 Stream const s = m.Build(); 1539 ASSERT_EQ(1U, s.size()); 1540 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 1541 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 1542 ASSERT_EQ(2U, s[0]->InputCount()); 1543 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1544 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 1545 ASSERT_EQ(1U, s[0]->OutputCount()); 1546 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0))); 1547 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1548 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition()); 1549 } 1550 { 1551 const Comparison& cmp = GetParam(); 1552 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 1553 MachineType::Int32()); 1554 Node* const p0 = m.Parameter(0); 1555 Node* const p1 = m.Parameter(1); 1556 Node* const r = 1557 m.Word32Equal(m.Int32Constant(0), (m.*cmp.constructor)(p0, p1)); 1558 m.Return(r); 1559 Stream const s = m.Build(); 1560 ASSERT_EQ(1U, s.size()); 1561 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 1562 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 1563 ASSERT_EQ(2U, s[0]->InputCount()); 1564 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1565 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 1566 ASSERT_EQ(1U, s[0]->OutputCount()); 1567 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0))); 1568 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1569 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition()); 1570 } 1571} 1572 1573 1574INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 1575 InstructionSelectorComparisonTest, 1576 ::testing::ValuesIn(kComparisons)); 1577 1578 1579// ----------------------------------------------------------------------------- 1580// Floating point comparisons. 1581 1582 1583namespace { 1584 1585const Comparison kF32Comparisons[] = { 1586 {&RawMachineAssembler::Float32Equal, "Float32Equal", kEqual, kNotEqual, 1587 kEqual}, 1588 {&RawMachineAssembler::Float32LessThan, "Float32LessThan", 1589 kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan}, 1590 {&RawMachineAssembler::Float32LessThanOrEqual, "Float32LessThanOrEqual", 1591 kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered, 1592 kFloatGreaterThanOrEqual}}; 1593 1594} // namespace 1595 1596typedef InstructionSelectorTestWithParam<Comparison> 1597 InstructionSelectorF32ComparisonTest; 1598 1599 1600TEST_P(InstructionSelectorF32ComparisonTest, WithParameters) { 1601 const Comparison& cmp = GetParam(); 1602 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(), 1603 MachineType::Float32()); 1604 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))); 1605 Stream const s = m.Build(); 1606 ASSERT_EQ(1U, s.size()); 1607 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode()); 1608 ASSERT_EQ(2U, s[0]->InputCount()); 1609 ASSERT_EQ(1U, s[0]->OutputCount()); 1610 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1611 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition()); 1612} 1613 1614 1615TEST_P(InstructionSelectorF32ComparisonTest, NegatedWithParameters) { 1616 const Comparison& cmp = GetParam(); 1617 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32(), 1618 MachineType::Float32()); 1619 m.Return( 1620 m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)))); 1621 Stream const s = m.Build(); 1622 ASSERT_EQ(1U, s.size()); 1623 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode()); 1624 ASSERT_EQ(2U, s[0]->InputCount()); 1625 ASSERT_EQ(1U, s[0]->OutputCount()); 1626 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1627 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition()); 1628} 1629 1630 1631TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnRight) { 1632 const Comparison& cmp = GetParam(); 1633 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32()); 1634 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float32Constant(0.0))); 1635 Stream const s = m.Build(); 1636 ASSERT_EQ(1U, s.size()); 1637 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode()); 1638 ASSERT_EQ(2U, s[0]->InputCount()); 1639 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 1640 ASSERT_EQ(1U, s[0]->OutputCount()); 1641 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1642 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition()); 1643} 1644 1645 1646TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnLeft) { 1647 const Comparison& cmp = GetParam(); 1648 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32()); 1649 m.Return((m.*cmp.constructor)(m.Float32Constant(0.0f), m.Parameter(0))); 1650 Stream const s = m.Build(); 1651 ASSERT_EQ(1U, s.size()); 1652 EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode()); 1653 ASSERT_EQ(2U, s[0]->InputCount()); 1654 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 1655 ASSERT_EQ(1U, s[0]->OutputCount()); 1656 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1657 EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition()); 1658} 1659 1660 1661INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 1662 InstructionSelectorF32ComparisonTest, 1663 ::testing::ValuesIn(kF32Comparisons)); 1664 1665 1666namespace { 1667 1668const Comparison kF64Comparisons[] = { 1669 {&RawMachineAssembler::Float64Equal, "Float64Equal", kEqual, kNotEqual, 1670 kEqual}, 1671 {&RawMachineAssembler::Float64LessThan, "Float64LessThan", 1672 kFloatLessThan, kFloatGreaterThanOrEqualOrUnordered, kFloatGreaterThan}, 1673 {&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual", 1674 kFloatLessThanOrEqual, kFloatGreaterThanOrUnordered, 1675 kFloatGreaterThanOrEqual}}; 1676 1677} // namespace 1678 1679typedef InstructionSelectorTestWithParam<Comparison> 1680 InstructionSelectorF64ComparisonTest; 1681 1682 1683TEST_P(InstructionSelectorF64ComparisonTest, WithParameters) { 1684 const Comparison& cmp = GetParam(); 1685 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(), 1686 MachineType::Float64()); 1687 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))); 1688 Stream const s = m.Build(); 1689 ASSERT_EQ(1U, s.size()); 1690 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode()); 1691 ASSERT_EQ(2U, s[0]->InputCount()); 1692 ASSERT_EQ(1U, s[0]->OutputCount()); 1693 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1694 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition()); 1695} 1696 1697 1698TEST_P(InstructionSelectorF64ComparisonTest, NegatedWithParameters) { 1699 const Comparison& cmp = GetParam(); 1700 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64(), 1701 MachineType::Float64()); 1702 m.Return( 1703 m.Word32BinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)))); 1704 Stream const s = m.Build(); 1705 ASSERT_EQ(1U, s.size()); 1706 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode()); 1707 ASSERT_EQ(2U, s[0]->InputCount()); 1708 ASSERT_EQ(1U, s[0]->OutputCount()); 1709 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1710 EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition()); 1711} 1712 1713 1714TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnRight) { 1715 const Comparison& cmp = GetParam(); 1716 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64()); 1717 m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float64Constant(0.0))); 1718 Stream const s = m.Build(); 1719 ASSERT_EQ(1U, s.size()); 1720 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode()); 1721 ASSERT_EQ(2U, s[0]->InputCount()); 1722 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 1723 ASSERT_EQ(1U, s[0]->OutputCount()); 1724 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1725 EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition()); 1726} 1727 1728 1729TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnLeft) { 1730 const Comparison& cmp = GetParam(); 1731 StreamBuilder m(this, MachineType::Int32(), MachineType::Float64()); 1732 m.Return((m.*cmp.constructor)(m.Float64Constant(0.0), m.Parameter(0))); 1733 Stream const s = m.Build(); 1734 ASSERT_EQ(1U, s.size()); 1735 EXPECT_EQ(kArmVcmpF64, s[0]->arch_opcode()); 1736 ASSERT_EQ(2U, s[0]->InputCount()); 1737 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 1738 ASSERT_EQ(1U, s[0]->OutputCount()); 1739 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1740 EXPECT_EQ(cmp.commuted_flags_condition, s[0]->flags_condition()); 1741} 1742 1743 1744INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 1745 InstructionSelectorF64ComparisonTest, 1746 ::testing::ValuesIn(kF64Comparisons)); 1747 1748 1749// ----------------------------------------------------------------------------- 1750// Floating point arithmetic. 1751 1752 1753typedef InstructionSelectorTestWithParam<FAI> InstructionSelectorFAITest; 1754 1755 1756TEST_P(InstructionSelectorFAITest, Parameters) { 1757 const FAI& fai = GetParam(); 1758 StreamBuilder m(this, fai.machine_type, fai.machine_type, fai.machine_type); 1759 Node* const p0 = m.Parameter(0); 1760 Node* const p1 = m.Parameter(1); 1761 Node* const r = (m.*fai.constructor)(p0, p1); 1762 m.Return(r); 1763 Stream const s = m.Build(); 1764 ASSERT_EQ(1U, s.size()); 1765 EXPECT_EQ(fai.arch_opcode, s[0]->arch_opcode()); 1766 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 1767 ASSERT_EQ(2U, s[0]->InputCount()); 1768 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1769 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 1770 ASSERT_EQ(1U, s[0]->OutputCount()); 1771 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0))); 1772 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 1773} 1774 1775 1776INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFAITest, 1777 ::testing::ValuesIn(kFAIs)); 1778 1779 1780TEST_F(InstructionSelectorTest, Float32Abs) { 1781 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); 1782 Node* const p0 = m.Parameter(0); 1783 Node* const n = m.Float32Abs(p0); 1784 m.Return(n); 1785 Stream s = m.Build(); 1786 ASSERT_EQ(1U, s.size()); 1787 EXPECT_EQ(kArmVabsF32, s[0]->arch_opcode()); 1788 ASSERT_EQ(1U, s[0]->InputCount()); 1789 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1790 ASSERT_EQ(1U, s[0]->OutputCount()); 1791 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1792} 1793 1794 1795TEST_F(InstructionSelectorTest, Float64Abs) { 1796 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); 1797 Node* const p0 = m.Parameter(0); 1798 Node* const n = m.Float64Abs(p0); 1799 m.Return(n); 1800 Stream s = m.Build(); 1801 ASSERT_EQ(1U, s.size()); 1802 EXPECT_EQ(kArmVabsF64, s[0]->arch_opcode()); 1803 ASSERT_EQ(1U, s[0]->InputCount()); 1804 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1805 ASSERT_EQ(1U, s[0]->OutputCount()); 1806 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1807} 1808 1809 1810TEST_F(InstructionSelectorTest, Float32AddWithFloat32Mul) { 1811 { 1812 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(), 1813 MachineType::Float32(), MachineType::Float32()); 1814 Node* const p0 = m.Parameter(0); 1815 Node* const p1 = m.Parameter(1); 1816 Node* const p2 = m.Parameter(2); 1817 Node* const n = m.Float32Add(m.Float32Mul(p0, p1), p2); 1818 m.Return(n); 1819 Stream s = m.Build(); 1820 ASSERT_EQ(1U, s.size()); 1821 EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode()); 1822 ASSERT_EQ(3U, s[0]->InputCount()); 1823 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0))); 1824 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 1825 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2))); 1826 ASSERT_EQ(1U, s[0]->OutputCount()); 1827 EXPECT_TRUE( 1828 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); 1829 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1830 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 1831 } 1832 { 1833 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(), 1834 MachineType::Float32(), MachineType::Float32()); 1835 Node* const p0 = m.Parameter(0); 1836 Node* const p1 = m.Parameter(1); 1837 Node* const p2 = m.Parameter(2); 1838 Node* const n = m.Float32Add(p0, m.Float32Mul(p1, p2)); 1839 m.Return(n); 1840 Stream s = m.Build(); 1841 ASSERT_EQ(1U, s.size()); 1842 EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode()); 1843 ASSERT_EQ(3U, s[0]->InputCount()); 1844 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1845 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 1846 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2))); 1847 ASSERT_EQ(1U, s[0]->OutputCount()); 1848 EXPECT_TRUE( 1849 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); 1850 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1851 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 1852 } 1853} 1854 1855 1856TEST_F(InstructionSelectorTest, Float64AddWithFloat64Mul) { 1857 { 1858 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), 1859 MachineType::Float64(), MachineType::Float64()); 1860 Node* const p0 = m.Parameter(0); 1861 Node* const p1 = m.Parameter(1); 1862 Node* const p2 = m.Parameter(2); 1863 Node* const n = m.Float64Add(m.Float64Mul(p0, p1), p2); 1864 m.Return(n); 1865 Stream s = m.Build(); 1866 ASSERT_EQ(1U, s.size()); 1867 EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode()); 1868 ASSERT_EQ(3U, s[0]->InputCount()); 1869 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0))); 1870 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 1871 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2))); 1872 ASSERT_EQ(1U, s[0]->OutputCount()); 1873 EXPECT_TRUE( 1874 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); 1875 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1876 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 1877 } 1878 { 1879 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), 1880 MachineType::Float64(), MachineType::Float64()); 1881 Node* const p0 = m.Parameter(0); 1882 Node* const p1 = m.Parameter(1); 1883 Node* const p2 = m.Parameter(2); 1884 Node* const n = m.Float64Add(p0, m.Float64Mul(p1, p2)); 1885 m.Return(n); 1886 Stream s = m.Build(); 1887 ASSERT_EQ(1U, s.size()); 1888 EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode()); 1889 ASSERT_EQ(3U, s[0]->InputCount()); 1890 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1891 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 1892 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2))); 1893 ASSERT_EQ(1U, s[0]->OutputCount()); 1894 EXPECT_TRUE( 1895 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); 1896 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1897 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 1898 } 1899} 1900 1901 1902TEST_F(InstructionSelectorTest, Float32SubWithMinusZero) { 1903 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); 1904 Node* const p0 = m.Parameter(0); 1905 Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); 1906 m.Return(n); 1907 Stream s = m.Build(); 1908 ASSERT_EQ(1U, s.size()); 1909 EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode()); 1910 ASSERT_EQ(1U, s[0]->InputCount()); 1911 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1912 ASSERT_EQ(1U, s[0]->OutputCount()); 1913 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1914} 1915 1916 1917TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) { 1918 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); 1919 Node* const p0 = m.Parameter(0); 1920 Node* const n = m.Float64Sub(m.Float64Constant(-0.0), p0); 1921 m.Return(n); 1922 Stream s = m.Build(); 1923 ASSERT_EQ(1U, s.size()); 1924 EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode()); 1925 ASSERT_EQ(1U, s[0]->InputCount()); 1926 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1927 ASSERT_EQ(1U, s[0]->OutputCount()); 1928 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1929} 1930 1931 1932TEST_F(InstructionSelectorTest, Float32SubWithFloat32Mul) { 1933 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(), 1934 MachineType::Float32(), MachineType::Float32()); 1935 Node* const p0 = m.Parameter(0); 1936 Node* const p1 = m.Parameter(1); 1937 Node* const p2 = m.Parameter(2); 1938 Node* const n = m.Float32Sub(p0, m.Float32Mul(p1, p2)); 1939 m.Return(n); 1940 Stream s = m.Build(); 1941 ASSERT_EQ(1U, s.size()); 1942 EXPECT_EQ(kArmVmlsF32, s[0]->arch_opcode()); 1943 ASSERT_EQ(3U, s[0]->InputCount()); 1944 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1945 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 1946 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2))); 1947 ASSERT_EQ(1U, s[0]->OutputCount()); 1948 EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); 1949 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1950 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 1951} 1952 1953 1954TEST_F(InstructionSelectorTest, Float64SubWithFloat64Mul) { 1955 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), 1956 MachineType::Float64(), MachineType::Float64()); 1957 Node* const p0 = m.Parameter(0); 1958 Node* const p1 = m.Parameter(1); 1959 Node* const p2 = m.Parameter(2); 1960 Node* const n = m.Float64Sub(p0, m.Float64Mul(p1, p2)); 1961 m.Return(n); 1962 Stream s = m.Build(); 1963 ASSERT_EQ(1U, s.size()); 1964 EXPECT_EQ(kArmVmlsF64, s[0]->arch_opcode()); 1965 ASSERT_EQ(3U, s[0]->InputCount()); 1966 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1967 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 1968 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2))); 1969 ASSERT_EQ(1U, s[0]->OutputCount()); 1970 EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); 1971 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1972 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 1973} 1974 1975 1976TEST_F(InstructionSelectorTest, Float32Sqrt) { 1977 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); 1978 Node* const p0 = m.Parameter(0); 1979 Node* const n = m.Float32Sqrt(p0); 1980 m.Return(n); 1981 Stream s = m.Build(); 1982 ASSERT_EQ(1U, s.size()); 1983 EXPECT_EQ(kArmVsqrtF32, s[0]->arch_opcode()); 1984 ASSERT_EQ(1U, s[0]->InputCount()); 1985 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1986 ASSERT_EQ(1U, s[0]->OutputCount()); 1987 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1988 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 1989} 1990 1991 1992TEST_F(InstructionSelectorTest, Float64Sqrt) { 1993 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); 1994 Node* const p0 = m.Parameter(0); 1995 Node* const n = m.Float64Sqrt(p0); 1996 m.Return(n); 1997 Stream s = m.Build(); 1998 ASSERT_EQ(1U, s.size()); 1999 EXPECT_EQ(kArmVsqrtF64, s[0]->arch_opcode()); 2000 ASSERT_EQ(1U, s[0]->InputCount()); 2001 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 2002 ASSERT_EQ(1U, s[0]->OutputCount()); 2003 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 2004 EXPECT_EQ(kFlags_none, s[0]->flags_mode()); 2005} 2006 2007 2008// ----------------------------------------------------------------------------- 2009// Miscellaneous. 2010 2011 2012TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) { 2013 { 2014 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2015 MachineType::Int32(), MachineType::Int32()); 2016 Node* const p0 = m.Parameter(0); 2017 Node* const p1 = m.Parameter(1); 2018 Node* const p2 = m.Parameter(2); 2019 Node* const n = m.Int32Add(p0, m.Int32Mul(p1, p2)); 2020 m.Return(n); 2021 Stream s = m.Build(); 2022 ASSERT_EQ(1U, s.size()); 2023 EXPECT_EQ(kArmMla, s[0]->arch_opcode()); 2024 ASSERT_EQ(3U, s[0]->InputCount()); 2025 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2026 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1))); 2027 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2))); 2028 ASSERT_EQ(1U, s[0]->OutputCount()); 2029 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 2030 } 2031 { 2032 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2033 MachineType::Int32(), MachineType::Int32()); 2034 Node* const p0 = m.Parameter(0); 2035 Node* const p1 = m.Parameter(1); 2036 Node* const p2 = m.Parameter(2); 2037 Node* const n = m.Int32Add(m.Int32Mul(p1, p2), p0); 2038 m.Return(n); 2039 Stream s = m.Build(); 2040 ASSERT_EQ(1U, s.size()); 2041 EXPECT_EQ(kArmMla, s[0]->arch_opcode()); 2042 ASSERT_EQ(3U, s[0]->InputCount()); 2043 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2044 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1))); 2045 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2))); 2046 ASSERT_EQ(1U, s[0]->OutputCount()); 2047 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 2048 } 2049} 2050 2051 2052TEST_F(InstructionSelectorTest, Int32AddWithInt32MulHigh) { 2053 { 2054 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2055 MachineType::Int32(), MachineType::Int32()); 2056 Node* const p0 = m.Parameter(0); 2057 Node* const p1 = m.Parameter(1); 2058 Node* const p2 = m.Parameter(2); 2059 Node* const n = m.Int32Add(p0, m.Int32MulHigh(p1, p2)); 2060 m.Return(n); 2061 Stream s = m.Build(); 2062 ASSERT_EQ(1U, s.size()); 2063 EXPECT_EQ(kArmSmmla, s[0]->arch_opcode()); 2064 ASSERT_EQ(3U, s[0]->InputCount()); 2065 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2066 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1))); 2067 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2))); 2068 ASSERT_EQ(1U, s[0]->OutputCount()); 2069 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 2070 } 2071 { 2072 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2073 MachineType::Int32(), MachineType::Int32()); 2074 Node* const p0 = m.Parameter(0); 2075 Node* const p1 = m.Parameter(1); 2076 Node* const p2 = m.Parameter(2); 2077 Node* const n = m.Int32Add(m.Int32MulHigh(p1, p2), p0); 2078 m.Return(n); 2079 Stream s = m.Build(); 2080 ASSERT_EQ(1U, s.size()); 2081 EXPECT_EQ(kArmSmmla, s[0]->arch_opcode()); 2082 ASSERT_EQ(3U, s[0]->InputCount()); 2083 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2084 EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(1))); 2085 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(2))); 2086 ASSERT_EQ(1U, s[0]->OutputCount()); 2087 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 2088 } 2089} 2090 2091 2092TEST_F(InstructionSelectorTest, Int32AddWithWord32And) { 2093 { 2094 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2095 MachineType::Int32()); 2096 Node* const p0 = m.Parameter(0); 2097 Node* const p1 = m.Parameter(1); 2098 Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xff)), p1); 2099 m.Return(r); 2100 Stream s = m.Build(); 2101 ASSERT_EQ(1U, s.size()); 2102 EXPECT_EQ(kArmUxtab, s[0]->arch_opcode()); 2103 ASSERT_EQ(3U, s[0]->InputCount()); 2104 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2105 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 2106 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2))); 2107 ASSERT_EQ(1U, s[0]->OutputCount()); 2108 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2109 } 2110 { 2111 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2112 MachineType::Int32()); 2113 Node* const p0 = m.Parameter(0); 2114 Node* const p1 = m.Parameter(1); 2115 Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xff))); 2116 m.Return(r); 2117 Stream s = m.Build(); 2118 ASSERT_EQ(1U, s.size()); 2119 EXPECT_EQ(kArmUxtab, s[0]->arch_opcode()); 2120 ASSERT_EQ(3U, s[0]->InputCount()); 2121 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2122 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 2123 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2))); 2124 ASSERT_EQ(1U, s[0]->OutputCount()); 2125 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2126 } 2127 { 2128 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2129 MachineType::Int32()); 2130 Node* const p0 = m.Parameter(0); 2131 Node* const p1 = m.Parameter(1); 2132 Node* const r = m.Int32Add(m.Word32And(p0, m.Int32Constant(0xffff)), p1); 2133 m.Return(r); 2134 Stream s = m.Build(); 2135 ASSERT_EQ(1U, s.size()); 2136 EXPECT_EQ(kArmUxtah, s[0]->arch_opcode()); 2137 ASSERT_EQ(3U, s[0]->InputCount()); 2138 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2139 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 2140 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2))); 2141 ASSERT_EQ(1U, s[0]->OutputCount()); 2142 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2143 } 2144 { 2145 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2146 MachineType::Int32()); 2147 Node* const p0 = m.Parameter(0); 2148 Node* const p1 = m.Parameter(1); 2149 Node* const r = m.Int32Add(p1, m.Word32And(p0, m.Int32Constant(0xffff))); 2150 m.Return(r); 2151 Stream s = m.Build(); 2152 ASSERT_EQ(1U, s.size()); 2153 EXPECT_EQ(kArmUxtah, s[0]->arch_opcode()); 2154 ASSERT_EQ(3U, s[0]->InputCount()); 2155 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2156 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 2157 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2))); 2158 ASSERT_EQ(1U, s[0]->OutputCount()); 2159 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2160 } 2161} 2162 2163 2164TEST_F(InstructionSelectorTest, Int32AddWithWord32SarWithWord32Shl) { 2165 { 2166 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2167 MachineType::Int32()); 2168 Node* const p0 = m.Parameter(0); 2169 Node* const p1 = m.Parameter(1); 2170 Node* const r = m.Int32Add( 2171 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)), 2172 p1); 2173 m.Return(r); 2174 Stream s = m.Build(); 2175 ASSERT_EQ(1U, s.size()); 2176 EXPECT_EQ(kArmSxtab, s[0]->arch_opcode()); 2177 ASSERT_EQ(3U, s[0]->InputCount()); 2178 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2179 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 2180 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2))); 2181 ASSERT_EQ(1U, s[0]->OutputCount()); 2182 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2183 } 2184 { 2185 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2186 MachineType::Int32()); 2187 Node* const p0 = m.Parameter(0); 2188 Node* const p1 = m.Parameter(1); 2189 Node* const r = m.Int32Add( 2190 p1, 2191 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24))); 2192 m.Return(r); 2193 Stream s = m.Build(); 2194 ASSERT_EQ(1U, s.size()); 2195 EXPECT_EQ(kArmSxtab, s[0]->arch_opcode()); 2196 ASSERT_EQ(3U, s[0]->InputCount()); 2197 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2198 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 2199 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2))); 2200 ASSERT_EQ(1U, s[0]->OutputCount()); 2201 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2202 } 2203 { 2204 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2205 MachineType::Int32()); 2206 Node* const p0 = m.Parameter(0); 2207 Node* const p1 = m.Parameter(1); 2208 Node* const r = m.Int32Add( 2209 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)), 2210 p1); 2211 m.Return(r); 2212 Stream s = m.Build(); 2213 ASSERT_EQ(1U, s.size()); 2214 EXPECT_EQ(kArmSxtah, s[0]->arch_opcode()); 2215 ASSERT_EQ(3U, s[0]->InputCount()); 2216 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2217 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 2218 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2))); 2219 ASSERT_EQ(1U, s[0]->OutputCount()); 2220 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2221 } 2222 { 2223 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2224 MachineType::Int32()); 2225 Node* const p0 = m.Parameter(0); 2226 Node* const p1 = m.Parameter(1); 2227 Node* const r = m.Int32Add( 2228 p1, 2229 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16))); 2230 m.Return(r); 2231 Stream s = m.Build(); 2232 ASSERT_EQ(1U, s.size()); 2233 EXPECT_EQ(kArmSxtah, s[0]->arch_opcode()); 2234 ASSERT_EQ(3U, s[0]->InputCount()); 2235 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(0))); 2236 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); 2237 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(2))); 2238 ASSERT_EQ(1U, s[0]->OutputCount()); 2239 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2240 } 2241} 2242 2243 2244TEST_F(InstructionSelectorTest, Int32SubWithInt32Mul) { 2245 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2246 MachineType::Int32(), MachineType::Int32()); 2247 m.Return( 2248 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2)))); 2249 Stream s = m.Build(); 2250 ASSERT_EQ(2U, s.size()); 2251 EXPECT_EQ(kArmMul, s[0]->arch_opcode()); 2252 ASSERT_EQ(1U, s[0]->OutputCount()); 2253 EXPECT_EQ(kArmSub, s[1]->arch_opcode()); 2254 ASSERT_EQ(2U, s[1]->InputCount()); 2255 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(1))); 2256} 2257 2258 2259TEST_F(InstructionSelectorTest, Int32SubWithInt32MulForMLS) { 2260 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2261 MachineType::Int32(), MachineType::Int32()); 2262 m.Return( 2263 m.Int32Sub(m.Parameter(0), m.Int32Mul(m.Parameter(1), m.Parameter(2)))); 2264 Stream s = m.Build(ARMv7); 2265 ASSERT_EQ(1U, s.size()); 2266 EXPECT_EQ(kArmMls, s[0]->arch_opcode()); 2267 EXPECT_EQ(1U, s[0]->OutputCount()); 2268 EXPECT_EQ(3U, s[0]->InputCount()); 2269} 2270 2271 2272TEST_F(InstructionSelectorTest, Int32DivWithParameters) { 2273 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2274 MachineType::Int32()); 2275 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1))); 2276 Stream s = m.Build(); 2277 ASSERT_EQ(4U, s.size()); 2278 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode()); 2279 ASSERT_EQ(1U, s[0]->OutputCount()); 2280 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode()); 2281 ASSERT_EQ(1U, s[1]->OutputCount()); 2282 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); 2283 ASSERT_EQ(2U, s[2]->InputCount()); 2284 ASSERT_EQ(1U, s[2]->OutputCount()); 2285 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); 2286 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); 2287 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode()); 2288 ASSERT_EQ(1U, s[3]->InputCount()); 2289 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); 2290} 2291 2292 2293TEST_F(InstructionSelectorTest, Int32DivWithParametersForSUDIV) { 2294 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2295 MachineType::Int32()); 2296 m.Return(m.Int32Div(m.Parameter(0), m.Parameter(1))); 2297 Stream s = m.Build(SUDIV); 2298 ASSERT_EQ(1U, s.size()); 2299 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode()); 2300} 2301 2302 2303TEST_F(InstructionSelectorTest, Int32ModWithParameters) { 2304 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2305 MachineType::Int32()); 2306 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1))); 2307 Stream s = m.Build(); 2308 ASSERT_EQ(6U, s.size()); 2309 EXPECT_EQ(kArmVcvtF64S32, s[0]->arch_opcode()); 2310 ASSERT_EQ(1U, s[0]->OutputCount()); 2311 EXPECT_EQ(kArmVcvtF64S32, s[1]->arch_opcode()); 2312 ASSERT_EQ(1U, s[1]->OutputCount()); 2313 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); 2314 ASSERT_EQ(2U, s[2]->InputCount()); 2315 ASSERT_EQ(1U, s[2]->OutputCount()); 2316 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); 2317 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); 2318 EXPECT_EQ(kArmVcvtS32F64, s[3]->arch_opcode()); 2319 ASSERT_EQ(1U, s[3]->InputCount()); 2320 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); 2321 EXPECT_EQ(kArmMul, s[4]->arch_opcode()); 2322 ASSERT_EQ(1U, s[4]->OutputCount()); 2323 ASSERT_EQ(2U, s[4]->InputCount()); 2324 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0))); 2325 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1))); 2326 EXPECT_EQ(kArmSub, s[5]->arch_opcode()); 2327 ASSERT_EQ(1U, s[5]->OutputCount()); 2328 ASSERT_EQ(2U, s[5]->InputCount()); 2329 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0))); 2330 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1))); 2331} 2332 2333 2334TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIV) { 2335 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2336 MachineType::Int32()); 2337 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1))); 2338 Stream s = m.Build(SUDIV); 2339 ASSERT_EQ(3U, s.size()); 2340 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode()); 2341 ASSERT_EQ(1U, s[0]->OutputCount()); 2342 ASSERT_EQ(2U, s[0]->InputCount()); 2343 EXPECT_EQ(kArmMul, s[1]->arch_opcode()); 2344 ASSERT_EQ(1U, s[1]->OutputCount()); 2345 ASSERT_EQ(2U, s[1]->InputCount()); 2346 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); 2347 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); 2348 EXPECT_EQ(kArmSub, s[2]->arch_opcode()); 2349 ASSERT_EQ(1U, s[2]->OutputCount()); 2350 ASSERT_EQ(2U, s[2]->InputCount()); 2351 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0))); 2352 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); 2353} 2354 2355 2356TEST_F(InstructionSelectorTest, Int32ModWithParametersForSUDIVAndMLS) { 2357 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2358 MachineType::Int32()); 2359 m.Return(m.Int32Mod(m.Parameter(0), m.Parameter(1))); 2360 Stream s = m.Build(ARMv7, SUDIV); 2361 ASSERT_EQ(2U, s.size()); 2362 EXPECT_EQ(kArmSdiv, s[0]->arch_opcode()); 2363 ASSERT_EQ(1U, s[0]->OutputCount()); 2364 ASSERT_EQ(2U, s[0]->InputCount()); 2365 EXPECT_EQ(kArmMls, s[1]->arch_opcode()); 2366 ASSERT_EQ(1U, s[1]->OutputCount()); 2367 ASSERT_EQ(3U, s[1]->InputCount()); 2368 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); 2369 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); 2370 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2))); 2371} 2372 2373 2374TEST_F(InstructionSelectorTest, Int32MulWithParameters) { 2375 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2376 MachineType::Int32()); 2377 m.Return(m.Int32Mul(m.Parameter(0), m.Parameter(1))); 2378 Stream s = m.Build(); 2379 ASSERT_EQ(1U, s.size()); 2380 EXPECT_EQ(kArmMul, s[0]->arch_opcode()); 2381 EXPECT_EQ(2U, s[0]->InputCount()); 2382 EXPECT_EQ(1U, s[0]->OutputCount()); 2383} 2384 2385 2386TEST_F(InstructionSelectorTest, Int32MulWithImmediate) { 2387 // x * (2^k + 1) -> x + (x >> k) 2388 TRACED_FORRANGE(int32_t, k, 1, 30) { 2389 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2390 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) + 1))); 2391 Stream s = m.Build(); 2392 ASSERT_EQ(1U, s.size()); 2393 EXPECT_EQ(kArmAdd, s[0]->arch_opcode()); 2394 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); 2395 ASSERT_EQ(3U, s[0]->InputCount()); 2396 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); 2397 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); 2398 EXPECT_EQ(1U, s[0]->OutputCount()); 2399 } 2400 // x * (2^k - 1) -> -x + (x >> k) 2401 TRACED_FORRANGE(int32_t, k, 3, 30) { 2402 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2403 m.Return(m.Int32Mul(m.Parameter(0), m.Int32Constant((1 << k) - 1))); 2404 Stream s = m.Build(); 2405 ASSERT_EQ(1U, s.size()); 2406 EXPECT_EQ(kArmRsb, s[0]->arch_opcode()); 2407 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); 2408 ASSERT_EQ(3U, s[0]->InputCount()); 2409 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); 2410 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); 2411 EXPECT_EQ(1U, s[0]->OutputCount()); 2412 } 2413 // (2^k + 1) * x -> x + (x >> k) 2414 TRACED_FORRANGE(int32_t, k, 1, 30) { 2415 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2416 m.Return(m.Int32Mul(m.Int32Constant((1 << k) + 1), m.Parameter(0))); 2417 Stream s = m.Build(); 2418 ASSERT_EQ(1U, s.size()); 2419 EXPECT_EQ(kArmAdd, s[0]->arch_opcode()); 2420 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); 2421 ASSERT_EQ(3U, s[0]->InputCount()); 2422 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); 2423 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); 2424 EXPECT_EQ(1U, s[0]->OutputCount()); 2425 } 2426 // x * (2^k - 1) -> -x + (x >> k) 2427 TRACED_FORRANGE(int32_t, k, 3, 30) { 2428 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2429 m.Return(m.Int32Mul(m.Int32Constant((1 << k) - 1), m.Parameter(0))); 2430 Stream s = m.Build(); 2431 ASSERT_EQ(1U, s.size()); 2432 EXPECT_EQ(kArmRsb, s[0]->arch_opcode()); 2433 EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode()); 2434 ASSERT_EQ(3U, s[0]->InputCount()); 2435 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); 2436 EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(2))); 2437 EXPECT_EQ(1U, s[0]->OutputCount()); 2438 } 2439} 2440 2441 2442TEST_F(InstructionSelectorTest, Int32MulHighWithParameters) { 2443 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2444 MachineType::Int32()); 2445 Node* const p0 = m.Parameter(0); 2446 Node* const p1 = m.Parameter(1); 2447 Node* const n = m.Int32MulHigh(p0, p1); 2448 m.Return(n); 2449 Stream s = m.Build(); 2450 ASSERT_EQ(1U, s.size()); 2451 EXPECT_EQ(kArmSmmul, s[0]->arch_opcode()); 2452 ASSERT_EQ(2U, s[0]->InputCount()); 2453 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 2454 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 2455 ASSERT_EQ(1U, s[0]->OutputCount()); 2456 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 2457} 2458 2459 2460TEST_F(InstructionSelectorTest, Uint32MulHighWithParameters) { 2461 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32(), 2462 MachineType::Uint32()); 2463 Node* const p0 = m.Parameter(0); 2464 Node* const p1 = m.Parameter(1); 2465 Node* const n = m.Uint32MulHigh(p0, p1); 2466 m.Return(n); 2467 Stream s = m.Build(); 2468 ASSERT_EQ(1U, s.size()); 2469 EXPECT_EQ(kArmUmull, s[0]->arch_opcode()); 2470 ASSERT_EQ(2U, s[0]->InputCount()); 2471 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 2472 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 2473 ASSERT_EQ(2U, s[0]->OutputCount()); 2474 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->OutputAt(1))); 2475} 2476 2477 2478TEST_F(InstructionSelectorTest, Uint32DivWithParameters) { 2479 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2480 MachineType::Int32()); 2481 m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1))); 2482 Stream s = m.Build(); 2483 ASSERT_EQ(4U, s.size()); 2484 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode()); 2485 ASSERT_EQ(1U, s[0]->OutputCount()); 2486 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode()); 2487 ASSERT_EQ(1U, s[1]->OutputCount()); 2488 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); 2489 ASSERT_EQ(2U, s[2]->InputCount()); 2490 ASSERT_EQ(1U, s[2]->OutputCount()); 2491 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); 2492 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); 2493 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode()); 2494 ASSERT_EQ(1U, s[3]->InputCount()); 2495 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); 2496} 2497 2498 2499TEST_F(InstructionSelectorTest, Uint32DivWithParametersForSUDIV) { 2500 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2501 MachineType::Int32()); 2502 m.Return(m.Uint32Div(m.Parameter(0), m.Parameter(1))); 2503 Stream s = m.Build(SUDIV); 2504 ASSERT_EQ(1U, s.size()); 2505 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode()); 2506} 2507 2508 2509TEST_F(InstructionSelectorTest, Uint32ModWithParameters) { 2510 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2511 MachineType::Int32()); 2512 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1))); 2513 Stream s = m.Build(); 2514 ASSERT_EQ(6U, s.size()); 2515 EXPECT_EQ(kArmVcvtF64U32, s[0]->arch_opcode()); 2516 ASSERT_EQ(1U, s[0]->OutputCount()); 2517 EXPECT_EQ(kArmVcvtF64U32, s[1]->arch_opcode()); 2518 ASSERT_EQ(1U, s[1]->OutputCount()); 2519 EXPECT_EQ(kArmVdivF64, s[2]->arch_opcode()); 2520 ASSERT_EQ(2U, s[2]->InputCount()); 2521 ASSERT_EQ(1U, s[2]->OutputCount()); 2522 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[2]->InputAt(0))); 2523 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); 2524 EXPECT_EQ(kArmVcvtU32F64, s[3]->arch_opcode()); 2525 ASSERT_EQ(1U, s[3]->InputCount()); 2526 EXPECT_EQ(s.ToVreg(s[2]->Output()), s.ToVreg(s[3]->InputAt(0))); 2527 EXPECT_EQ(kArmMul, s[4]->arch_opcode()); 2528 ASSERT_EQ(1U, s[4]->OutputCount()); 2529 ASSERT_EQ(2U, s[4]->InputCount()); 2530 EXPECT_EQ(s.ToVreg(s[3]->Output()), s.ToVreg(s[4]->InputAt(0))); 2531 EXPECT_EQ(s.ToVreg(s[1]->InputAt(0)), s.ToVreg(s[4]->InputAt(1))); 2532 EXPECT_EQ(kArmSub, s[5]->arch_opcode()); 2533 ASSERT_EQ(1U, s[5]->OutputCount()); 2534 ASSERT_EQ(2U, s[5]->InputCount()); 2535 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[5]->InputAt(0))); 2536 EXPECT_EQ(s.ToVreg(s[4]->Output()), s.ToVreg(s[5]->InputAt(1))); 2537} 2538 2539 2540TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIV) { 2541 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2542 MachineType::Int32()); 2543 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1))); 2544 Stream s = m.Build(SUDIV); 2545 ASSERT_EQ(3U, s.size()); 2546 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode()); 2547 ASSERT_EQ(1U, s[0]->OutputCount()); 2548 ASSERT_EQ(2U, s[0]->InputCount()); 2549 EXPECT_EQ(kArmMul, s[1]->arch_opcode()); 2550 ASSERT_EQ(1U, s[1]->OutputCount()); 2551 ASSERT_EQ(2U, s[1]->InputCount()); 2552 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); 2553 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); 2554 EXPECT_EQ(kArmSub, s[2]->arch_opcode()); 2555 ASSERT_EQ(1U, s[2]->OutputCount()); 2556 ASSERT_EQ(2U, s[2]->InputCount()); 2557 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[2]->InputAt(0))); 2558 EXPECT_EQ(s.ToVreg(s[1]->Output()), s.ToVreg(s[2]->InputAt(1))); 2559} 2560 2561 2562TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIVAndMLS) { 2563 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2564 MachineType::Int32()); 2565 m.Return(m.Uint32Mod(m.Parameter(0), m.Parameter(1))); 2566 Stream s = m.Build(ARMv7, SUDIV); 2567 ASSERT_EQ(2U, s.size()); 2568 EXPECT_EQ(kArmUdiv, s[0]->arch_opcode()); 2569 ASSERT_EQ(1U, s[0]->OutputCount()); 2570 ASSERT_EQ(2U, s[0]->InputCount()); 2571 EXPECT_EQ(kArmMls, s[1]->arch_opcode()); 2572 ASSERT_EQ(1U, s[1]->OutputCount()); 2573 ASSERT_EQ(3U, s[1]->InputCount()); 2574 EXPECT_EQ(s.ToVreg(s[0]->Output()), s.ToVreg(s[1]->InputAt(0))); 2575 EXPECT_EQ(s.ToVreg(s[0]->InputAt(1)), s.ToVreg(s[1]->InputAt(1))); 2576 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[1]->InputAt(2))); 2577} 2578 2579 2580TEST_F(InstructionSelectorTest, Word32ShlWord32SarForSbfx) { 2581 TRACED_FORRANGE(int32_t, shl, 1, 31) { 2582 TRACED_FORRANGE(int32_t, sar, shl, 31) { 2583 if ((shl == sar) && (sar == 16)) continue; // Sxth. 2584 if ((shl == sar) && (sar == 24)) continue; // Sxtb. 2585 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2586 m.Return(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(shl)), 2587 m.Int32Constant(sar))); 2588 Stream s = m.Build(ARMv7); 2589 ASSERT_EQ(1U, s.size()); 2590 EXPECT_EQ(kArmSbfx, s[0]->arch_opcode()); 2591 ASSERT_EQ(3U, s[0]->InputCount()); 2592 EXPECT_EQ(sar - shl, s.ToInt32(s[0]->InputAt(1))); 2593 EXPECT_EQ(32 - sar, s.ToInt32(s[0]->InputAt(2))); 2594 } 2595 } 2596} 2597 2598 2599TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) { 2600 TRACED_FORRANGE(int32_t, width, 9, 23) { 2601 if (width == 16) continue; // Uxth. 2602 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2603 m.Return(m.Word32And(m.Parameter(0), 2604 m.Int32Constant(0xffffffffu >> (32 - width)))); 2605 Stream s = m.Build(ARMv7); 2606 ASSERT_EQ(1U, s.size()); 2607 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); 2608 ASSERT_EQ(3U, s[0]->InputCount()); 2609 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); 2610 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 2611 } 2612 TRACED_FORRANGE(int32_t, width, 9, 23) { 2613 if (width == 16) continue; // Uxth. 2614 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2615 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)), 2616 m.Parameter(0))); 2617 Stream s = m.Build(ARMv7); 2618 ASSERT_EQ(1U, s.size()); 2619 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); 2620 ASSERT_EQ(3U, s[0]->InputCount()); 2621 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); 2622 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 2623 } 2624} 2625 2626 2627TEST_F(InstructionSelectorTest, Word32AndWithBfcImmediateForARMv7) { 2628 TRACED_FORRANGE(int32_t, lsb, 0, 31) { 2629 TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) { 2630 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2631 m.Return(m.Word32And( 2632 m.Parameter(0), 2633 m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)))); 2634 Stream s = m.Build(ARMv7); 2635 ASSERT_EQ(1U, s.size()); 2636 EXPECT_EQ(kArmBfc, s[0]->arch_opcode()); 2637 ASSERT_EQ(1U, s[0]->OutputCount()); 2638 EXPECT_TRUE( 2639 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); 2640 ASSERT_EQ(3U, s[0]->InputCount()); 2641 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 2642 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 2643 } 2644 } 2645 TRACED_FORRANGE(int32_t, lsb, 0, 31) { 2646 TRACED_FORRANGE(int32_t, width, 9, (24 - lsb) - 1) { 2647 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2648 m.Return( 2649 m.Word32And(m.Int32Constant(~((0xffffffffu >> (32 - width)) << lsb)), 2650 m.Parameter(0))); 2651 Stream s = m.Build(ARMv7); 2652 ASSERT_EQ(1U, s.size()); 2653 EXPECT_EQ(kArmBfc, s[0]->arch_opcode()); 2654 ASSERT_EQ(1U, s[0]->OutputCount()); 2655 EXPECT_TRUE( 2656 UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); 2657 ASSERT_EQ(3U, s[0]->InputCount()); 2658 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 2659 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 2660 } 2661 } 2662} 2663 2664 2665TEST_F(InstructionSelectorTest, Word32AndWith0xffff) { 2666 { 2667 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2668 Node* const p0 = m.Parameter(0); 2669 Node* const r = m.Word32And(p0, m.Int32Constant(0xffff)); 2670 m.Return(r); 2671 Stream s = m.Build(); 2672 ASSERT_EQ(1U, s.size()); 2673 EXPECT_EQ(kArmUxth, s[0]->arch_opcode()); 2674 ASSERT_EQ(2U, s[0]->InputCount()); 2675 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 2676 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); 2677 ASSERT_EQ(1U, s[0]->OutputCount()); 2678 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2679 } 2680 { 2681 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2682 Node* const p0 = m.Parameter(0); 2683 Node* const r = m.Word32And(m.Int32Constant(0xffff), p0); 2684 m.Return(r); 2685 Stream s = m.Build(); 2686 ASSERT_EQ(1U, s.size()); 2687 EXPECT_EQ(kArmUxth, s[0]->arch_opcode()); 2688 ASSERT_EQ(2U, s[0]->InputCount()); 2689 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 2690 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); 2691 ASSERT_EQ(1U, s[0]->OutputCount()); 2692 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2693 } 2694} 2695 2696 2697TEST_F(InstructionSelectorTest, Word32SarWithWord32Shl) { 2698 { 2699 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2700 Node* const p0 = m.Parameter(0); 2701 Node* const r = 2702 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(24)), m.Int32Constant(24)); 2703 m.Return(r); 2704 Stream s = m.Build(); 2705 ASSERT_EQ(1U, s.size()); 2706 EXPECT_EQ(kArmSxtb, s[0]->arch_opcode()); 2707 ASSERT_EQ(2U, s[0]->InputCount()); 2708 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 2709 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); 2710 ASSERT_EQ(1U, s[0]->OutputCount()); 2711 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2712 } 2713 { 2714 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2715 Node* const p0 = m.Parameter(0); 2716 Node* const r = 2717 m.Word32Sar(m.Word32Shl(p0, m.Int32Constant(16)), m.Int32Constant(16)); 2718 m.Return(r); 2719 Stream s = m.Build(); 2720 ASSERT_EQ(1U, s.size()); 2721 EXPECT_EQ(kArmSxth, s[0]->arch_opcode()); 2722 ASSERT_EQ(2U, s[0]->InputCount()); 2723 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 2724 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); 2725 ASSERT_EQ(1U, s[0]->OutputCount()); 2726 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 2727 } 2728} 2729 2730 2731TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediateForARMv7) { 2732 TRACED_FORRANGE(int32_t, lsb, 0, 31) { 2733 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { 2734 uint32_t max = 1 << lsb; 2735 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1; 2736 uint32_t jnk = rng()->NextInt(max); 2737 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; 2738 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2739 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)), 2740 m.Int32Constant(lsb))); 2741 Stream s = m.Build(ARMv7); 2742 ASSERT_EQ(1U, s.size()); 2743 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); 2744 ASSERT_EQ(3U, s[0]->InputCount()); 2745 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 2746 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 2747 } 2748 } 2749 TRACED_FORRANGE(int32_t, lsb, 0, 31) { 2750 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { 2751 uint32_t max = 1 << lsb; 2752 if (max > static_cast<uint32_t>(kMaxInt)) max -= 1; 2753 uint32_t jnk = rng()->NextInt(max); 2754 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; 2755 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2756 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)), 2757 m.Int32Constant(lsb))); 2758 Stream s = m.Build(ARMv7); 2759 ASSERT_EQ(1U, s.size()); 2760 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); 2761 ASSERT_EQ(3U, s[0]->InputCount()); 2762 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 2763 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 2764 } 2765 } 2766} 2767 2768 2769TEST_F(InstructionSelectorTest, Word32AndWithWord32Not) { 2770 { 2771 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2772 MachineType::Int32()); 2773 m.Return(m.Word32And(m.Parameter(0), m.Word32Not(m.Parameter(1)))); 2774 Stream s = m.Build(); 2775 ASSERT_EQ(1U, s.size()); 2776 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); 2777 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 2778 EXPECT_EQ(2U, s[0]->InputCount()); 2779 EXPECT_EQ(1U, s[0]->OutputCount()); 2780 } 2781 { 2782 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2783 MachineType::Int32()); 2784 m.Return(m.Word32And(m.Word32Not(m.Parameter(0)), m.Parameter(1))); 2785 Stream s = m.Build(); 2786 ASSERT_EQ(1U, s.size()); 2787 EXPECT_EQ(kArmBic, s[0]->arch_opcode()); 2788 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 2789 EXPECT_EQ(2U, s[0]->InputCount()); 2790 EXPECT_EQ(1U, s[0]->OutputCount()); 2791 } 2792} 2793 2794 2795TEST_F(InstructionSelectorTest, Word32EqualWithParameters) { 2796 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(), 2797 MachineType::Int32()); 2798 m.Return(m.Word32Equal(m.Parameter(0), m.Parameter(1))); 2799 Stream s = m.Build(); 2800 ASSERT_EQ(1U, s.size()); 2801 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 2802 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 2803 EXPECT_EQ(2U, s[0]->InputCount()); 2804 EXPECT_EQ(1U, s[0]->OutputCount()); 2805 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 2806 EXPECT_EQ(kEqual, s[0]->flags_condition()); 2807} 2808 2809 2810TEST_F(InstructionSelectorTest, Word32EqualWithImmediate) { 2811 TRACED_FOREACH(int32_t, imm, kImmediates) { 2812 if (imm == 0) continue; 2813 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2814 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(imm))); 2815 Stream s = m.Build(); 2816 ASSERT_EQ(1U, s.size()); 2817 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 2818 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 2819 ASSERT_EQ(2U, s[0]->InputCount()); 2820 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 2821 EXPECT_EQ(1U, s[0]->OutputCount()); 2822 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 2823 EXPECT_EQ(kEqual, s[0]->flags_condition()); 2824 } 2825 TRACED_FOREACH(int32_t, imm, kImmediates) { 2826 if (imm == 0) continue; 2827 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2828 m.Return(m.Word32Equal(m.Int32Constant(imm), m.Parameter(0))); 2829 Stream s = m.Build(); 2830 ASSERT_EQ(1U, s.size()); 2831 EXPECT_EQ(kArmCmp, s[0]->arch_opcode()); 2832 EXPECT_EQ(kMode_Operand2_I, s[0]->addressing_mode()); 2833 ASSERT_EQ(2U, s[0]->InputCount()); 2834 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 2835 EXPECT_EQ(1U, s[0]->OutputCount()); 2836 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 2837 EXPECT_EQ(kEqual, s[0]->flags_condition()); 2838 } 2839} 2840 2841 2842TEST_F(InstructionSelectorTest, Word32EqualWithZero) { 2843 { 2844 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2845 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0))); 2846 Stream s = m.Build(); 2847 ASSERT_EQ(1U, s.size()); 2848 EXPECT_EQ(kArmTst, s[0]->arch_opcode()); 2849 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 2850 ASSERT_EQ(2U, s[0]->InputCount()); 2851 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); 2852 EXPECT_EQ(1U, s[0]->OutputCount()); 2853 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 2854 EXPECT_EQ(kEqual, s[0]->flags_condition()); 2855 } 2856 { 2857 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2858 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0))); 2859 Stream s = m.Build(); 2860 ASSERT_EQ(1U, s.size()); 2861 EXPECT_EQ(kArmTst, s[0]->arch_opcode()); 2862 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 2863 ASSERT_EQ(2U, s[0]->InputCount()); 2864 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); 2865 EXPECT_EQ(1U, s[0]->OutputCount()); 2866 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 2867 EXPECT_EQ(kEqual, s[0]->flags_condition()); 2868 } 2869} 2870 2871 2872TEST_F(InstructionSelectorTest, Word32NotWithParameter) { 2873 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2874 m.Return(m.Word32Not(m.Parameter(0))); 2875 Stream s = m.Build(); 2876 ASSERT_EQ(1U, s.size()); 2877 EXPECT_EQ(kArmMvn, s[0]->arch_opcode()); 2878 EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode()); 2879 EXPECT_EQ(1U, s[0]->InputCount()); 2880 EXPECT_EQ(1U, s[0]->OutputCount()); 2881} 2882 2883 2884TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrWithImmediateForARMv7) { 2885 TRACED_FORRANGE(int32_t, lsb, 1, 31) { 2886 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { 2887 if (((width == 8) || (width == 16)) && 2888 ((lsb == 8) || (lsb == 16) || (lsb == 24))) 2889 continue; // Uxtb/h ror. 2890 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2891 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)), 2892 m.Int32Constant(0xffffffffu >> (32 - width)))); 2893 Stream s = m.Build(ARMv7); 2894 ASSERT_EQ(1U, s.size()); 2895 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); 2896 ASSERT_EQ(3U, s[0]->InputCount()); 2897 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 2898 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 2899 } 2900 } 2901 TRACED_FORRANGE(int32_t, lsb, 1, 31) { 2902 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { 2903 if (((width == 8) || (width == 16)) && 2904 ((lsb == 8) || (lsb == 16) || (lsb == 24))) 2905 continue; // Uxtb/h ror. 2906 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2907 m.Return(m.Word32And(m.Int32Constant(0xffffffffu >> (32 - width)), 2908 m.Word32Shr(m.Parameter(0), m.Int32Constant(lsb)))); 2909 Stream s = m.Build(ARMv7); 2910 ASSERT_EQ(1U, s.size()); 2911 EXPECT_EQ(kArmUbfx, s[0]->arch_opcode()); 2912 ASSERT_EQ(3U, s[0]->InputCount()); 2913 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 2914 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 2915 } 2916 } 2917} 2918 2919 2920TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xff) { 2921 TRACED_FORRANGE(int32_t, shr, 1, 3) { 2922 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2923 Node* const p0 = m.Parameter(0); 2924 Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)), 2925 m.Int32Constant(0xff)); 2926 m.Return(r); 2927 Stream s = m.Build(); 2928 ASSERT_EQ(1U, s.size()); 2929 EXPECT_EQ(kArmUxtb, s[0]->arch_opcode()); 2930 ASSERT_EQ(2U, s[0]->InputCount()); 2931 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1))); 2932 } 2933 TRACED_FORRANGE(int32_t, shr, 1, 3) { 2934 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2935 Node* const p0 = m.Parameter(0); 2936 Node* const r = m.Word32And(m.Int32Constant(0xff), 2937 m.Word32Shr(p0, m.Int32Constant(shr * 8))); 2938 m.Return(r); 2939 Stream s = m.Build(); 2940 ASSERT_EQ(1U, s.size()); 2941 EXPECT_EQ(kArmUxtb, s[0]->arch_opcode()); 2942 ASSERT_EQ(2U, s[0]->InputCount()); 2943 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1))); 2944 } 2945} 2946 2947 2948TEST_F(InstructionSelectorTest, Word32AndWithWord32ShrAnd0xffff) { 2949 TRACED_FORRANGE(int32_t, shr, 1, 3) { 2950 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2951 Node* const p0 = m.Parameter(0); 2952 Node* const r = m.Word32And(m.Word32Shr(p0, m.Int32Constant(shr * 8)), 2953 m.Int32Constant(0xffff)); 2954 m.Return(r); 2955 Stream s = m.Build(); 2956 ASSERT_EQ(1U, s.size()); 2957 EXPECT_EQ(kArmUxth, s[0]->arch_opcode()); 2958 ASSERT_EQ(2U, s[0]->InputCount()); 2959 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1))); 2960 } 2961 TRACED_FORRANGE(int32_t, shr, 1, 3) { 2962 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 2963 Node* const p0 = m.Parameter(0); 2964 Node* const r = m.Word32And(m.Int32Constant(0xffff), 2965 m.Word32Shr(p0, m.Int32Constant(shr * 8))); 2966 m.Return(r); 2967 Stream s = m.Build(); 2968 ASSERT_EQ(1U, s.size()); 2969 EXPECT_EQ(kArmUxth, s[0]->arch_opcode()); 2970 ASSERT_EQ(2U, s[0]->InputCount()); 2971 EXPECT_EQ(shr * 8, s.ToInt32(s[0]->InputAt(1))); 2972 } 2973} 2974 2975 2976TEST_F(InstructionSelectorTest, Word32Clz) { 2977 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32()); 2978 Node* const p0 = m.Parameter(0); 2979 Node* const n = m.Word32Clz(p0); 2980 m.Return(n); 2981 Stream s = m.Build(); 2982 ASSERT_EQ(1U, s.size()); 2983 EXPECT_EQ(kArmClz, s[0]->arch_opcode()); 2984 ASSERT_EQ(1U, s[0]->InputCount()); 2985 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 2986 ASSERT_EQ(1U, s[0]->OutputCount()); 2987 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 2988} 2989 2990TEST_F(InstructionSelectorTest, Float32Max) { 2991 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(), 2992 MachineType::Float32()); 2993 Node* const p0 = m.Parameter(0); 2994 Node* const p1 = m.Parameter(1); 2995 Node* const n = m.Float32Max(p0, p1); 2996 m.Return(n); 2997 Stream s = m.Build(ARMv8); 2998 // Float32Max is `(b < a) ? a : b`. 2999 ASSERT_EQ(1U, s.size()); 3000 EXPECT_EQ(kArmFloat32Max, s[0]->arch_opcode()); 3001 ASSERT_EQ(2U, s[0]->InputCount()); 3002 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 3003 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 3004 ASSERT_EQ(1U, s[0]->OutputCount()); 3005 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 3006} 3007 3008TEST_F(InstructionSelectorTest, Float32Min) { 3009 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(), 3010 MachineType::Float32()); 3011 Node* const p0 = m.Parameter(0); 3012 Node* const p1 = m.Parameter(1); 3013 Node* const n = m.Float32Min(p0, p1); 3014 m.Return(n); 3015 Stream s = m.Build(ARMv8); 3016 // Float32Min is `(a < b) ? a : b`. 3017 ASSERT_EQ(1U, s.size()); 3018 EXPECT_EQ(kArmFloat32Min, s[0]->arch_opcode()); 3019 ASSERT_EQ(2U, s[0]->InputCount()); 3020 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 3021 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 3022 ASSERT_EQ(1U, s[0]->OutputCount()); 3023 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 3024} 3025 3026TEST_F(InstructionSelectorTest, Float64Max) { 3027 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), 3028 MachineType::Float64()); 3029 Node* const p0 = m.Parameter(0); 3030 Node* const p1 = m.Parameter(1); 3031 Node* const n = m.Float64Max(p0, p1); 3032 m.Return(n); 3033 Stream s = m.Build(ARMv8); 3034 // Float64Max is `(b < a) ? a : b`. 3035 ASSERT_EQ(1U, s.size()); 3036 EXPECT_EQ(kArmFloat64Max, s[0]->arch_opcode()); 3037 ASSERT_EQ(2U, s[0]->InputCount()); 3038 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 3039 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 3040 ASSERT_EQ(1U, s[0]->OutputCount()); 3041 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 3042} 3043 3044TEST_F(InstructionSelectorTest, Float64Min) { 3045 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), 3046 MachineType::Float64()); 3047 Node* const p0 = m.Parameter(0); 3048 Node* const p1 = m.Parameter(1); 3049 Node* const n = m.Float64Min(p0, p1); 3050 m.Return(n); 3051 Stream s = m.Build(ARMv8); 3052 // Float64Min is `(a < b) ? a : b`. 3053 ASSERT_EQ(1U, s.size()); 3054 EXPECT_EQ(kArmFloat64Min, s[0]->arch_opcode()); 3055 ASSERT_EQ(2U, s[0]->InputCount()); 3056 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 3057 EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); 3058 ASSERT_EQ(1U, s[0]->OutputCount()); 3059 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 3060} 3061 3062TEST_F(InstructionSelectorTest, Float32Neg) { 3063 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); 3064 Node* const p0 = m.Parameter(0); 3065 // Don't use m.Float32Neg() as that generates an explicit sub. 3066 Node* const n = m.AddNode(m.machine()->Float32Neg().op(), m.Parameter(0)); 3067 m.Return(n); 3068 Stream s = m.Build(); 3069 ASSERT_EQ(1U, s.size()); 3070 EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode()); 3071 ASSERT_EQ(1U, s[0]->InputCount()); 3072 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 3073 ASSERT_EQ(1U, s[0]->OutputCount()); 3074 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 3075} 3076 3077TEST_F(InstructionSelectorTest, Float64Neg) { 3078 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); 3079 Node* const p0 = m.Parameter(0); 3080 // Don't use m.Float64Neg() as that generates an explicit sub. 3081 Node* const n = m.AddNode(m.machine()->Float64Neg().op(), m.Parameter(0)); 3082 m.Return(n); 3083 Stream s = m.Build(); 3084 ASSERT_EQ(1U, s.size()); 3085 EXPECT_EQ(kArmVnegF64, s[0]->arch_opcode()); 3086 ASSERT_EQ(1U, s[0]->InputCount()); 3087 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 3088 ASSERT_EQ(1U, s[0]->OutputCount()); 3089 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 3090} 3091 3092} // namespace compiler 3093} // namespace internal 3094} // namespace v8 3095