| 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); | 
| } | 
|  |