| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/base/bits.h" | 5 #include "src/base/bits.h" |
| 6 #include "src/compiler/instruction-selector-impl.h" | 6 #include "src/compiler/instruction-selector-impl.h" |
| 7 #include "src/compiler/node-matchers.h" | 7 #include "src/compiler/node-matchers.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) { | 361 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) { |
| 362 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), | 362 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), |
| 363 value_operand, shift_operand); | 363 value_operand, shift_operand); |
| 364 return; | 364 return; |
| 365 } | 365 } |
| 366 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), | 366 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), |
| 367 g.DefineAsRegister(node), g.UseRegister(left), | 367 g.DefineAsRegister(node), g.UseRegister(left), |
| 368 g.UseRegister(right)); | 368 g.UseRegister(right)); |
| 369 } | 369 } |
| 370 | 370 |
| 371 |
| 372 void EmitUbfx(InstructionSelector* selector, Node* node, Node* left, |
| 373 uint32_t lsb, uint32_t width) { |
| 374 DCHECK_LE(1, width); |
| 375 DCHECK_LE(width, 32 - lsb); |
| 376 ArmOperandGenerator g(selector); |
| 377 selector->Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(left), |
| 378 g.TempImmediate(lsb), g.TempImmediate(width)); |
| 379 } |
| 380 |
| 371 } // namespace | 381 } // namespace |
| 372 | 382 |
| 373 | 383 |
| 374 void InstructionSelector::VisitWord32And(Node* node) { | 384 void InstructionSelector::VisitWord32And(Node* node) { |
| 375 ArmOperandGenerator g(this); | 385 ArmOperandGenerator g(this); |
| 376 Int32BinopMatcher m(node); | 386 Int32BinopMatcher m(node); |
| 377 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) { | 387 if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) { |
| 378 Int32BinopMatcher mleft(m.left().node()); | 388 Int32BinopMatcher mleft(m.left().node()); |
| 379 if (mleft.right().Is(-1)) { | 389 if (mleft.right().Is(-1)) { |
| 380 EmitBic(this, node, m.right().node(), mleft.left().node()); | 390 EmitBic(this, node, m.right().node(), mleft.left().node()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 391 if (m.right().HasValue()) { | 401 if (m.right().HasValue()) { |
| 392 uint32_t const value = m.right().Value(); | 402 uint32_t const value = m.right().Value(); |
| 393 uint32_t width = base::bits::CountPopulation32(value); | 403 uint32_t width = base::bits::CountPopulation32(value); |
| 394 uint32_t msb = base::bits::CountLeadingZeros32(value); | 404 uint32_t msb = base::bits::CountLeadingZeros32(value); |
| 395 // Try to interpret this AND as UBFX. | 405 // Try to interpret this AND as UBFX. |
| 396 if (IsSupported(ARMv7) && width != 0 && msb + width == 32) { | 406 if (IsSupported(ARMv7) && width != 0 && msb + width == 32) { |
| 397 DCHECK_EQ(0, base::bits::CountTrailingZeros32(value)); | 407 DCHECK_EQ(0, base::bits::CountTrailingZeros32(value)); |
| 398 if (m.left().IsWord32Shr()) { | 408 if (m.left().IsWord32Shr()) { |
| 399 Int32BinopMatcher mleft(m.left().node()); | 409 Int32BinopMatcher mleft(m.left().node()); |
| 400 if (mleft.right().IsInRange(0, 31)) { | 410 if (mleft.right().IsInRange(0, 31)) { |
| 401 Emit(kArmUbfx, g.DefineAsRegister(node), | 411 // UBFX cannot extract bits past the register size, however since |
| 402 g.UseRegister(mleft.left().node()), | 412 // shifting the original value would have introduced some zeros we can |
| 403 g.UseImmediate(mleft.right().node()), g.TempImmediate(width)); | 413 // still use UBFX with a smaller mask and the remaining bits will be |
| 404 return; | 414 // zeros. |
| 415 uint32_t const lsb = mleft.right().Value(); |
| 416 return EmitUbfx(this, node, mleft.left().node(), lsb, |
| 417 std::min(width, 32 - lsb)); |
| 405 } | 418 } |
| 406 } | 419 } |
| 407 Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 420 return EmitUbfx(this, node, m.left().node(), 0, width); |
| 408 g.TempImmediate(0), g.TempImmediate(width)); | |
| 409 return; | |
| 410 } | 421 } |
| 411 // Try to interpret this AND as BIC. | 422 // Try to interpret this AND as BIC. |
| 412 if (g.CanBeImmediate(~value)) { | 423 if (g.CanBeImmediate(~value)) { |
| 413 Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), | 424 Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I), |
| 414 g.DefineAsRegister(node), g.UseRegister(m.left().node()), | 425 g.DefineAsRegister(node), g.UseRegister(m.left().node()), |
| 415 g.TempImmediate(~value)); | 426 g.TempImmediate(~value)); |
| 416 return; | 427 return; |
| 417 } | 428 } |
| 418 // Try to interpret this AND as UXTH. | 429 // Try to interpret this AND as UXTH. |
| 419 if (value == 0xffff) { | 430 if (value == 0xffff) { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 if (IsSupported(ARMv7) && m.left().IsWord32And() && | 527 if (IsSupported(ARMv7) && m.left().IsWord32And() && |
| 517 m.right().IsInRange(0, 31)) { | 528 m.right().IsInRange(0, 31)) { |
| 518 int32_t lsb = m.right().Value(); | 529 int32_t lsb = m.right().Value(); |
| 519 Int32BinopMatcher mleft(m.left().node()); | 530 Int32BinopMatcher mleft(m.left().node()); |
| 520 if (mleft.right().HasValue()) { | 531 if (mleft.right().HasValue()) { |
| 521 uint32_t value = (mleft.right().Value() >> lsb) << lsb; | 532 uint32_t value = (mleft.right().Value() >> lsb) << lsb; |
| 522 uint32_t width = base::bits::CountPopulation32(value); | 533 uint32_t width = base::bits::CountPopulation32(value); |
| 523 uint32_t msb = base::bits::CountLeadingZeros32(value); | 534 uint32_t msb = base::bits::CountLeadingZeros32(value); |
| 524 if (msb + width + lsb == 32) { | 535 if (msb + width + lsb == 32) { |
| 525 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value)); | 536 DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value)); |
| 526 Emit(kArmUbfx, g.DefineAsRegister(node), | 537 return EmitUbfx(this, node, mleft.left().node(), lsb, width); |
| 527 g.UseRegister(mleft.left().node()), g.TempImmediate(lsb), | |
| 528 g.TempImmediate(width)); | |
| 529 return; | |
| 530 } | 538 } |
| 531 } | 539 } |
| 532 } | 540 } |
| 533 VisitShift(this, node, TryMatchLSR); | 541 VisitShift(this, node, TryMatchLSR); |
| 534 } | 542 } |
| 535 | 543 |
| 536 | 544 |
| 537 void InstructionSelector::VisitWord32Sar(Node* node) { | 545 void InstructionSelector::VisitWord32Sar(Node* node) { |
| 538 ArmOperandGenerator g(this); | 546 ArmOperandGenerator g(this); |
| 539 Int32BinopMatcher m(node); | 547 Int32BinopMatcher m(node); |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 MachineOperatorBuilder::kFloat64Ceil | | 1264 MachineOperatorBuilder::kFloat64Ceil | |
| 1257 MachineOperatorBuilder::kFloat64RoundTruncate | | 1265 MachineOperatorBuilder::kFloat64RoundTruncate | |
| 1258 MachineOperatorBuilder::kFloat64RoundTiesAway; | 1266 MachineOperatorBuilder::kFloat64RoundTiesAway; |
| 1259 } | 1267 } |
| 1260 return flags; | 1268 return flags; |
| 1261 } | 1269 } |
| 1262 | 1270 |
| 1263 } // namespace compiler | 1271 } // namespace compiler |
| 1264 } // namespace internal | 1272 } // namespace internal |
| 1265 } // namespace v8 | 1273 } // namespace v8 |
| OLD | NEW |