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