Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 "src/compiler/instruction-selector-unittest.h" | |
| 6 | |
| 7 namespace v8 { | |
| 8 namespace internal { | |
| 9 namespace compiler { | |
| 10 | |
| 11 namespace { | |
| 12 | |
| 13 template <typename T> | |
| 14 struct MachInst { | |
| 15 T constructor; | |
| 16 const char* constructor_name; | |
| 17 ArchOpcode arch_opcode; | |
| 18 MachineType machine_type; | |
| 19 }; | |
| 20 | |
|
Benedikt Meurer
2014/09/25 05:37:11
You should add std::ostream& operator<<(std::ostre
paul.l...
2014/09/25 17:18:39
Done.
| |
| 21 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; | |
| 22 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; | |
| 23 | |
| 24 // To avoid duplicated code IntCmp helper structure | |
| 25 // is created. It contains MachInst2 with two nodes and expected_size | |
| 26 // because different cmp instructions have different size. | |
| 27 struct IntCmp { | |
| 28 MachInst2 mi; | |
| 29 uint32_t expected_size; | |
| 30 }; | |
| 31 | |
| 32 struct FPCmp { | |
| 33 MachInst2 mi; | |
| 34 FlagsCondition cond; | |
| 35 }; | |
| 36 | |
| 37 static const FPCmp kFPCmpInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
| 38 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMipsFloat64Cmp, | |
| 39 kMachFloat64}, | |
| 40 kUnorderedEqual}, | |
| 41 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMipsFloat64Cmp, | |
| 42 kMachFloat64}, | |
| 43 kUnorderedLessThan}, | |
| 44 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual", | |
| 45 kMipsFloat64Cmp, kMachFloat64}, | |
| 46 kUnorderedLessThanOrEqual}, | |
| 47 {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan", | |
| 48 kMipsFloat64Cmp, kMachFloat64}, | |
| 49 kUnorderedLessThan}, | |
| 50 {{&RawMachineAssembler::Float64GreaterThanOrEqual, | |
| 51 "Float64GreaterThanOrEqual", kMipsFloat64Cmp, kMachFloat64}, | |
| 52 kUnorderedLessThanOrEqual}}; | |
| 53 | |
| 54 struct Conversion { | |
| 55 // The machine_type field in MachInst1 represents the destination type. | |
| 56 MachInst1 mi; | |
| 57 MachineType src_machine_type; | |
| 58 }; | |
| 59 | |
| 60 | |
| 61 // ---------------------------------------------------------------------------- | |
| 62 // Logical instructions. | |
| 63 // ---------------------------------------------------------------------------- | |
| 64 | |
| 65 | |
| 66 static const MachInst2 kLogicalInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:40
Done.
| |
| 67 {&RawMachineAssembler::WordAnd, "WordAnd", kMipsAnd, kMachInt16}, | |
| 68 {&RawMachineAssembler::WordOr, "WordOr", kMipsOr, kMachInt16}, | |
| 69 {&RawMachineAssembler::WordXor, "WordXor", kMipsXor, kMachInt16}, | |
| 70 {&RawMachineAssembler::Word32And, "Word32And", kMipsAnd, kMachInt32}, | |
| 71 {&RawMachineAssembler::Word32Or, "Word32Or", kMipsOr, kMachInt32}, | |
| 72 {&RawMachineAssembler::Word32Xor, "Word32Xor", kMipsXor, kMachInt32}}; | |
| 73 | |
| 74 | |
| 75 // ---------------------------------------------------------------------------- | |
| 76 // Shift instructions. | |
| 77 // ---------------------------------------------------------------------------- | |
| 78 | |
| 79 | |
| 80 static const MachInst2 kShiftInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
| 81 {&RawMachineAssembler::WordShl, "WordShl", kMipsShl, kMachInt16}, | |
| 82 {&RawMachineAssembler::WordShr, "WordShr", kMipsShr, kMachInt16}, | |
| 83 {&RawMachineAssembler::WordSar, "WordSar", kMipsSar, kMachInt16}, | |
| 84 {&RawMachineAssembler::WordRor, "WordRor", kMipsRor, kMachInt16}, | |
| 85 {&RawMachineAssembler::Word32Shl, "Word32Shl", kMipsShl, kMachInt32}, | |
| 86 {&RawMachineAssembler::Word32Shr, "Word32Shr", kMipsShr, kMachInt32}, | |
| 87 {&RawMachineAssembler::Word32Sar, "Word32Sar", kMipsSar, kMachInt32}, | |
| 88 {&RawMachineAssembler::Word32Ror, "Word32Ror", kMipsRor, kMachInt32}}; | |
| 89 | |
| 90 | |
| 91 // ---------------------------------------------------------------------------- | |
| 92 // MUL/DIV instructions. | |
| 93 // ---------------------------------------------------------------------------- | |
| 94 | |
| 95 | |
| 96 static const MachInst2 kMulDivInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
| 97 {&RawMachineAssembler::Int32Mul, "Int32Mul", kMipsMul, kMachInt32}, | |
| 98 {&RawMachineAssembler::Int32Div, "Int32Div", kMipsDiv, kMachInt32}, | |
| 99 {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kMipsDivU, kMachUint32}, | |
| 100 {&RawMachineAssembler::Float64Mul, "Float64Mul", kMipsFloat64Mul, | |
| 101 kMachFloat64}, | |
| 102 {&RawMachineAssembler::Float64Div, "Float64Div", kMipsFloat64Div, | |
| 103 kMachFloat64}}; | |
| 104 | |
| 105 | |
| 106 // ---------------------------------------------------------------------------- | |
| 107 // MOD instructions. | |
| 108 // ---------------------------------------------------------------------------- | |
| 109 | |
| 110 | |
| 111 static const MachInst2 kModInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
| 112 {&RawMachineAssembler::Int32Mod, "Int32Mod", kMipsMod, kMachInt32}, | |
| 113 {&RawMachineAssembler::Int32UMod, "Int32UMod", kMipsModU, kMachInt32}, | |
| 114 {&RawMachineAssembler::Float64Mod, "Float64Mod", kMipsFloat64Mod, | |
| 115 kMachFloat64}}; | |
| 116 | |
| 117 | |
| 118 // ---------------------------------------------------------------------------- | |
| 119 // Arithmetic FPU instructions. | |
| 120 // ---------------------------------------------------------------------------- | |
| 121 | |
| 122 | |
| 123 static const MachInst2 kFPArithInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
| 124 {&RawMachineAssembler::Float64Add, "Float64Add", kMipsFloat64Add, | |
| 125 kMachFloat64}, | |
| 126 {&RawMachineAssembler::Float64Sub, "Float64Sub", kMipsFloat64Sub, | |
| 127 kMachFloat64}}; | |
| 128 | |
| 129 | |
| 130 // ---------------------------------------------------------------------------- | |
| 131 // IntArithTest instructions, two nodes. | |
| 132 // ---------------------------------------------------------------------------- | |
| 133 | |
| 134 | |
| 135 static const MachInst2 kAddSubInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
| 136 {&RawMachineAssembler::Int32Add, "Int32Add", kMipsAdd, kMachInt32}, | |
| 137 {&RawMachineAssembler::Int32Sub, "Int32Sub", kMipsSub, kMachInt32}, | |
| 138 {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow", | |
| 139 kMipsAddOvf, kMachInt32}, | |
| 140 {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow", | |
| 141 kMipsSubOvf, kMachInt32}}; | |
| 142 | |
| 143 | |
| 144 // ---------------------------------------------------------------------------- | |
| 145 // IntArithTest instructions, one node. | |
| 146 // ---------------------------------------------------------------------------- | |
| 147 | |
| 148 | |
| 149 static const MachInst1 kAddSubOneInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
| 150 {&RawMachineAssembler::Int32Neg, "Int32Neg", kMipsSub, kMachInt32}, | |
| 151 // TODO(dusmil): check this ... | |
| 152 // {&RawMachineAssembler::WordEqual , "WordEqual" , kMipsTst, kMachInt32} | |
| 153 }; | |
| 154 | |
| 155 | |
| 156 // ---------------------------------------------------------------------------- | |
| 157 // Arithmetic compare instructions. | |
| 158 // ---------------------------------------------------------------------------- | |
| 159 | |
| 160 | |
| 161 static const IntCmp kCmpInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
| |
| 162 {{&RawMachineAssembler::WordEqual, "WordEqual", kMipsCmp, kMachInt16}, 1U}, | |
| 163 {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMipsCmp, kMachInt16}, | |
| 164 2U}, | |
| 165 {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMipsCmp, kMachInt32}, | |
| 166 1U}, | |
| 167 {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMipsCmp, | |
| 168 kMachInt32}, | |
| 169 2U}, | |
| 170 {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMipsCmp, | |
| 171 kMachInt32}, | |
| 172 1U}, | |
| 173 {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual", | |
| 174 kMipsCmp, kMachInt32}, | |
| 175 1U}, | |
| 176 {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMipsCmp, | |
| 177 kMachInt32}, | |
| 178 1U}, | |
| 179 {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual", | |
| 180 kMipsCmp, kMachInt32}, | |
| 181 1U}, | |
| 182 {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMipsCmp, | |
| 183 kMachUint32}, | |
| 184 1U}, | |
| 185 {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual", | |
| 186 kMipsCmp, kMachUint32}, | |
| 187 1U}}; | |
| 188 | |
| 189 | |
| 190 // ---------------------------------------------------------------------------- | |
| 191 // Conversion instructions. | |
| 192 // ---------------------------------------------------------------------------- | |
| 193 | |
| 194 static const Conversion kConversionInstructions[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:40
Done.
| |
| 195 // Conversion instructions are related to machine_operator.h: | |
| 196 // FPU conversions: | |
| 197 // Convert representation of integers between float64 and int32/uint32. | |
| 198 // The precise rounding mode and handling of out of range inputs are *not* | |
| 199 // defined for these operators, since they are intended only for use with | |
| 200 // integers. | |
| 201 // mips instruction: cvt_d_w | |
| 202 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64", | |
| 203 kMipsInt32ToFloat64, kMachFloat64}, | |
| 204 kMachInt32}, | |
| 205 | |
| 206 // mips instruction: cvt_d_uw | |
| 207 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64", | |
| 208 kMipsUint32ToFloat64, kMachFloat64}, | |
| 209 kMachInt32}, | |
| 210 | |
| 211 // mips instruction: trunc_w_d | |
| 212 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32", | |
| 213 kMipsFloat64ToInt32, kMachFloat64}, | |
| 214 kMachInt32}, | |
| 215 | |
| 216 // mips instruction: trunc_uw_d | |
| 217 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32", | |
| 218 kMipsFloat64ToUint32, kMachFloat64}, | |
| 219 kMachInt32}}; | |
| 220 | |
| 221 } // namespace | |
| 222 | |
| 223 | |
| 224 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest; | |
| 225 | |
| 226 | |
| 227 TEST_P(InstructionSelectorFPCmpTest, Parameter) { | |
| 228 const FPCmp cmp = GetParam(); | |
| 229 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type); | |
| 230 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 231 Stream s = m.Build(); | |
| 232 ASSERT_EQ(1U, s.size()); | |
| 233 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); | |
| 234 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 235 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 236 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
| 237 EXPECT_EQ(cmp.cond, s[0]->flags_condition()); | |
| 238 } | |
| 239 | |
| 240 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest, | |
| 241 ::testing::ValuesIn(kFPCmpInstructions)); | |
| 242 | |
| 243 | |
| 244 // ---------------------------------------------------------------------------- | |
| 245 // Arithmetic compare instructions integers. | |
| 246 // ---------------------------------------------------------------------------- | |
| 247 | |
| 248 | |
| 249 typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest; | |
| 250 | |
| 251 | |
| 252 TEST_P(InstructionSelectorCmpTest, Parameter) { | |
| 253 const IntCmp cmp = GetParam(); | |
| 254 const MachineType type = cmp.mi.machine_type; | |
| 255 StreamBuilder m(this, type, type, type); | |
| 256 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 257 Stream s = m.Build(); | |
| 258 ASSERT_EQ(cmp.expected_size, s.size()); | |
| 259 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); | |
| 260 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 261 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 262 } | |
| 263 | |
| 264 | |
| 265 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest, | |
| 266 ::testing::ValuesIn(kCmpInstructions)); | |
| 267 | |
| 268 | |
| 269 // ---------------------------------------------------------------------------- | |
| 270 // Shift instructions. | |
| 271 // ---------------------------------------------------------------------------- | |
| 272 | |
| 273 | |
| 274 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 275 InstructionSelectorShiftTest; | |
| 276 | |
| 277 | |
| 278 TEST_P(InstructionSelectorShiftTest, Immediate) { | |
| 279 const MachInst2 dpi = GetParam(); | |
| 280 const MachineType type = dpi.machine_type; | |
| 281 TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) { | |
| 282 StreamBuilder m(this, type, type); | |
| 283 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
| 284 Stream s = m.Build(); | |
| 285 ASSERT_EQ(1U, s.size()); | |
| 286 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 287 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 288 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
| 289 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
| 290 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 291 } | |
| 292 } | |
| 293 | |
| 294 | |
| 295 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, | |
| 296 ::testing::ValuesIn(kShiftInstructions)); | |
| 297 | |
| 298 | |
| 299 // ---------------------------------------------------------------------------- | |
| 300 // Logical instructions. | |
| 301 // ---------------------------------------------------------------------------- | |
| 302 | |
| 303 | |
| 304 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 305 InstructionSelectorLogicalTest; | |
| 306 | |
| 307 | |
| 308 TEST_P(InstructionSelectorLogicalTest, Parameter) { | |
| 309 const MachInst2 dpi = GetParam(); | |
| 310 const MachineType type = dpi.machine_type; | |
| 311 StreamBuilder m(this, type, type, type); | |
| 312 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 313 Stream s = m.Build(); | |
| 314 ASSERT_EQ(1U, s.size()); | |
| 315 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 316 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 317 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 318 } | |
| 319 | |
| 320 | |
| 321 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, | |
| 322 ::testing::ValuesIn(kLogicalInstructions)); | |
| 323 | |
| 324 | |
| 325 // ---------------------------------------------------------------------------- | |
| 326 // MUL/DIV instructions. | |
| 327 // ---------------------------------------------------------------------------- | |
| 328 | |
| 329 | |
| 330 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 331 InstructionSelectorMulDivTest; | |
| 332 | |
| 333 | |
| 334 TEST_P(InstructionSelectorMulDivTest, Parameter) { | |
| 335 const MachInst2 dpi = GetParam(); | |
| 336 const MachineType type = dpi.machine_type; | |
| 337 StreamBuilder m(this, type, type, type); | |
| 338 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 339 Stream s = m.Build(); | |
| 340 ASSERT_EQ(1U, s.size()); | |
| 341 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 342 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 343 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 344 } | |
| 345 | |
| 346 | |
| 347 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest, | |
| 348 ::testing::ValuesIn(kMulDivInstructions)); | |
| 349 | |
| 350 | |
| 351 // ---------------------------------------------------------------------------- | |
| 352 // MOD instructions. | |
| 353 // ---------------------------------------------------------------------------- | |
| 354 | |
| 355 | |
| 356 typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest; | |
| 357 | |
| 358 | |
| 359 TEST_P(InstructionSelectorModTest, Parameter) { | |
| 360 const MachInst2 dpi = GetParam(); | |
| 361 const MachineType type = dpi.machine_type; | |
| 362 StreamBuilder m(this, type, type, type); | |
| 363 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 364 Stream s = m.Build(); | |
| 365 ASSERT_EQ(1U, s.size()); | |
| 366 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 367 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 368 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 369 } | |
| 370 | |
| 371 | |
| 372 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest, | |
| 373 ::testing::ValuesIn(kModInstructions)); | |
| 374 | |
| 375 | |
| 376 // ---------------------------------------------------------------------------- | |
| 377 // Floating point instructions. | |
| 378 // ---------------------------------------------------------------------------- | |
| 379 | |
| 380 | |
| 381 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 382 InstructionSelectorFPArithTest; | |
| 383 | |
| 384 | |
| 385 TEST_P(InstructionSelectorFPArithTest, Parameter) { | |
| 386 const MachInst2 fpa = GetParam(); | |
| 387 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type); | |
| 388 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 389 Stream s = m.Build(); | |
| 390 ASSERT_EQ(1U, s.size()); | |
| 391 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode()); | |
| 392 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 393 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 394 } | |
| 395 | |
| 396 | |
| 397 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest, | |
| 398 ::testing::ValuesIn(kFPArithInstructions)); | |
| 399 | |
| 400 | |
| 401 // ---------------------------------------------------------------------------- | |
| 402 // Integer arithmetic. | |
| 403 // ---------------------------------------------------------------------------- | |
| 404 | |
| 405 | |
| 406 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 407 InstructionSelectorIntArithTwoTest; | |
| 408 | |
| 409 | |
| 410 TEST_P(InstructionSelectorIntArithTwoTest, Parameter) { | |
| 411 const MachInst2 intpa = GetParam(); | |
| 412 StreamBuilder m(this, intpa.machine_type, intpa.machine_type, | |
| 413 intpa.machine_type); | |
| 414 m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 415 Stream s = m.Build(); | |
| 416 ASSERT_EQ(1U, s.size()); | |
| 417 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); | |
| 418 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 419 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 420 } | |
| 421 | |
| 422 | |
| 423 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
| 424 InstructionSelectorIntArithTwoTest, | |
| 425 ::testing::ValuesIn(kAddSubInstructions)); | |
| 426 | |
| 427 | |
| 428 // ---------------------------------------------------------------------------- | |
| 429 // One node. | |
| 430 // ---------------------------------------------------------------------------- | |
| 431 | |
| 432 | |
| 433 typedef InstructionSelectorTestWithParam<MachInst1> | |
| 434 InstructionSelectorIntArithOneTest; | |
| 435 | |
| 436 | |
| 437 TEST_P(InstructionSelectorIntArithOneTest, Parameter) { | |
| 438 const MachInst1 intpa = GetParam(); | |
| 439 StreamBuilder m(this, intpa.machine_type, intpa.machine_type, | |
| 440 intpa.machine_type); | |
| 441 m.Return((m.*intpa.constructor)(m.Parameter(0))); | |
| 442 Stream s = m.Build(); | |
| 443 ASSERT_EQ(1U, s.size()); | |
| 444 EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); | |
| 445 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 446 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 447 } | |
| 448 | |
| 449 | |
| 450 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
| 451 InstructionSelectorIntArithOneTest, | |
| 452 ::testing::ValuesIn(kAddSubOneInstructions)); | |
| 453 | |
| 454 | |
| 455 // ---------------------------------------------------------------------------- | |
| 456 // Conversions. | |
| 457 // ---------------------------------------------------------------------------- | |
| 458 | |
| 459 | |
| 460 typedef InstructionSelectorTestWithParam<Conversion> | |
| 461 InstructionSelectorConversionTest; | |
| 462 | |
| 463 | |
| 464 TEST_P(InstructionSelectorConversionTest, Parameter) { | |
| 465 const Conversion conv = GetParam(); | |
| 466 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); | |
| 467 m.Return((m.*conv.mi.constructor)(m.Parameter(0))); | |
| 468 Stream s = m.Build(); | |
| 469 ASSERT_EQ(1U, s.size()); | |
| 470 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); | |
| 471 EXPECT_EQ(1U, s[0]->InputCount()); | |
| 472 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 473 } | |
| 474 | |
| 475 | |
| 476 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
| 477 InstructionSelectorConversionTest, | |
| 478 ::testing::ValuesIn(kConversionInstructions)); | |
| 479 | |
| 480 | |
| 481 // ---------------------------------------------------------------------------- | |
| 482 // Loads and stores. | |
| 483 // ---------------------------------------------------------------------------- | |
| 484 | |
| 485 namespace { | |
| 486 | |
| 487 struct MemoryAccess { | |
| 488 MachineType type; | |
| 489 ArchOpcode load_opcode; | |
| 490 ArchOpcode store_opcode; | |
| 491 }; | |
| 492 | |
| 493 | |
| 494 static const MemoryAccess kMemoryAccesses[] = { | |
| 495 {kMachInt8, kMipsLb, kMipsSb}, | |
| 496 {kMachUint8, kMipsLbu, kMipsSb}, | |
| 497 {kMachInt16, kMipsLh, kMipsSh}, | |
| 498 {kMachUint16, kMipsLhu, kMipsSh}, | |
| 499 {kMachInt32, kMipsLw, kMipsSw}, | |
| 500 {kRepFloat32, kMipsLwc1, kMipsSwc1}, | |
| 501 {kRepFloat64, kMipsLdc1, kMipsSdc1}}; | |
| 502 | |
| 503 | |
| 504 struct MemoryAccessImm { | |
| 505 MachineType type; | |
| 506 ArchOpcode load_opcode; | |
| 507 ArchOpcode store_opcode; | |
| 508 bool (InstructionSelectorTest::Stream::*val_predicate)( | |
| 509 const InstructionOperand*) const; | |
| 510 const int32_t immediates[40]; | |
| 511 }; | |
| 512 | |
|
Benedikt Meurer
2014/09/25 05:37:11
You should add
std::ostream& operator<<(std::ostr
paul.l...
2014/09/25 17:18:39
Done.
| |
| 513 | |
| 514 struct MemoryAccessImm1 { | |
| 515 MachineType type; | |
| 516 ArchOpcode load_opcode; | |
| 517 ArchOpcode store_opcode; | |
| 518 bool (InstructionSelectorTest::Stream::*val_predicate)( | |
| 519 const InstructionOperand*) const; | |
| 520 const int32_t immediates[5]; | |
| 521 }; | |
| 522 | |
|
Benedikt Meurer
2014/09/25 05:37:11
Stream operator, see above.
paul.l...
2014/09/25 17:18:39
Done.
| |
| 523 | |
| 524 // ---------------------------------------------------------------------------- | |
| 525 // Loads and stores immediate values. | |
| 526 // ---------------------------------------------------------------------------- | |
| 527 | |
| 528 | |
| 529 static const MemoryAccessImm kMemoryAccessesImm[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: static, see above.
paul.l...
2014/09/25 17:18:40
Done.
| |
| 530 {kMachInt8, | |
| 531 kMipsLb, | |
| 532 kMipsSb, | |
| 533 &InstructionSelectorTest::Stream::IsInteger, | |
| 534 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
| 535 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
| 536 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
| 537 {kMachUint8, | |
| 538 kMipsLbu, | |
| 539 kMipsSb, | |
| 540 &InstructionSelectorTest::Stream::IsInteger, | |
| 541 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
| 542 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
| 543 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
| 544 {kMachInt16, | |
| 545 kMipsLh, | |
| 546 kMipsSh, | |
| 547 &InstructionSelectorTest::Stream::IsInteger, | |
| 548 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
| 549 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
| 550 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
| 551 {kMachUint16, | |
| 552 kMipsLhu, | |
| 553 kMipsSh, | |
| 554 &InstructionSelectorTest::Stream::IsInteger, | |
| 555 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
| 556 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
| 557 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
| 558 {kMachInt32, | |
| 559 kMipsLw, | |
| 560 kMipsSw, | |
| 561 &InstructionSelectorTest::Stream::IsInteger, | |
| 562 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
| 563 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
| 564 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
| 565 {kMachFloat32, | |
| 566 kMipsLwc1, | |
| 567 kMipsSwc1, | |
| 568 &InstructionSelectorTest::Stream::IsDouble, | |
| 569 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
| 570 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
| 571 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, | |
| 572 {kMachFloat64, | |
| 573 kMipsLdc1, | |
| 574 kMipsSdc1, | |
| 575 &InstructionSelectorTest::Stream::IsDouble, | |
| 576 {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, | |
| 577 -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, | |
| 578 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}}; | |
| 579 | |
| 580 | |
| 581 static const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = { | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: static, see above.
paul.l...
2014/09/25 17:18:39
Done.
| |
| 582 {kMachInt8, | |
| 583 kMipsLb, | |
| 584 kMipsSb, | |
| 585 &InstructionSelectorTest::Stream::IsInteger, | |
| 586 {-65000, -55000, 32777, 55000, 65000}}, | |
| 587 {kMachInt8, | |
| 588 kMipsLbu, | |
| 589 kMipsSb, | |
| 590 &InstructionSelectorTest::Stream::IsInteger, | |
| 591 {-65000, -55000, 32777, 55000, 65000}}, | |
| 592 {kMachInt16, | |
| 593 kMipsLh, | |
| 594 kMipsSh, | |
| 595 &InstructionSelectorTest::Stream::IsInteger, | |
| 596 {-65000, -55000, 32777, 55000, 65000}}, | |
| 597 {kMachInt16, | |
| 598 kMipsLhu, | |
| 599 kMipsSh, | |
| 600 &InstructionSelectorTest::Stream::IsInteger, | |
| 601 {-65000, -55000, 32777, 55000, 65000}}, | |
| 602 {kMachInt32, | |
| 603 kMipsLw, | |
| 604 kMipsSw, | |
| 605 &InstructionSelectorTest::Stream::IsInteger, | |
| 606 {-65000, -55000, 32777, 55000, 65000}}, | |
| 607 {kMachFloat32, | |
| 608 kMipsLwc1, | |
| 609 kMipsSwc1, | |
| 610 &InstructionSelectorTest::Stream::IsDouble, | |
| 611 {-65000, -55000, 32777, 55000, 65000}}, | |
| 612 {kMachFloat64, | |
| 613 kMipsLdc1, | |
| 614 kMipsSdc1, | |
| 615 &InstructionSelectorTest::Stream::IsDouble, | |
| 616 {-65000, -55000, 32777, 55000, 65000}}}; | |
| 617 | |
| 618 } // namespace | |
| 619 | |
| 620 | |
| 621 typedef InstructionSelectorTestWithParam<MemoryAccess> | |
| 622 InstructionSelectorMemoryAccessTest; | |
| 623 | |
| 624 | |
| 625 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { | |
| 626 const MemoryAccess memacc = GetParam(); | |
| 627 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32); | |
| 628 m.Return(m.Load(memacc.type, m.Parameter(0))); | |
| 629 Stream s = m.Build(); | |
| 630 ASSERT_EQ(1U, s.size()); | |
| 631 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | |
| 632 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | |
| 633 } | |
| 634 | |
| 635 | |
| 636 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | |
| 637 const MemoryAccess memacc = GetParam(); | |
| 638 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); | |
| 639 m.Store(memacc.type, m.Parameter(0), m.Parameter(1)); | |
| 640 m.Return(m.Int32Constant(0)); | |
| 641 Stream s = m.Build(); | |
| 642 ASSERT_EQ(1U, s.size()); | |
| 643 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | |
| 644 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | |
| 645 } | |
| 646 | |
| 647 | |
| 648 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
| 649 InstructionSelectorMemoryAccessTest, | |
| 650 ::testing::ValuesIn(kMemoryAccesses)); | |
| 651 | |
| 652 | |
| 653 // ---------------------------------------------------------------------------- | |
| 654 // Load immediate. | |
| 655 // ---------------------------------------------------------------------------- | |
| 656 | |
| 657 | |
| 658 typedef InstructionSelectorTestWithParam<MemoryAccessImm> | |
| 659 InstructionSelectorMemoryAccessImmTest; | |
| 660 | |
| 661 | |
| 662 TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) { | |
| 663 const MemoryAccessImm memacc = GetParam(); | |
| 664 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
| 665 StreamBuilder m(this, memacc.type, kMachPtr); | |
| 666 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | |
| 667 Stream s = m.Build(); | |
| 668 ASSERT_EQ(1U, s.size()); | |
| 669 EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); | |
| 670 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | |
| 671 ASSERT_EQ(2U, s[0]->InputCount()); | |
| 672 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
| 673 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | |
| 674 ASSERT_EQ(1U, s[0]->OutputCount()); | |
| 675 EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output())); | |
| 676 } | |
| 677 } | |
| 678 | |
| 679 | |
| 680 // ---------------------------------------------------------------------------- | |
| 681 // Store immediate. | |
| 682 // ---------------------------------------------------------------------------- | |
| 683 | |
| 684 | |
| 685 TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) { | |
| 686 const MemoryAccessImm memacc = GetParam(); | |
| 687 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
| 688 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); | |
| 689 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), | |
| 690 m.Parameter(1)); | |
| 691 m.Return(m.Int32Constant(0)); | |
| 692 Stream s = m.Build(); | |
| 693 ASSERT_EQ(1U, s.size()); | |
| 694 EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); | |
| 695 EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); | |
| 696 ASSERT_EQ(3U, s[0]->InputCount()); | |
| 697 ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); | |
| 698 EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); | |
| 699 EXPECT_EQ(0U, s[0]->OutputCount()); | |
| 700 } | |
| 701 } | |
| 702 | |
| 703 | |
| 704 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
| 705 InstructionSelectorMemoryAccessImmTest, | |
| 706 ::testing::ValuesIn(kMemoryAccessesImm)); | |
| 707 | |
| 708 | |
| 709 // ---------------------------------------------------------------------------- | |
| 710 // Load/store offsets more than 16 bits. | |
| 711 // ---------------------------------------------------------------------------- | |
| 712 | |
| 713 | |
| 714 typedef InstructionSelectorTestWithParam<MemoryAccessImm1> | |
| 715 InstructionSelectorMemoryAccessImmMoreThan16bitTest; | |
| 716 | |
| 717 | |
| 718 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, | |
| 719 LoadWithImmediateIndex) { | |
| 720 const MemoryAccessImm1 memacc = GetParam(); | |
| 721 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
| 722 StreamBuilder m(this, memacc.type, kMachPtr); | |
| 723 m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); | |
| 724 Stream s = m.Build(); | |
| 725 ASSERT_EQ(2U, s.size()); | |
| 726 // kMipsAdd is expected opcode. | |
| 727 // size more than 16 bits wide. | |
| 728 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); | |
| 729 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); | |
| 730 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 731 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 732 } | |
| 733 } | |
| 734 | |
| 735 | |
| 736 TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, | |
| 737 StoreWithImmediateIndex) { | |
| 738 const MemoryAccessImm1 memacc = GetParam(); | |
| 739 TRACED_FOREACH(int32_t, index, memacc.immediates) { | |
| 740 StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); | |
| 741 m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), | |
| 742 m.Parameter(1)); | |
| 743 m.Return(m.Int32Constant(0)); | |
| 744 Stream s = m.Build(); | |
| 745 ASSERT_EQ(2U, s.size()); | |
| 746 // kMipsAdd is expected opcode | |
| 747 // size more than 16 bits wide | |
| 748 EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); | |
| 749 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); | |
| 750 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 751 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 752 } | |
| 753 } | |
| 754 | |
| 755 | |
| 756 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
| 757 InstructionSelectorMemoryAccessImmMoreThan16bitTest, | |
| 758 ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit)); | |
| 759 | |
| 760 | |
| 761 // ---------------------------------------------------------------------------- | |
| 762 // kMipsTst testing. | |
| 763 // ---------------------------------------------------------------------------- | |
| 764 | |
| 765 | |
| 766 TEST_F(InstructionSelectorTest, Word32EqualWithZero) { | |
| 767 { | |
| 768 StreamBuilder m(this, kMachInt32, kMachInt32); | |
| 769 m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0))); | |
| 770 Stream s = m.Build(); | |
| 771 ASSERT_EQ(1U, s.size()); | |
| 772 EXPECT_EQ(kMipsTst, s[0]->arch_opcode()); | |
| 773 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); | |
| 774 ASSERT_EQ(2U, s[0]->InputCount()); | |
| 775 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
| 776 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 777 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
| 778 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
| 779 } | |
| 780 { | |
| 781 StreamBuilder m(this, kMachInt32, kMachInt32); | |
| 782 m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0))); | |
| 783 Stream s = m.Build(); | |
| 784 ASSERT_EQ(1U, s.size()); | |
| 785 EXPECT_EQ(kMipsTst, s[0]->arch_opcode()); | |
| 786 EXPECT_EQ(kMode_None, s[0]->addressing_mode()); | |
| 787 ASSERT_EQ(2U, s[0]->InputCount()); | |
| 788 EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); | |
| 789 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 790 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
| 791 EXPECT_EQ(kEqual, s[0]->flags_condition()); | |
| 792 } | |
| 793 } | |
| 794 | |
| 795 | |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: extra new line :-)
paul.l...
2014/09/25 17:18:39
Done.
| |
| 796 } // namespace compiler | |
| 797 } // namespace internal | |
| 798 } // namespace v8 | |
| OLD | NEW |