Index: src/compiler/arm64/instruction-selector-arm64.cc |
diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc |
index 52bd9790c0b2a3a4bc201177b30c0990b5389071..26e9b8cad9010594ca22b5308bad624acdf67c35 100644 |
--- a/src/compiler/arm64/instruction-selector-arm64.cc |
+++ b/src/compiler/arm64/instruction-selector-arm64.cc |
@@ -660,8 +660,36 @@ void InstructionSelector::VisitWord64Shl(Node* node) { |
} |
+namespace { |
+ |
+bool TryEmitBitfieldExtract32(InstructionSelector* selector, Node* node) { |
+ Arm64OperandGenerator g(selector); |
+ Int32BinopMatcher m(node); |
+ if (selector->CanCover(node, m.left().node()) && m.left().IsWord32Shl()) { |
+ // Select Ubfx or Sbfx for (x << (K & 0x1f)) OP (K & 0x1f), where |
+ // OP is >>> or >> and (K & 0x1f) != 0. |
+ Int32BinopMatcher mleft(m.left().node()); |
+ if (mleft.right().HasValue() && m.right().HasValue() && |
+ (mleft.right().Value() & 0x1f) == (m.right().Value() & 0x1f)) { |
+ DCHECK(m.IsWord32Shr() || m.IsWord32Sar()); |
+ ArchOpcode opcode = m.IsWord32Sar() ? kArm64Sbfx32 : kArm64Ubfx32; |
+ |
+ int right_val = m.right().Value() & 0x1f; |
+ DCHECK_NE(right_val, 0); |
+ |
+ selector->Emit(opcode, g.DefineAsRegister(node), |
+ g.UseRegister(mleft.left().node()), g.TempImmediate(0), |
+ g.TempImmediate(32 - right_val)); |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+} // namespace |
+ |
+ |
void InstructionSelector::VisitWord32Shr(Node* node) { |
- Arm64OperandGenerator g(this); |
Int32BinopMatcher m(node); |
if (m.left().IsWord32And() && m.right().IsInRange(0, 31)) { |
uint32_t lsb = m.right().Value(); |
@@ -673,6 +701,7 @@ void InstructionSelector::VisitWord32Shr(Node* node) { |
// Select Ubfx for Shr(And(x, mask), imm) where the result of the mask is |
// shifted into the least-significant bits. |
if ((mask_msb + mask_width + lsb) == 32) { |
+ Arm64OperandGenerator g(this); |
DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(mask)); |
Emit(kArm64Ubfx32, g.DefineAsRegister(node), |
g.UseRegister(mleft.left().node()), g.TempImmediate(lsb), |
@@ -680,6 +709,8 @@ void InstructionSelector::VisitWord32Shr(Node* node) { |
return; |
} |
} |
+ } else if (TryEmitBitfieldExtract32(this, node)) { |
+ return; |
} |
VisitRRO(this, kArm64Lsr32, node, kShift32Imm); |
} |
@@ -711,20 +742,8 @@ void InstructionSelector::VisitWord64Shr(Node* node) { |
void InstructionSelector::VisitWord32Sar(Node* node) { |
- Arm64OperandGenerator g(this); |
- Int32BinopMatcher m(node); |
- // Select Sxth/Sxtb for (x << K) >> K where K is 16 or 24. |
- if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) { |
- Int32BinopMatcher mleft(m.left().node()); |
- if (mleft.right().Is(16) && m.right().Is(16)) { |
- Emit(kArm64Sxth32, g.DefineAsRegister(node), |
- g.UseRegister(mleft.left().node())); |
- return; |
- } else if (mleft.right().Is(24) && m.right().Is(24)) { |
- Emit(kArm64Sxtb32, g.DefineAsRegister(node), |
- g.UseRegister(mleft.left().node())); |
- return; |
- } |
+ if (TryEmitBitfieldExtract32(this, node)) { |
+ return; |
} |
VisitRRO(this, kArm64Asr32, node, kShift32Imm); |
} |