Commit 14a5c18c authored by martyn.capewell's avatar martyn.capewell Committed by Commit bot

[turbofan] ARM: Use SBFX in instruction selector.

Support SBFX in the instruction selector for sign-extension patterns like
Sar(Shl(x, a), b), where a and b are immediate values.

BUG=

Review URL: https://codereview.chromium.org/1695293002

Cr-Commit-Position: refs/heads/master@{#34029}
parent 0dfd7bcd
...@@ -672,6 +672,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) { ...@@ -672,6 +672,13 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
DCHECK_EQ(LeaveCC, i.OutputSBit()); DCHECK_EQ(LeaveCC, i.OutputSBit());
break; break;
} }
case kArmSbfx: {
CpuFeatureScope scope(masm(), ARMv7);
__ sbfx(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
i.InputInt8(2));
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
case kArmSxtb: case kArmSxtb:
__ sxtb(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1)); __ sxtb(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1));
DCHECK_EQ(LeaveCC, i.OutputSBit()); DCHECK_EQ(LeaveCC, i.OutputSBit());
......
...@@ -36,6 +36,7 @@ namespace compiler { ...@@ -36,6 +36,7 @@ namespace compiler {
V(ArmMvn) \ V(ArmMvn) \
V(ArmBfc) \ V(ArmBfc) \
V(ArmUbfx) \ V(ArmUbfx) \
V(ArmSbfx) \
V(ArmSxtb) \ V(ArmSxtb) \
V(ArmSxth) \ V(ArmSxth) \
V(ArmSxtab) \ V(ArmSxtab) \
......
...@@ -38,6 +38,7 @@ int InstructionScheduler::GetTargetInstructionFlags( ...@@ -38,6 +38,7 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kArmMvn: case kArmMvn:
case kArmBfc: case kArmBfc:
case kArmUbfx: case kArmUbfx:
case kArmSbfx:
case kArmSxtb: case kArmSxtb:
case kArmSxth: case kArmSxth:
case kArmSxtab: case kArmSxtab:
......
...@@ -733,14 +733,23 @@ void InstructionSelector::VisitWord32Sar(Node* node) { ...@@ -733,14 +733,23 @@ void InstructionSelector::VisitWord32Sar(Node* node) {
Int32BinopMatcher m(node); Int32BinopMatcher m(node);
if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) { if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) {
Int32BinopMatcher mleft(m.left().node()); Int32BinopMatcher mleft(m.left().node());
if (mleft.right().Is(16) && m.right().Is(16)) { if (m.right().HasValue() && mleft.right().HasValue()) {
Emit(kArmSxth, g.DefineAsRegister(node), uint32_t sar = m.right().Value();
g.UseRegister(mleft.left().node()), g.TempImmediate(0)); uint32_t shl = mleft.right().Value();
return; if ((sar == shl) && (sar == 16)) {
} else if (mleft.right().Is(24) && m.right().Is(24)) { Emit(kArmSxth, g.DefineAsRegister(node),
Emit(kArmSxtb, g.DefineAsRegister(node), g.UseRegister(mleft.left().node()), g.TempImmediate(0));
g.UseRegister(mleft.left().node()), g.TempImmediate(0)); return;
return; } else if ((sar == shl) && (sar == 24)) {
Emit(kArmSxtb, g.DefineAsRegister(node),
g.UseRegister(mleft.left().node()), g.TempImmediate(0));
return;
} else if (IsSupported(ARMv7) && (sar >= shl)) {
Emit(kArmSbfx, g.DefineAsRegister(node),
g.UseRegister(mleft.left().node()), g.TempImmediate(sar - shl),
g.TempImmediate(32 - sar));
return;
}
} }
} }
VisitShift(this, node, TryMatchASR); VisitShift(this, node, TryMatchASR);
......
...@@ -2544,6 +2544,25 @@ TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIVAndMLS) { ...@@ -2544,6 +2544,25 @@ TEST_F(InstructionSelectorTest, Uint32ModWithParametersForSUDIVAndMLS) {
} }
TEST_F(InstructionSelectorTest, Word32ShlWord32SarForSbfx) {
TRACED_FORRANGE(int32_t, shl, 1, 31) {
TRACED_FORRANGE(int32_t, sar, shl, 31) {
if ((shl == sar) && (sar == 16)) continue; // Sxth.
if ((shl == sar) && (sar == 24)) continue; // Sxtb.
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
m.Return(m.Word32Sar(m.Word32Shl(m.Parameter(0), m.Int32Constant(shl)),
m.Int32Constant(sar)));
Stream s = m.Build(ARMv7);
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArmSbfx, s[0]->arch_opcode());
ASSERT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(sar - shl, s.ToInt32(s[0]->InputAt(1)));
EXPECT_EQ(32 - sar, s.ToInt32(s[0]->InputAt(2)));
}
}
}
TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) { TEST_F(InstructionSelectorTest, Word32AndWithUbfxImmediateForARMv7) {
TRACED_FORRANGE(int32_t, width, 9, 23) { TRACED_FORRANGE(int32_t, width, 9, 23) {
if (width == 16) continue; // Uxth. if (width == 16) continue; // Uxth.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment