| 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 <list> | |
| 6 | |
| 7 #include "test/compiler-unittests/instruction-selector-unittest.h" | |
| 8 | |
| 9 namespace v8 { | |
| 10 namespace internal { | |
| 11 namespace compiler { | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 template <typename T> | |
| 16 struct MachInst { | |
| 17 T constructor; | |
| 18 const char* constructor_name; | |
| 19 ArchOpcode arch_opcode; | |
| 20 MachineType machine_type; | |
| 21 }; | |
| 22 | |
| 23 typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; | |
| 24 typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; | |
| 25 | |
| 26 | |
| 27 template <typename T> | |
| 28 std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) { | |
| 29 return os << mi.constructor_name; | |
| 30 } | |
| 31 | |
| 32 | |
| 33 // ARM64 logical instructions. | |
| 34 static const MachInst2 kLogicalInstructions[] = { | |
| 35 {&RawMachineAssembler::Word32And, "Word32And", kArm64And32, kMachInt32}, | |
| 36 {&RawMachineAssembler::Word64And, "Word64And", kArm64And, kMachInt64}, | |
| 37 {&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32, kMachInt32}, | |
| 38 {&RawMachineAssembler::Word64Or, "Word64Or", kArm64Or, kMachInt64}, | |
| 39 {&RawMachineAssembler::Word32Xor, "Word32Xor", kArm64Xor32, kMachInt32}, | |
| 40 {&RawMachineAssembler::Word64Xor, "Word64Xor", kArm64Xor, kMachInt64}}; | |
| 41 | |
| 42 | |
| 43 // ARM64 logical immediates: contiguous set bits, rotated about a power of two | |
| 44 // sized block. The block is then duplicated across the word. Below is a random | |
| 45 // subset of the 32-bit immediates. | |
| 46 static const uint32_t kLogicalImmediates[] = { | |
| 47 0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0, | |
| 48 0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000, | |
| 49 0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000, | |
| 50 0x001ffffc, 0x003f0000, 0x003f8000, 0x00780000, 0x007fc000, 0x00ff0000, | |
| 51 0x01800000, 0x01800180, 0x01f801f8, 0x03fe0000, 0x03ffffc0, 0x03fffffc, | |
| 52 0x06000000, 0x07fc0000, 0x07ffc000, 0x07ffffc0, 0x07ffffe0, 0x0ffe0ffe, | |
| 53 0x0ffff800, 0x0ffffff0, 0x0fffffff, 0x18001800, 0x1f001f00, 0x1f801f80, | |
| 54 0x30303030, 0x3ff03ff0, 0x3ff83ff8, 0x3fff0000, 0x3fff8000, 0x3fffffc0, | |
| 55 0x70007000, 0x7f7f7f7f, 0x7fc00000, 0x7fffffc0, 0x8000001f, 0x800001ff, | |
| 56 0x81818181, 0x9fff9fff, 0xc00007ff, 0xc0ffffff, 0xdddddddd, 0xe00001ff, | |
| 57 0xe00003ff, 0xe007ffff, 0xefffefff, 0xf000003f, 0xf001f001, 0xf3fff3ff, | |
| 58 0xf800001f, 0xf80fffff, 0xf87ff87f, 0xfbfbfbfb, 0xfc00001f, 0xfc0000ff, | |
| 59 0xfc0001ff, 0xfc03fc03, 0xfe0001ff, 0xff000001, 0xff03ff03, 0xff800000, | |
| 60 0xff800fff, 0xff801fff, 0xff87ffff, 0xffc0003f, 0xffc007ff, 0xffcfffcf, | |
| 61 0xffe00003, 0xffe1ffff, 0xfff0001f, 0xfff07fff, 0xfff80007, 0xfff87fff, | |
| 62 0xfffc00ff, 0xfffe07ff, 0xffff00ff, 0xffffc001, 0xfffff007, 0xfffff3ff, | |
| 63 0xfffff807, 0xfffff9ff, 0xfffffc0f, 0xfffffeff}; | |
| 64 | |
| 65 | |
| 66 // ARM64 arithmetic instructions. | |
| 67 static const MachInst2 kAddSubInstructions[] = { | |
| 68 {&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32}, | |
| 69 {&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64}, | |
| 70 {&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Sub32, kMachInt32}, | |
| 71 {&RawMachineAssembler::Int64Sub, "Int64Sub", kArm64Sub, kMachInt64}}; | |
| 72 | |
| 73 | |
| 74 // ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12. | |
| 75 // Below is a combination of a random subset and some edge values. | |
| 76 static const int32_t kAddSubImmediates[] = { | |
| 77 0, 1, 69, 493, 599, 701, 719, | |
| 78 768, 818, 842, 945, 1246, 1286, 1429, | |
| 79 1669, 2171, 2179, 2182, 2254, 2334, 2338, | |
| 80 2343, 2396, 2449, 2610, 2732, 2855, 2876, | |
| 81 2944, 3377, 3458, 3475, 3476, 3540, 3574, | |
| 82 3601, 3813, 3871, 3917, 4095, 4096, 16384, | |
| 83 364544, 462848, 970752, 1523712, 1863680, 2363392, 3219456, | |
| 84 3280896, 4247552, 4526080, 4575232, 4960256, 5505024, 5894144, | |
| 85 6004736, 6193152, 6385664, 6795264, 7114752, 7233536, 7348224, | |
| 86 7499776, 7573504, 7729152, 8634368, 8937472, 9465856, 10354688, | |
| 87 10682368, 11059200, 11460608, 13168640, 13176832, 14336000, 15028224, | |
| 88 15597568, 15892480, 16773120}; | |
| 89 | |
| 90 | |
| 91 // ARM64 shift instructions. | |
| 92 static const MachInst2 kShiftInstructions[] = { | |
| 93 {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Shl32, kMachInt32}, | |
| 94 {&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Shl, kMachInt64}, | |
| 95 {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Shr32, kMachInt32}, | |
| 96 {&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Shr, kMachInt64}, | |
| 97 {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Sar32, kMachInt32}, | |
| 98 {&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Sar, kMachInt64}, | |
| 99 {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32}, | |
| 100 {&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64}}; | |
| 101 | |
| 102 | |
| 103 // ARM64 Mul/Div instructions. | |
| 104 static const MachInst2 kMulDivInstructions[] = { | |
| 105 {&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32}, | |
| 106 {&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64}, | |
| 107 {&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32}, | |
| 108 {&RawMachineAssembler::Int64Div, "Int64Div", kArm64Idiv, kMachInt64}, | |
| 109 {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kArm64Udiv32, kMachInt32}, | |
| 110 {&RawMachineAssembler::Int64UDiv, "Int64UDiv", kArm64Udiv, kMachInt64}}; | |
| 111 | |
| 112 | |
| 113 // ARM64 FP arithmetic instructions. | |
| 114 static const MachInst2 kFPArithInstructions[] = { | |
| 115 {&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add, | |
| 116 kMachFloat64}, | |
| 117 {&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub, | |
| 118 kMachFloat64}, | |
| 119 {&RawMachineAssembler::Float64Mul, "Float64Mul", kArm64Float64Mul, | |
| 120 kMachFloat64}, | |
| 121 {&RawMachineAssembler::Float64Div, "Float64Div", kArm64Float64Div, | |
| 122 kMachFloat64}}; | |
| 123 | |
| 124 | |
| 125 struct FPCmp { | |
| 126 MachInst2 mi; | |
| 127 FlagsCondition cond; | |
| 128 }; | |
| 129 | |
| 130 | |
| 131 std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) { | |
| 132 return os << cmp.mi; | |
| 133 } | |
| 134 | |
| 135 | |
| 136 // ARM64 FP comparison instructions. | |
| 137 static const FPCmp kFPCmpInstructions[] = { | |
| 138 {{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp, | |
| 139 kMachFloat64}, | |
| 140 kUnorderedEqual}, | |
| 141 {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", | |
| 142 kArm64Float64Cmp, kMachFloat64}, | |
| 143 kUnorderedLessThan}, | |
| 144 {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual", | |
| 145 kArm64Float64Cmp, kMachFloat64}, | |
| 146 kUnorderedLessThanOrEqual}}; | |
| 147 | |
| 148 | |
| 149 struct Conversion { | |
| 150 // The machine_type field in MachInst1 represents the destination type. | |
| 151 MachInst1 mi; | |
| 152 MachineType src_machine_type; | |
| 153 }; | |
| 154 | |
| 155 | |
| 156 std::ostream& operator<<(std::ostream& os, const Conversion& conv) { | |
| 157 return os << conv.mi; | |
| 158 } | |
| 159 | |
| 160 | |
| 161 // ARM64 type conversion instructions. | |
| 162 static const Conversion kConversionInstructions[] = { | |
| 163 {{&RawMachineAssembler::ChangeInt32ToInt64, "ChangeInt32ToInt64", | |
| 164 kArm64Sxtw, kMachInt64}, | |
| 165 kMachInt32}, | |
| 166 {{&RawMachineAssembler::ChangeUint32ToUint64, "ChangeUint32ToUint64", | |
| 167 kArm64Mov32, kMachUint64}, | |
| 168 kMachUint32}, | |
| 169 {{&RawMachineAssembler::TruncateInt64ToInt32, "TruncateInt64ToInt32", | |
| 170 kArm64Mov32, kMachInt32}, | |
| 171 kMachInt64}, | |
| 172 {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64", | |
| 173 kArm64Int32ToFloat64, kMachFloat64}, | |
| 174 kMachInt32}, | |
| 175 {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64", | |
| 176 kArm64Uint32ToFloat64, kMachFloat64}, | |
| 177 kMachUint32}, | |
| 178 {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32", | |
| 179 kArm64Float64ToInt32, kMachInt32}, | |
| 180 kMachFloat64}, | |
| 181 {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32", | |
| 182 kArm64Float64ToUint32, kMachUint32}, | |
| 183 kMachFloat64}}; | |
| 184 | |
| 185 } // namespace | |
| 186 | |
| 187 | |
| 188 // ----------------------------------------------------------------------------- | |
| 189 // Logical instructions. | |
| 190 | |
| 191 | |
| 192 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 193 InstructionSelectorLogicalTest; | |
| 194 | |
| 195 | |
| 196 TEST_P(InstructionSelectorLogicalTest, Parameter) { | |
| 197 const MachInst2 dpi = GetParam(); | |
| 198 const MachineType type = dpi.machine_type; | |
| 199 StreamBuilder m(this, type, type, type); | |
| 200 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 201 Stream s = m.Build(); | |
| 202 ASSERT_EQ(1U, s.size()); | |
| 203 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 204 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 205 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 206 } | |
| 207 | |
| 208 | |
| 209 TEST_P(InstructionSelectorLogicalTest, Immediate) { | |
| 210 const MachInst2 dpi = GetParam(); | |
| 211 const MachineType type = dpi.machine_type; | |
| 212 // TODO(all): Add support for testing 64-bit immediates. | |
| 213 if (type == kMachInt32) { | |
| 214 // Immediate on the right. | |
| 215 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) { | |
| 216 StreamBuilder m(this, type, type); | |
| 217 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
| 218 Stream s = m.Build(); | |
| 219 ASSERT_EQ(1U, s.size()); | |
| 220 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 221 ASSERT_EQ(2U, s[0]->InputCount()); | |
| 222 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
| 223 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
| 224 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 225 } | |
| 226 | |
| 227 // Immediate on the left; all logical ops should commute. | |
| 228 TRACED_FOREACH(int32_t, imm, kLogicalImmediates) { | |
| 229 StreamBuilder m(this, type, type); | |
| 230 m.Return((m.*dpi.constructor)(m.Int32Constant(imm), m.Parameter(0))); | |
| 231 Stream s = m.Build(); | |
| 232 ASSERT_EQ(1U, s.size()); | |
| 233 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 234 ASSERT_EQ(2U, s[0]->InputCount()); | |
| 235 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
| 236 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
| 237 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 238 } | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 | |
| 243 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, | |
| 244 ::testing::ValuesIn(kLogicalInstructions)); | |
| 245 | |
| 246 | |
| 247 // ----------------------------------------------------------------------------- | |
| 248 // Add and Sub instructions. | |
| 249 | |
| 250 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 251 InstructionSelectorAddSubTest; | |
| 252 | |
| 253 | |
| 254 TEST_P(InstructionSelectorAddSubTest, Parameter) { | |
| 255 const MachInst2 dpi = GetParam(); | |
| 256 const MachineType type = dpi.machine_type; | |
| 257 StreamBuilder m(this, type, type, type); | |
| 258 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 259 Stream s = m.Build(); | |
| 260 ASSERT_EQ(1U, s.size()); | |
| 261 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 262 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 263 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 264 } | |
| 265 | |
| 266 | |
| 267 TEST_P(InstructionSelectorAddSubTest, Immediate) { | |
| 268 const MachInst2 dpi = GetParam(); | |
| 269 const MachineType type = dpi.machine_type; | |
| 270 TRACED_FOREACH(int32_t, imm, kAddSubImmediates) { | |
| 271 StreamBuilder m(this, type, type); | |
| 272 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
| 273 Stream s = m.Build(); | |
| 274 ASSERT_EQ(1U, s.size()); | |
| 275 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 276 ASSERT_EQ(2U, s[0]->InputCount()); | |
| 277 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
| 278 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
| 279 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 280 } | |
| 281 } | |
| 282 | |
| 283 | |
| 284 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest, | |
| 285 ::testing::ValuesIn(kAddSubInstructions)); | |
| 286 | |
| 287 | |
| 288 // ----------------------------------------------------------------------------- | |
| 289 // Shift instructions. | |
| 290 | |
| 291 | |
| 292 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 293 InstructionSelectorShiftTest; | |
| 294 | |
| 295 | |
| 296 TEST_P(InstructionSelectorShiftTest, Parameter) { | |
| 297 const MachInst2 dpi = GetParam(); | |
| 298 const MachineType type = dpi.machine_type; | |
| 299 StreamBuilder m(this, type, type, type); | |
| 300 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 301 Stream s = m.Build(); | |
| 302 ASSERT_EQ(1U, s.size()); | |
| 303 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 304 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 305 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 306 } | |
| 307 | |
| 308 | |
| 309 TEST_P(InstructionSelectorShiftTest, Immediate) { | |
| 310 const MachInst2 dpi = GetParam(); | |
| 311 const MachineType type = dpi.machine_type; | |
| 312 TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) { | |
| 313 StreamBuilder m(this, type, type); | |
| 314 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); | |
| 315 Stream s = m.Build(); | |
| 316 ASSERT_EQ(1U, s.size()); | |
| 317 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 318 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 319 EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); | |
| 320 EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); | |
| 321 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 322 } | |
| 323 } | |
| 324 | |
| 325 | |
| 326 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, | |
| 327 ::testing::ValuesIn(kShiftInstructions)); | |
| 328 | |
| 329 | |
| 330 // ----------------------------------------------------------------------------- | |
| 331 // Mul and Div instructions. | |
| 332 | |
| 333 | |
| 334 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 335 InstructionSelectorMulDivTest; | |
| 336 | |
| 337 | |
| 338 TEST_P(InstructionSelectorMulDivTest, Parameter) { | |
| 339 const MachInst2 dpi = GetParam(); | |
| 340 const MachineType type = dpi.machine_type; | |
| 341 StreamBuilder m(this, type, type, type); | |
| 342 m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 343 Stream s = m.Build(); | |
| 344 ASSERT_EQ(1U, s.size()); | |
| 345 EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); | |
| 346 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 347 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 348 } | |
| 349 | |
| 350 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest, | |
| 351 ::testing::ValuesIn(kMulDivInstructions)); | |
| 352 | |
| 353 | |
| 354 // ----------------------------------------------------------------------------- | |
| 355 // Floating point instructions. | |
| 356 | |
| 357 typedef InstructionSelectorTestWithParam<MachInst2> | |
| 358 InstructionSelectorFPArithTest; | |
| 359 | |
| 360 | |
| 361 TEST_P(InstructionSelectorFPArithTest, Parameter) { | |
| 362 const MachInst2 fpa = GetParam(); | |
| 363 StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type); | |
| 364 m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 365 Stream s = m.Build(); | |
| 366 ASSERT_EQ(1U, s.size()); | |
| 367 EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode()); | |
| 368 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 369 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 370 } | |
| 371 | |
| 372 | |
| 373 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest, | |
| 374 ::testing::ValuesIn(kFPArithInstructions)); | |
| 375 | |
| 376 | |
| 377 typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest; | |
| 378 | |
| 379 | |
| 380 TEST_P(InstructionSelectorFPCmpTest, Parameter) { | |
| 381 const FPCmp cmp = GetParam(); | |
| 382 StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type); | |
| 383 m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); | |
| 384 Stream s = m.Build(); | |
| 385 ASSERT_EQ(1U, s.size()); | |
| 386 EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); | |
| 387 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 388 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 389 EXPECT_EQ(kFlags_set, s[0]->flags_mode()); | |
| 390 EXPECT_EQ(cmp.cond, s[0]->flags_condition()); | |
| 391 } | |
| 392 | |
| 393 | |
| 394 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest, | |
| 395 ::testing::ValuesIn(kFPCmpInstructions)); | |
| 396 | |
| 397 | |
| 398 // ----------------------------------------------------------------------------- | |
| 399 // Conversions. | |
| 400 | |
| 401 typedef InstructionSelectorTestWithParam<Conversion> | |
| 402 InstructionSelectorConversionTest; | |
| 403 | |
| 404 | |
| 405 TEST_P(InstructionSelectorConversionTest, Parameter) { | |
| 406 const Conversion conv = GetParam(); | |
| 407 StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); | |
| 408 m.Return((m.*conv.mi.constructor)(m.Parameter(0))); | |
| 409 Stream s = m.Build(); | |
| 410 ASSERT_EQ(1U, s.size()); | |
| 411 EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); | |
| 412 EXPECT_EQ(1U, s[0]->InputCount()); | |
| 413 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 414 } | |
| 415 | |
| 416 | |
| 417 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
| 418 InstructionSelectorConversionTest, | |
| 419 ::testing::ValuesIn(kConversionInstructions)); | |
| 420 | |
| 421 | |
| 422 // ----------------------------------------------------------------------------- | |
| 423 // Memory access instructions. | |
| 424 | |
| 425 | |
| 426 namespace { | |
| 427 | |
| 428 struct MemoryAccess { | |
| 429 MachineType type; | |
| 430 ArchOpcode ldr_opcode; | |
| 431 ArchOpcode str_opcode; | |
| 432 }; | |
| 433 | |
| 434 | |
| 435 std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { | |
| 436 OStringStream ost; | |
| 437 ost << memacc.type; | |
| 438 return os << ost.c_str(); | |
| 439 } | |
| 440 | |
| 441 } // namespace | |
| 442 | |
| 443 | |
| 444 static const MemoryAccess kMemoryAccesses[] = { | |
| 445 {kMachInt8, kArm64Ldrsb, kArm64Strb}, | |
| 446 {kMachUint8, kArm64Ldrb, kArm64Strb}, | |
| 447 {kMachInt16, kArm64Ldrsh, kArm64Strh}, | |
| 448 {kMachUint16, kArm64Ldrh, kArm64Strh}, | |
| 449 {kMachInt32, kArm64LdrW, kArm64StrW}, | |
| 450 {kMachUint32, kArm64LdrW, kArm64StrW}, | |
| 451 {kMachInt64, kArm64Ldr, kArm64Str}, | |
| 452 {kMachUint64, kArm64Ldr, kArm64Str}, | |
| 453 {kMachFloat32, kArm64LdrS, kArm64StrS}, | |
| 454 {kMachFloat64, kArm64LdrD, kArm64StrD}}; | |
| 455 | |
| 456 | |
| 457 typedef InstructionSelectorTestWithParam<MemoryAccess> | |
| 458 InstructionSelectorMemoryAccessTest; | |
| 459 | |
| 460 | |
| 461 TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { | |
| 462 const MemoryAccess memacc = GetParam(); | |
| 463 StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32); | |
| 464 m.Return(m.Load(memacc.type, m.Parameter(0), m.Parameter(1))); | |
| 465 Stream s = m.Build(); | |
| 466 ASSERT_EQ(1U, s.size()); | |
| 467 EXPECT_EQ(memacc.ldr_opcode, s[0]->arch_opcode()); | |
| 468 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode()); | |
| 469 EXPECT_EQ(2U, s[0]->InputCount()); | |
| 470 EXPECT_EQ(1U, s[0]->OutputCount()); | |
| 471 } | |
| 472 | |
| 473 | |
| 474 TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { | |
| 475 const MemoryAccess memacc = GetParam(); | |
| 476 StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); | |
| 477 m.Store(memacc.type, m.Parameter(0), m.Parameter(1), m.Parameter(2)); | |
| 478 m.Return(m.Int32Constant(0)); | |
| 479 Stream s = m.Build(); | |
| 480 ASSERT_EQ(1U, s.size()); | |
| 481 EXPECT_EQ(memacc.str_opcode, s[0]->arch_opcode()); | |
| 482 EXPECT_EQ(kMode_MRR, s[0]->addressing_mode()); | |
| 483 EXPECT_EQ(3U, s[0]->InputCount()); | |
| 484 EXPECT_EQ(0U, s[0]->OutputCount()); | |
| 485 } | |
| 486 | |
| 487 | |
| 488 INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, | |
| 489 InstructionSelectorMemoryAccessTest, | |
| 490 ::testing::ValuesIn(kMemoryAccesses)); | |
| 491 | |
| 492 } // namespace compiler | |
| 493 } // namespace internal | |
| 494 } // namespace v8 | |
| OLD | NEW |