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 "test/unittests/compiler/instruction-selector-unittest.h" 6 7namespace v8 { 8namespace internal { 9namespace compiler { 10 11namespace { 12 13template <typename T> 14struct MachInst { 15 T constructor; 16 const char* constructor_name; 17 ArchOpcode arch_opcode; 18 MachineType machine_type; 19}; 20 21template <typename T> 22std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) { 23 return os << mi.constructor_name; 24} 25 26typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; 27typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; 28 29// To avoid duplicated code IntCmp helper structure 30// is created. It contains MachInst2 with two nodes and expected_size 31// because different cmp instructions have different size. 32struct IntCmp { 33 MachInst2 mi; 34 uint32_t expected_size; 35}; 36 37struct FPCmp { 38 MachInst2 mi; 39 FlagsCondition cond; 40}; 41 42const FPCmp kFPCmpInstructions[] = { 43 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMipsCmpD, 44 MachineType::Float64()}, 45 kEqual}, 46 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMipsCmpD, 47 MachineType::Float64()}, 48 kUnsignedLessThan}, 49 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual", 50 kMipsCmpD, MachineType::Float64()}, 51 kUnsignedLessThanOrEqual}, 52 {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan", kMipsCmpD, 53 MachineType::Float64()}, 54 kUnsignedLessThan}, 55 {{&RawMachineAssembler::Float64GreaterThanOrEqual, 56 "Float64GreaterThanOrEqual", kMipsCmpD, MachineType::Float64()}, 57 kUnsignedLessThanOrEqual}}; 58 59struct Conversion { 60 // The machine_type field in MachInst1 represents the destination type. 61 MachInst1 mi; 62 MachineType src_machine_type; 63}; 64 65 66// ---------------------------------------------------------------------------- 67// Logical instructions. 68// ---------------------------------------------------------------------------- 69 70 71const MachInst2 kLogicalInstructions[] = { 72 {&RawMachineAssembler::WordAnd, "WordAnd", kMipsAnd, MachineType::Int16()}, 73 {&RawMachineAssembler::WordOr, "WordOr", kMipsOr, MachineType::Int16()}, 74 {&RawMachineAssembler::WordXor, "WordXor", kMipsXor, MachineType::Int16()}, 75 {&RawMachineAssembler::Word32And, "Word32And", kMipsAnd, 76 MachineType::Int32()}, 77 {&RawMachineAssembler::Word32Or, "Word32Or", kMipsOr, MachineType::Int32()}, 78 {&RawMachineAssembler::Word32Xor, "Word32Xor", kMipsXor, 79 MachineType::Int32()}}; 80 81 82// ---------------------------------------------------------------------------- 83// Shift instructions. 84// ---------------------------------------------------------------------------- 85 86 87const MachInst2 kShiftInstructions[] = { 88 {&RawMachineAssembler::WordShl, "WordShl", kMipsShl, MachineType::Int16()}, 89 {&RawMachineAssembler::WordShr, "WordShr", kMipsShr, MachineType::Int16()}, 90 {&RawMachineAssembler::WordSar, "WordSar", kMipsSar, MachineType::Int16()}, 91 {&RawMachineAssembler::WordRor, "WordRor", kMipsRor, MachineType::Int16()}, 92 {&RawMachineAssembler::Word32Shl, "Word32Shl", kMipsShl, 93 MachineType::Int32()}, 94 {&RawMachineAssembler::Word32Shr, "Word32Shr", kMipsShr, 95 MachineType::Int32()}, 96 {&RawMachineAssembler::Word32Sar, "Word32Sar", kMipsSar, 97 MachineType::Int32()}, 98 {&RawMachineAssembler::Word32Ror, "Word32Ror", kMipsRor, 99 MachineType::Int32()}}; 100 101 102// ---------------------------------------------------------------------------- 103// MUL/DIV instructions. 104// ---------------------------------------------------------------------------- 105 106 107const MachInst2 kMulDivInstructions[] = { 108 {&RawMachineAssembler::Int32Mul, "Int32Mul", kMipsMul, 109 MachineType::Int32()}, 110 {&RawMachineAssembler::Int32Div, "Int32Div", kMipsDiv, 111 MachineType::Int32()}, 112 {&RawMachineAssembler::Uint32Div, "Uint32Div", kMipsDivU, 113 MachineType::Uint32()}, 114 {&RawMachineAssembler::Float64Mul, "Float64Mul", kMipsMulD, 115 MachineType::Float64()}, 116 {&RawMachineAssembler::Float64Div, "Float64Div", kMipsDivD, 117 MachineType::Float64()}}; 118 119 120// ---------------------------------------------------------------------------- 121// MOD instructions. 122// ---------------------------------------------------------------------------- 123 124 125const MachInst2 kModInstructions[] = { 126 {&RawMachineAssembler::Int32Mod, "Int32Mod", kMipsMod, 127 MachineType::Int32()}, 128 {&RawMachineAssembler::Uint32Mod, "Int32UMod", kMipsModU, 129 MachineType::Int32()}, 130 {&RawMachineAssembler::Float64Mod, "Float64Mod", kMipsModD, 131 MachineType::Float64()}}; 132 133 134// ---------------------------------------------------------------------------- 135// Arithmetic FPU instructions. 136// ---------------------------------------------------------------------------- 137 138 139const MachInst2 kFPArithInstructions[] = { 140 {&RawMachineAssembler::Float64Add, "Float64Add", kMipsAddD, 141 MachineType::Float64()}, 142 {&RawMachineAssembler::Float64Sub, "Float64Sub", kMipsSubD, 143 MachineType::Float64()}}; 144 145 146// ---------------------------------------------------------------------------- 147// IntArithTest instructions, two nodes. 148// ---------------------------------------------------------------------------- 149 150 151const MachInst2 kAddSubInstructions[] = { 152 {&RawMachineAssembler::Int32Add, "Int32Add", kMipsAdd, 153 MachineType::Int32()}, 154 {&RawMachineAssembler::Int32Sub, "Int32Sub", kMipsSub, 155 MachineType::Int32()}, 156 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow", 157 kMipsAddOvf, MachineType::Int32()}, 158 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow", 159 kMipsSubOvf, MachineType::Int32()}}; 160 161 162// ---------------------------------------------------------------------------- 163// IntArithTest instructions, one node. 164// ---------------------------------------------------------------------------- 165 166 167const MachInst1 kAddSubOneInstructions[] = { 168 {&RawMachineAssembler::Int32Neg, "Int32Neg", kMipsSub, 169 MachineType::Int32()}, 170 // TODO(dusmil): check this ... 171 // {&RawMachineAssembler::WordEqual , "WordEqual" , kMipsTst, 172 // MachineType::Int32()} 173}; 174 175 176// ---------------------------------------------------------------------------- 177// Arithmetic compare instructions. 178// ---------------------------------------------------------------------------- 179 180 181const IntCmp kCmpInstructions[] = { 182 {{&RawMachineAssembler::WordEqual, "WordEqual", kMipsCmp, 183 MachineType::Int16()}, 184 1U}, 185 {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMipsCmp, 186 MachineType::Int16()}, 187 1U}, 188 {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMipsCmp, 189 MachineType::Int32()}, 190 1U}, 191 {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMipsCmp, 192 MachineType::Int32()}, 193 1U}, 194 {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMipsCmp, 195 MachineType::Int32()}, 196 1U}, 197 {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual", 198 kMipsCmp, MachineType::Int32()}, 199 1U}, 200 {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMipsCmp, 201 MachineType::Int32()}, 202 1U}, 203 {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual", 204 kMipsCmp, MachineType::Int32()}, 205 1U}, 206 {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMipsCmp, 207 MachineType::Uint32()}, 208 1U}, 209 {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual", 210 kMipsCmp, MachineType::Uint32()}, 211 1U}}; 212 213 214// ---------------------------------------------------------------------------- 215// Conversion instructions. 216// ---------------------------------------------------------------------------- 217 218const Conversion kConversionInstructions[] = { 219 // Conversion instructions are related to machine_operator.h: 220 // FPU conversions: 221 // Convert representation of integers between float64 and int32/uint32. 222 // The precise rounding mode and handling of out of range inputs are *not* 223 // defined for these operators, since they are intended only for use with 224 // integers. 225 // mips instruction: cvt_d_w 226 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64", 227 kMipsCvtDW, MachineType::Float64()}, 228 MachineType::Int32()}, 229 230 // mips instruction: cvt_d_uw 231 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64", 232 kMipsCvtDUw, MachineType::Float64()}, 233 MachineType::Int32()}, 234 235 // mips instruction: trunc_w_d 236 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32", 237 kMipsTruncWD, MachineType::Float64()}, 238 MachineType::Int32()}, 239 240 // mips instruction: trunc_uw_d 241 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32", 242 kMipsTruncUwD, MachineType::Float64()}, 243 MachineType::Int32()}}; 244 245const Conversion kFloat64RoundInstructions[] = { 246 {{&RawMachineAssembler::Float64RoundUp, "Float64RoundUp", kMipsCeilWD, 247 MachineType::Int32()}, 248 MachineType::Float64()}, 249 {{&RawMachineAssembler::Float64RoundDown, "Float64RoundDown", kMipsFloorWD, 250 MachineType::Int32()}, 251 MachineType::Float64()}, 252 {{&RawMachineAssembler::Float64RoundTiesEven, "Float64RoundTiesEven", 253 kMipsRoundWD, MachineType::Int32()}, 254 MachineType::Float64()}, 255 {{&RawMachineAssembler::Float64RoundTruncate, "Float64RoundTruncate", 256 kMipsTruncWD, MachineType::Int32()}, 257 MachineType::Float64()}}; 258 259const Conversion kFloat32RoundInstructions[] = { 260 {{&RawMachineAssembler::Float32RoundUp, "Float32RoundUp", kMipsCeilWS, 261 MachineType::Int32()}, 262 MachineType::Float32()}, 263 {{&RawMachineAssembler::Float32RoundDown, "Float32RoundDown", kMipsFloorWS, 264 MachineType::Int32()}, 265 MachineType::Float32()}, 266 {{&RawMachineAssembler::Float32RoundTiesEven, "Float32RoundTiesEven", 267 kMipsRoundWS, MachineType::Int32()}, 268 MachineType::Float32()}, 269 {{&RawMachineAssembler::Float32RoundTruncate, "Float32RoundTruncate", 270 kMipsTruncWS, MachineType::Int32()}, 271 MachineType::Float32()}}; 272 273} // namespace 274 275 276typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest; 277 278 279TEST_P(InstructionSelectorFPCmpTest, Parameter) { 280 const FPCmp cmp = GetParam(); 281 StreamBuilder m(this, MachineType::Int32(), cmp.mi.machine_type, 282 cmp.mi.machine_type); 283 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); 284 Stream s = m.Build(); 285 ASSERT_EQ(1U, s.size()); 286 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); 287 EXPECT_EQ(2U, s[0]->InputCount()); 288 EXPECT_EQ(1U, s[0]->OutputCount()); 289 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 290 EXPECT_EQ(cmp.cond, s[0]->flags_condition()); 291} 292 293INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest, 294 ::testing::ValuesIn(kFPCmpInstructions)); 295 296 297// ---------------------------------------------------------------------------- 298// Arithmetic compare instructions integers. 299// ---------------------------------------------------------------------------- 300 301 302typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest; 303 304 305TEST_P(InstructionSelectorCmpTest, Parameter) { 306 const IntCmp cmp = GetParam(); 307 const MachineType type = cmp.mi.machine_type; 308 StreamBuilder m(this, type, type, type); 309 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); 310 Stream s = m.Build(); 311 ASSERT_EQ(cmp.expected_size, s.size()); 312 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); 313 EXPECT_EQ(2U, s[0]->InputCount()); 314 EXPECT_EQ(1U, s[0]->OutputCount()); 315} 316 317 318INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest, 319 ::testing::ValuesIn(kCmpInstructions)); 320 321 322// ---------------------------------------------------------------------------- 323// Shift instructions. 324// ---------------------------------------------------------------------------- 325 326 327typedef InstructionSelectorTestWithParam<MachInst2> 328 InstructionSelectorShiftTest; 329 330 331TEST_P(InstructionSelectorShiftTest, Immediate) { 332 const MachInst2 dpi = GetParam(); 333 const MachineType type = dpi.machine_type; 334 TRACED_FORRANGE(int32_t, imm, 0, 335 ((1 << ElementSizeLog2Of(type.representation())) * 8) - 1) { 336 StreamBuilder m(this, type, type); 337 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); 338 Stream s = m.Build(); 339 ASSERT_EQ(1U, s.size()); 340 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); 341 EXPECT_EQ(2U, s[0]->InputCount()); 342 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); 343 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); 344 EXPECT_EQ(1U, s[0]->OutputCount()); 345 } 346} 347 348 349INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, 350 ::testing::ValuesIn(kShiftInstructions)); 351 352 353TEST_F(InstructionSelectorTest, Word32ShrWithWord32AndWithImmediate) { 354 // The available shift operand range is `0 <= imm < 32`, but we also test 355 // that immediates outside this range are handled properly (modulo-32). 356 TRACED_FORRANGE(int32_t, shift, -32, 63) { 357 int32_t lsb = shift & 0x1f; 358 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { 359 uint32_t jnk = rng()->NextInt(); 360 jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0; 361 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; 362 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 363 m.Return(m.Word32Shr(m.Word32And(m.Parameter(0), m.Int32Constant(msk)), 364 m.Int32Constant(shift))); 365 Stream s = m.Build(); 366 ASSERT_EQ(1U, s.size()); 367 EXPECT_EQ(kMipsExt, s[0]->arch_opcode()); 368 ASSERT_EQ(3U, s[0]->InputCount()); 369 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 370 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 371 } 372 } 373 TRACED_FORRANGE(int32_t, shift, -32, 63) { 374 int32_t lsb = shift & 0x1f; 375 TRACED_FORRANGE(int32_t, width, 1, 32 - lsb) { 376 uint32_t jnk = rng()->NextInt(); 377 jnk = (lsb > 0) ? (jnk >> (32 - lsb)) : 0; 378 uint32_t msk = ((0xffffffffu >> (32 - width)) << lsb) | jnk; 379 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 380 m.Return(m.Word32Shr(m.Word32And(m.Int32Constant(msk), m.Parameter(0)), 381 m.Int32Constant(shift))); 382 Stream s = m.Build(); 383 ASSERT_EQ(1U, s.size()); 384 EXPECT_EQ(kMipsExt, s[0]->arch_opcode()); 385 ASSERT_EQ(3U, s[0]->InputCount()); 386 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 387 EXPECT_EQ(width, s.ToInt32(s[0]->InputAt(2))); 388 } 389 } 390} 391 392 393TEST_F(InstructionSelectorTest, Word32ShlWithWord32And) { 394 TRACED_FORRANGE(int32_t, shift, 0, 30) { 395 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 396 Node* const p0 = m.Parameter(0); 397 Node* const r = 398 m.Word32Shl(m.Word32And(p0, m.Int32Constant((1 << (31 - shift)) - 1)), 399 m.Int32Constant(shift + 1)); 400 m.Return(r); 401 Stream s = m.Build(); 402 ASSERT_EQ(1U, s.size()); 403 EXPECT_EQ(kMipsShl, s[0]->arch_opcode()); 404 ASSERT_EQ(2U, s[0]->InputCount()); 405 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 406 ASSERT_EQ(1U, s[0]->OutputCount()); 407 EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->Output())); 408 } 409} 410 411 412// ---------------------------------------------------------------------------- 413// Logical instructions. 414// ---------------------------------------------------------------------------- 415 416 417typedef InstructionSelectorTestWithParam<MachInst2> 418 InstructionSelectorLogicalTest; 419 420 421TEST_P(InstructionSelectorLogicalTest, Parameter) { 422 const MachInst2 dpi = GetParam(); 423 const MachineType type = dpi.machine_type; 424 StreamBuilder m(this, type, type, type); 425 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); 426 Stream s = m.Build(); 427 ASSERT_EQ(1U, s.size()); 428 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); 429 EXPECT_EQ(2U, s[0]->InputCount()); 430 EXPECT_EQ(1U, s[0]->OutputCount()); 431} 432 433 434INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, 435 ::testing::ValuesIn(kLogicalInstructions)); 436 437 438TEST_F(InstructionSelectorTest, Word32XorMinusOneWithParameter) { 439 { 440 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 441 m.Return(m.Word32Xor(m.Parameter(0), m.Int32Constant(-1))); 442 Stream s = m.Build(); 443 ASSERT_EQ(1U, s.size()); 444 EXPECT_EQ(kMipsNor, s[0]->arch_opcode()); 445 EXPECT_EQ(2U, s[0]->InputCount()); 446 EXPECT_EQ(1U, s[0]->OutputCount()); 447 } 448 { 449 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 450 m.Return(m.Word32Xor(m.Int32Constant(-1), m.Parameter(0))); 451 Stream s = m.Build(); 452 ASSERT_EQ(1U, s.size()); 453 EXPECT_EQ(kMipsNor, s[0]->arch_opcode()); 454 EXPECT_EQ(2U, s[0]->InputCount()); 455 EXPECT_EQ(1U, s[0]->OutputCount()); 456 } 457} 458 459 460TEST_F(InstructionSelectorTest, Word32XorMinusOneWithWord32Or) { 461 { 462 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 463 m.Return(m.Word32Xor(m.Word32Or(m.Parameter(0), m.Parameter(0)), 464 m.Int32Constant(-1))); 465 Stream s = m.Build(); 466 ASSERT_EQ(1U, s.size()); 467 EXPECT_EQ(kMipsNor, s[0]->arch_opcode()); 468 EXPECT_EQ(2U, s[0]->InputCount()); 469 EXPECT_EQ(1U, s[0]->OutputCount()); 470 } 471 { 472 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 473 m.Return(m.Word32Xor(m.Int32Constant(-1), 474 m.Word32Or(m.Parameter(0), m.Parameter(0)))); 475 Stream s = m.Build(); 476 ASSERT_EQ(1U, s.size()); 477 EXPECT_EQ(kMipsNor, s[0]->arch_opcode()); 478 EXPECT_EQ(2U, s[0]->InputCount()); 479 EXPECT_EQ(1U, s[0]->OutputCount()); 480 } 481} 482 483 484TEST_F(InstructionSelectorTest, Word32AndWithImmediateWithWord32Shr) { 485 // The available shift operand range is `0 <= imm < 32`, but we also test 486 // that immediates outside this range are handled properly (modulo-32). 487 TRACED_FORRANGE(int32_t, shift, -32, 63) { 488 int32_t lsb = shift & 0x1f; 489 TRACED_FORRANGE(int32_t, width, 1, 31) { 490 uint32_t msk = (1 << width) - 1; 491 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 492 m.Return(m.Word32And(m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)), 493 m.Int32Constant(msk))); 494 Stream s = m.Build(); 495 ASSERT_EQ(1U, s.size()); 496 EXPECT_EQ(kMipsExt, s[0]->arch_opcode()); 497 ASSERT_EQ(3U, s[0]->InputCount()); 498 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 499 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width; 500 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2))); 501 } 502 } 503 TRACED_FORRANGE(int32_t, shift, -32, 63) { 504 int32_t lsb = shift & 0x1f; 505 TRACED_FORRANGE(int32_t, width, 1, 31) { 506 uint32_t msk = (1 << width) - 1; 507 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 508 m.Return( 509 m.Word32And(m.Int32Constant(msk), 510 m.Word32Shr(m.Parameter(0), m.Int32Constant(shift)))); 511 Stream s = m.Build(); 512 ASSERT_EQ(1U, s.size()); 513 EXPECT_EQ(kMipsExt, s[0]->arch_opcode()); 514 ASSERT_EQ(3U, s[0]->InputCount()); 515 EXPECT_EQ(lsb, s.ToInt32(s[0]->InputAt(1))); 516 int32_t actual_width = (lsb + width > 32) ? (32 - lsb) : width; 517 EXPECT_EQ(actual_width, s.ToInt32(s[0]->InputAt(2))); 518 } 519 } 520} 521 522 523TEST_F(InstructionSelectorTest, Word32AndToClearBits) { 524 TRACED_FORRANGE(int32_t, shift, 1, 31) { 525 int32_t mask = ~((1 << shift) - 1); 526 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 527 m.Return(m.Word32And(m.Parameter(0), m.Int32Constant(mask))); 528 Stream s = m.Build(); 529 ASSERT_EQ(1U, s.size()); 530 EXPECT_EQ(kMipsIns, s[0]->arch_opcode()); 531 ASSERT_EQ(3U, s[0]->InputCount()); 532 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); 533 EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2))); 534 } 535 TRACED_FORRANGE(int32_t, shift, 1, 31) { 536 int32_t mask = ~((1 << shift) - 1); 537 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 538 m.Return(m.Word32And(m.Int32Constant(mask), m.Parameter(0))); 539 Stream s = m.Build(); 540 ASSERT_EQ(1U, s.size()); 541 EXPECT_EQ(kMipsIns, s[0]->arch_opcode()); 542 ASSERT_EQ(3U, s[0]->InputCount()); 543 EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(1))); 544 EXPECT_EQ(shift, s.ToInt32(s[0]->InputAt(2))); 545 } 546} 547 548 549// ---------------------------------------------------------------------------- 550// MUL/DIV instructions. 551// ---------------------------------------------------------------------------- 552 553 554typedef InstructionSelectorTestWithParam<MachInst2> 555 InstructionSelectorMulDivTest; 556 557 558TEST_P(InstructionSelectorMulDivTest, Parameter) { 559 const MachInst2 dpi = GetParam(); 560 const MachineType type = dpi.machine_type; 561 StreamBuilder m(this, type, type, type); 562 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); 563 Stream s = m.Build(); 564 ASSERT_EQ(1U, s.size()); 565 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); 566 EXPECT_EQ(2U, s[0]->InputCount()); 567 EXPECT_EQ(1U, s[0]->OutputCount()); 568} 569 570 571INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest, 572 ::testing::ValuesIn(kMulDivInstructions)); 573 574 575// ---------------------------------------------------------------------------- 576// MOD instructions. 577// ---------------------------------------------------------------------------- 578 579 580typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest; 581 582 583TEST_P(InstructionSelectorModTest, Parameter) { 584 const MachInst2 dpi = GetParam(); 585 const MachineType type = dpi.machine_type; 586 StreamBuilder m(this, type, type, type); 587 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); 588 Stream s = m.Build(); 589 ASSERT_EQ(1U, s.size()); 590 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); 591 EXPECT_EQ(2U, s[0]->InputCount()); 592 EXPECT_EQ(1U, s[0]->OutputCount()); 593} 594 595 596INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest, 597 ::testing::ValuesIn(kModInstructions)); 598 599 600// ---------------------------------------------------------------------------- 601// Floating point instructions. 602// ---------------------------------------------------------------------------- 603 604 605typedef InstructionSelectorTestWithParam<MachInst2> 606 InstructionSelectorFPArithTest; 607 608 609TEST_P(InstructionSelectorFPArithTest, Parameter) { 610 const MachInst2 fpa = GetParam(); 611 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type); 612 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1))); 613 Stream s = m.Build(); 614 ASSERT_EQ(1U, s.size()); 615 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode()); 616 EXPECT_EQ(2U, s[0]->InputCount()); 617 EXPECT_EQ(1U, s[0]->OutputCount()); 618} 619 620 621INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest, 622 ::testing::ValuesIn(kFPArithInstructions)); 623 624 625// ---------------------------------------------------------------------------- 626// Integer arithmetic. 627// ---------------------------------------------------------------------------- 628 629 630typedef InstructionSelectorTestWithParam<MachInst2> 631 InstructionSelectorIntArithTwoTest; 632 633 634TEST_P(InstructionSelectorIntArithTwoTest, Parameter) { 635 const MachInst2 intpa = GetParam(); 636 StreamBuilder m(this, intpa.machine_type, intpa.machine_type, 637 intpa.machine_type); 638 m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1))); 639 Stream s = m.Build(); 640 ASSERT_EQ(1U, s.size()); 641 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); 642 EXPECT_EQ(2U, s[0]->InputCount()); 643 EXPECT_EQ(1U, s[0]->OutputCount()); 644} 645 646 647INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 648 InstructionSelectorIntArithTwoTest, 649 ::testing::ValuesIn(kAddSubInstructions)); 650 651 652// ---------------------------------------------------------------------------- 653// One node. 654// ---------------------------------------------------------------------------- 655 656 657typedef InstructionSelectorTestWithParam<MachInst1> 658 InstructionSelectorIntArithOneTest; 659 660 661TEST_P(InstructionSelectorIntArithOneTest, Parameter) { 662 const MachInst1 intpa = GetParam(); 663 StreamBuilder m(this, intpa.machine_type, intpa.machine_type, 664 intpa.machine_type); 665 m.Return((m.*intpa.constructor)(m.Parameter(0))); 666 Stream s = m.Build(); 667 ASSERT_EQ(1U, s.size()); 668 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); 669 EXPECT_EQ(2U, s[0]->InputCount()); 670 EXPECT_EQ(1U, s[0]->OutputCount()); 671} 672 673 674INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 675 InstructionSelectorIntArithOneTest, 676 ::testing::ValuesIn(kAddSubOneInstructions)); 677 678 679// ---------------------------------------------------------------------------- 680// Conversions. 681// ---------------------------------------------------------------------------- 682 683 684typedef InstructionSelectorTestWithParam<Conversion> 685 InstructionSelectorConversionTest; 686 687 688TEST_P(InstructionSelectorConversionTest, Parameter) { 689 const Conversion conv = GetParam(); 690 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); 691 m.Return((m.*conv.mi.constructor)(m.Parameter(0))); 692 Stream s = m.Build(); 693 ASSERT_EQ(1U, s.size()); 694 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); 695 EXPECT_EQ(1U, s[0]->InputCount()); 696 EXPECT_EQ(1U, s[0]->OutputCount()); 697} 698 699 700INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 701 InstructionSelectorConversionTest, 702 ::testing::ValuesIn(kConversionInstructions)); 703 704 705typedef InstructionSelectorTestWithParam<Conversion> 706 CombineChangeFloat64ToInt32WithRoundFloat64; 707 708TEST_P(CombineChangeFloat64ToInt32WithRoundFloat64, Parameter) { 709 { 710 const Conversion conv = GetParam(); 711 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); 712 m.Return(m.ChangeFloat64ToInt32((m.*conv.mi.constructor)(m.Parameter(0)))); 713 Stream s = m.Build(); 714 ASSERT_EQ(1U, s.size()); 715 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); 716 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 717 ASSERT_EQ(1U, s[0]->InputCount()); 718 EXPECT_EQ(1U, s[0]->OutputCount()); 719 } 720} 721 722INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 723 CombineChangeFloat64ToInt32WithRoundFloat64, 724 ::testing::ValuesIn(kFloat64RoundInstructions)); 725 726 727typedef InstructionSelectorTestWithParam<Conversion> 728 CombineChangeFloat32ToInt32WithRoundFloat32; 729 730TEST_P(CombineChangeFloat32ToInt32WithRoundFloat32, Parameter) { 731 { 732 const Conversion conv = GetParam(); 733 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); 734 m.Return(m.ChangeFloat64ToInt32( 735 m.ChangeFloat32ToFloat64((m.*conv.mi.constructor)(m.Parameter(0))))); 736 Stream s = m.Build(); 737 ASSERT_EQ(1U, s.size()); 738 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); 739 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 740 ASSERT_EQ(1U, s[0]->InputCount()); 741 EXPECT_EQ(1U, s[0]->OutputCount()); 742 } 743} 744 745INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 746 CombineChangeFloat32ToInt32WithRoundFloat32, 747 ::testing::ValuesIn(kFloat32RoundInstructions)); 748 749 750TEST_F(InstructionSelectorTest, ChangeFloat64ToInt32OfChangeFloat32ToFloat64) { 751 { 752 StreamBuilder m(this, MachineType::Int32(), MachineType::Float32()); 753 m.Return(m.ChangeFloat64ToInt32(m.ChangeFloat32ToFloat64(m.Parameter(0)))); 754 Stream s = m.Build(); 755 ASSERT_EQ(1U, s.size()); 756 EXPECT_EQ(kMipsTruncWS, s[0]->arch_opcode()); 757 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 758 ASSERT_EQ(1U, s[0]->InputCount()); 759 EXPECT_EQ(1U, s[0]->OutputCount()); 760 } 761} 762 763 764TEST_F(InstructionSelectorTest, 765 TruncateFloat64ToFloat32OfChangeInt32ToFloat64) { 766 { 767 StreamBuilder m(this, MachineType::Float32(), MachineType::Int32()); 768 m.Return( 769 m.TruncateFloat64ToFloat32(m.ChangeInt32ToFloat64(m.Parameter(0)))); 770 Stream s = m.Build(); 771 ASSERT_EQ(1U, s.size()); 772 EXPECT_EQ(kMipsCvtSW, s[0]->arch_opcode()); 773 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 774 ASSERT_EQ(1U, s[0]->InputCount()); 775 EXPECT_EQ(1U, s[0]->OutputCount()); 776 } 777} 778 779 780// ---------------------------------------------------------------------------- 781// Loads and stores. 782// ---------------------------------------------------------------------------- 783 784namespace { 785 786struct MemoryAccess { 787 MachineType type; 788 ArchOpcode load_opcode; 789 ArchOpcode store_opcode; 790}; 791 792 793static const MemoryAccess kMemoryAccesses[] = { 794 {MachineType::Int8(), kMipsLb, kMipsSb}, 795 {MachineType::Uint8(), kMipsLbu, kMipsSb}, 796 {MachineType::Int16(), kMipsLh, kMipsSh}, 797 {MachineType::Uint16(), kMipsLhu, kMipsSh}, 798 {MachineType::Int32(), kMipsLw, kMipsSw}, 799 {MachineType::Float32(), kMipsLwc1, kMipsSwc1}, 800 {MachineType::Float64(), kMipsLdc1, kMipsSdc1}}; 801 802 803struct MemoryAccessImm { 804 MachineType type; 805 ArchOpcode load_opcode; 806 ArchOpcode store_opcode; 807 bool (InstructionSelectorTest::Stream::*val_predicate)( 808 const InstructionOperand*) const; 809 const int32_t immediates[40]; 810}; 811 812 813std::ostream& operator<<(std::ostream& os, const MemoryAccessImm& acc) { 814 return os << acc.type; 815} 816 817 818struct MemoryAccessImm1 { 819 MachineType type; 820 ArchOpcode load_opcode; 821 ArchOpcode store_opcode; 822 bool (InstructionSelectorTest::Stream::*val_predicate)( 823 const InstructionOperand*) const; 824 const int32_t immediates[5]; 825}; 826 827 828std::ostream& operator<<(std::ostream& os, const MemoryAccessImm1& acc) { 829 return os << acc.type; 830} 831 832 833// ---------------------------------------------------------------------------- 834// Loads and stores immediate values. 835// ---------------------------------------------------------------------------- 836 837 838const MemoryAccessImm kMemoryAccessesImm[] = { 839 {MachineType::Int8(), 840 kMipsLb, 841 kMipsSb, 842 &InstructionSelectorTest::Stream::IsInteger, 843 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, 844 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, 845 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, 846 {MachineType::Uint8(), 847 kMipsLbu, 848 kMipsSb, 849 &InstructionSelectorTest::Stream::IsInteger, 850 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, 851 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, 852 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, 853 {MachineType::Int16(), 854 kMipsLh, 855 kMipsSh, 856 &InstructionSelectorTest::Stream::IsInteger, 857 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, 858 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, 859 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, 860 {MachineType::Uint16(), 861 kMipsLhu, 862 kMipsSh, 863 &InstructionSelectorTest::Stream::IsInteger, 864 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, 865 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, 866 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, 867 {MachineType::Int32(), 868 kMipsLw, 869 kMipsSw, 870 &InstructionSelectorTest::Stream::IsInteger, 871 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, 872 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, 873 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, 874 {MachineType::Float32(), 875 kMipsLwc1, 876 kMipsSwc1, 877 &InstructionSelectorTest::Stream::IsDouble, 878 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, 879 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, 880 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, 881 {MachineType::Float64(), 882 kMipsLdc1, 883 kMipsSdc1, 884 &InstructionSelectorTest::Stream::IsDouble, 885 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, 886 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, 887 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}}; 888 889 890const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = { 891 {MachineType::Int8(), 892 kMipsLb, 893 kMipsSb, 894 &InstructionSelectorTest::Stream::IsInteger, 895 {-65000, -55000, 32777, 55000, 65000}}, 896 {MachineType::Int8(), 897 kMipsLbu, 898 kMipsSb, 899 &InstructionSelectorTest::Stream::IsInteger, 900 {-65000, -55000, 32777, 55000, 65000}}, 901 {MachineType::Int16(), 902 kMipsLh, 903 kMipsSh, 904 &InstructionSelectorTest::Stream::IsInteger, 905 {-65000, -55000, 32777, 55000, 65000}}, 906 {MachineType::Int16(), 907 kMipsLhu, 908 kMipsSh, 909 &InstructionSelectorTest::Stream::IsInteger, 910 {-65000, -55000, 32777, 55000, 65000}}, 911 {MachineType::Int32(), 912 kMipsLw, 913 kMipsSw, 914 &InstructionSelectorTest::Stream::IsInteger, 915 {-65000, -55000, 32777, 55000, 65000}}, 916 {MachineType::Float32(), 917 kMipsLwc1, 918 kMipsSwc1, 919 &InstructionSelectorTest::Stream::IsDouble, 920 {-65000, -55000, 32777, 55000, 65000}}, 921 {MachineType::Float64(), 922 kMipsLdc1, 923 kMipsSdc1, 924 &InstructionSelectorTest::Stream::IsDouble, 925 {-65000, -55000, 32777, 55000, 65000}}}; 926 927} // namespace 928 929 930typedef InstructionSelectorTestWithParam<MemoryAccess> 931 InstructionSelectorMemoryAccessTest; 932 933 934TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { 935 const MemoryAccess memacc = GetParam(); 936 StreamBuilder m(this, memacc.type, MachineType::Pointer(), 937 MachineType::Int32()); 938 m.Return(m.Load(memacc.type, m.Parameter(0))); 939 Stream s = m.Build(); 940 ASSERT_EQ(1U, s.size()); 941 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); 942 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 943} 944 945 946TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { 947 const MemoryAccess memacc = GetParam(); 948 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), 949 MachineType::Int32(), memacc.type); 950 m.Store(memacc.type.representation(), m.Parameter(0), m.Parameter(1), 951 kNoWriteBarrier); 952 m.Return(m.Int32Constant(0)); 953 Stream s = m.Build(); 954 ASSERT_EQ(1U, s.size()); 955 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); 956 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 957} 958 959 960INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 961 InstructionSelectorMemoryAccessTest, 962 ::testing::ValuesIn(kMemoryAccesses)); 963 964 965// ---------------------------------------------------------------------------- 966// Load immediate. 967// ---------------------------------------------------------------------------- 968 969 970typedef InstructionSelectorTestWithParam<MemoryAccessImm> 971 InstructionSelectorMemoryAccessImmTest; 972 973 974TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) { 975 const MemoryAccessImm memacc = GetParam(); 976 TRACED_FOREACH(int32_t, index, memacc.immediates) { 977 StreamBuilder m(this, memacc.type, MachineType::Pointer()); 978 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); 979 Stream s = m.Build(); 980 ASSERT_EQ(1U, s.size()); 981 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); 982 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 983 ASSERT_EQ(2U, s[0]->InputCount()); 984 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); 985 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); 986 ASSERT_EQ(1U, s[0]->OutputCount()); 987 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output())); 988 } 989} 990 991 992// ---------------------------------------------------------------------------- 993// Store immediate. 994// ---------------------------------------------------------------------------- 995 996 997TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) { 998 const MemoryAccessImm memacc = GetParam(); 999 TRACED_FOREACH(int32_t, index, memacc.immediates) { 1000 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), 1001 memacc.type); 1002 m.Store(memacc.type.representation(), m.Parameter(0), 1003 m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier); 1004 m.Return(m.Int32Constant(0)); 1005 Stream s = m.Build(); 1006 ASSERT_EQ(1U, s.size()); 1007 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); 1008 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); 1009 ASSERT_EQ(3U, s[0]->InputCount()); 1010 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); 1011 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); 1012 EXPECT_EQ(0U, s[0]->OutputCount()); 1013 } 1014} 1015 1016 1017INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 1018 InstructionSelectorMemoryAccessImmTest, 1019 ::testing::ValuesIn(kMemoryAccessesImm)); 1020 1021 1022// ---------------------------------------------------------------------------- 1023// Load/store offsets more than 16 bits. 1024// ---------------------------------------------------------------------------- 1025 1026 1027typedef InstructionSelectorTestWithParam<MemoryAccessImm1> 1028 InstructionSelectorMemoryAccessImmMoreThan16bitTest; 1029 1030 1031TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, 1032 LoadWithImmediateIndex) { 1033 const MemoryAccessImm1 memacc = GetParam(); 1034 TRACED_FOREACH(int32_t, index, memacc.immediates) { 1035 StreamBuilder m(this, memacc.type, MachineType::Pointer()); 1036 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); 1037 Stream s = m.Build(); 1038 ASSERT_EQ(2U, s.size()); 1039 // kMipsAdd is expected opcode. 1040 // size more than 16 bits wide. 1041 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); 1042 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 1043 EXPECT_EQ(2U, s[0]->InputCount()); 1044 EXPECT_EQ(1U, s[0]->OutputCount()); 1045 } 1046} 1047 1048 1049TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, 1050 StoreWithImmediateIndex) { 1051 const MemoryAccessImm1 memacc = GetParam(); 1052 TRACED_FOREACH(int32_t, index, memacc.immediates) { 1053 StreamBuilder m(this, MachineType::Int32(), MachineType::Pointer(), 1054 memacc.type); 1055 m.Store(memacc.type.representation(), m.Parameter(0), 1056 m.Int32Constant(index), m.Parameter(1), kNoWriteBarrier); 1057 m.Return(m.Int32Constant(0)); 1058 Stream s = m.Build(); 1059 ASSERT_EQ(2U, s.size()); 1060 // kMipsAdd is expected opcode 1061 // size more than 16 bits wide 1062 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); 1063 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 1064 EXPECT_EQ(2U, s[0]->InputCount()); 1065 EXPECT_EQ(1U, s[0]->OutputCount()); 1066 } 1067} 1068 1069 1070INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, 1071 InstructionSelectorMemoryAccessImmMoreThan16bitTest, 1072 ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit)); 1073 1074 1075// ---------------------------------------------------------------------------- 1076// kMipsTst testing. 1077// ---------------------------------------------------------------------------- 1078 1079 1080TEST_F(InstructionSelectorTest, Word32EqualWithZero) { 1081 { 1082 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 1083 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0))); 1084 Stream s = m.Build(); 1085 ASSERT_EQ(1U, s.size()); 1086 EXPECT_EQ(kMipsCmp, s[0]->arch_opcode()); 1087 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 1088 ASSERT_EQ(2U, s[0]->InputCount()); 1089 EXPECT_EQ(1U, s[0]->OutputCount()); 1090 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1091 EXPECT_EQ(kEqual, s[0]->flags_condition()); 1092 } 1093 { 1094 StreamBuilder m(this, MachineType::Int32(), MachineType::Int32()); 1095 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0))); 1096 Stream s = m.Build(); 1097 ASSERT_EQ(1U, s.size()); 1098 EXPECT_EQ(kMipsCmp, s[0]->arch_opcode()); 1099 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); 1100 ASSERT_EQ(2U, s[0]->InputCount()); 1101 EXPECT_EQ(1U, s[0]->OutputCount()); 1102 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); 1103 EXPECT_EQ(kEqual, s[0]->flags_condition()); 1104 } 1105} 1106 1107 1108TEST_F(InstructionSelectorTest, Word32Clz) { 1109 StreamBuilder m(this, MachineType::Uint32(), MachineType::Uint32()); 1110 Node* const p0 = m.Parameter(0); 1111 Node* const n = m.Word32Clz(p0); 1112 m.Return(n); 1113 Stream s = m.Build(); 1114 ASSERT_EQ(1U, s.size()); 1115 EXPECT_EQ(kMipsClz, s[0]->arch_opcode()); 1116 ASSERT_EQ(1U, s[0]->InputCount()); 1117 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1118 ASSERT_EQ(1U, s[0]->OutputCount()); 1119 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1120} 1121 1122 1123TEST_F(InstructionSelectorTest, Float32Abs) { 1124 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32()); 1125 Node* const p0 = m.Parameter(0); 1126 Node* const n = m.Float32Abs(p0); 1127 m.Return(n); 1128 Stream s = m.Build(); 1129 ASSERT_EQ(1U, s.size()); 1130 EXPECT_EQ(kMipsAbsS, s[0]->arch_opcode()); 1131 ASSERT_EQ(1U, s[0]->InputCount()); 1132 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1133 ASSERT_EQ(1U, s[0]->OutputCount()); 1134 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1135} 1136 1137 1138TEST_F(InstructionSelectorTest, Float64Abs) { 1139 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64()); 1140 Node* const p0 = m.Parameter(0); 1141 Node* const n = m.Float64Abs(p0); 1142 m.Return(n); 1143 Stream s = m.Build(); 1144 ASSERT_EQ(1U, s.size()); 1145 EXPECT_EQ(kMipsAbsD, s[0]->arch_opcode()); 1146 ASSERT_EQ(1U, s[0]->InputCount()); 1147 EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); 1148 ASSERT_EQ(1U, s[0]->OutputCount()); 1149 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1150} 1151 1152 1153TEST_F(InstructionSelectorTest, Float32Max) { 1154 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(), 1155 MachineType::Float32()); 1156 Node* const p0 = m.Parameter(0); 1157 Node* const p1 = m.Parameter(1); 1158 Node* const n = m.Float32Max(p0, p1); 1159 m.Return(n); 1160 Stream s = m.Build(); 1161 // Float32Max is `(b < a) ? a : b`. 1162 ASSERT_EQ(1U, s.size()); 1163 EXPECT_EQ(kMipsFloat32Max, s[0]->arch_opcode()); 1164 ASSERT_EQ(2U, s[0]->InputCount()); 1165 ASSERT_EQ(1U, s[0]->OutputCount()); 1166 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1167} 1168 1169 1170TEST_F(InstructionSelectorTest, Float32Min) { 1171 StreamBuilder m(this, MachineType::Float32(), MachineType::Float32(), 1172 MachineType::Float32()); 1173 Node* const p0 = m.Parameter(0); 1174 Node* const p1 = m.Parameter(1); 1175 Node* const n = m.Float32Min(p0, p1); 1176 m.Return(n); 1177 Stream s = m.Build(); 1178 // Float32Min is `(a < b) ? a : b`. 1179 ASSERT_EQ(1U, s.size()); 1180 EXPECT_EQ(kMipsFloat32Min, s[0]->arch_opcode()); 1181 ASSERT_EQ(2U, s[0]->InputCount()); 1182 ASSERT_EQ(1U, s[0]->OutputCount()); 1183 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1184} 1185 1186 1187TEST_F(InstructionSelectorTest, Float64Max) { 1188 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), 1189 MachineType::Float64()); 1190 Node* const p0 = m.Parameter(0); 1191 Node* const p1 = m.Parameter(1); 1192 Node* const n = m.Float64Max(p0, p1); 1193 m.Return(n); 1194 Stream s = m.Build(); 1195 // Float64Max is `(b < a) ? a : b`. 1196 ASSERT_EQ(1U, s.size()); 1197 EXPECT_EQ(kMipsFloat64Max, s[0]->arch_opcode()); 1198 ASSERT_EQ(2U, s[0]->InputCount()); 1199 ASSERT_EQ(1U, s[0]->OutputCount()); 1200 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1201} 1202 1203 1204TEST_F(InstructionSelectorTest, Float64Min) { 1205 StreamBuilder m(this, MachineType::Float64(), MachineType::Float64(), 1206 MachineType::Float64()); 1207 Node* const p0 = m.Parameter(0); 1208 Node* const p1 = m.Parameter(1); 1209 Node* const n = m.Float64Min(p0, p1); 1210 m.Return(n); 1211 Stream s = m.Build(); 1212 // Float64Min is `(a < b) ? a : b`. 1213 ASSERT_EQ(1U, s.size()); 1214 EXPECT_EQ(kMipsFloat64Min, s[0]->arch_opcode()); 1215 ASSERT_EQ(2U, s[0]->InputCount()); 1216 ASSERT_EQ(1U, s[0]->OutputCount()); 1217 EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); 1218} 1219 1220 1221} // namespace compiler 1222} // namespace internal 1223} // namespace v8 1224