[arm64][turbofan] Fix add+shr for big shift values.

Arm64 compiles "x +_64 (y >> shift)" into a single instruction if
"shift" is a constant. The code generator expects that "shift" is a
32 bit constant. however, TurboFan can also pass in a 64 bit constant,
which caused a crash in the code generator.

With this CL we cast the constant of TurboFan to an int in the
instruction selector and thereby satisfy the assumption of the code
generator. This should be correct since the code generator anyways cast
the "shift" to an int5 or int6 eventually.

R=v8-arm-ports@googlegroups.com
BUG=v8:5923

Review-Url: https://codereview.chromium.org/2669203005
Cr-Commit-Position: refs/heads/master@{#43036}
This commit is contained in:
ahaas 2017-02-08 03:52:16 -08:00 committed by Commit bot
parent a1bba7fe3b
commit ed6e28d2ad
3 changed files with 38 additions and 11 deletions

View File

@ -436,14 +436,18 @@ void VisitBinop(InstructionSelector* selector, Node* node,
Matcher m_shift(right_node);
inputs[input_count++] = g.UseRegisterOrImmediateZero(left_node);
inputs[input_count++] = g.UseRegister(m_shift.left().node());
inputs[input_count++] = g.UseImmediate(m_shift.right().node());
// We only need at most the last 6 bits of the shift.
inputs[input_count++] =
g.UseImmediate(static_cast<int>(m_shift.right().Value() & 0x3F));
} else if (can_commute && TryMatchAnyShift(selector, node, left_node, &opcode,
!is_add_sub)) {
if (must_commute_cond) cont->Commute();
Matcher m_shift(left_node);
inputs[input_count++] = g.UseRegisterOrImmediateZero(right_node);
inputs[input_count++] = g.UseRegister(m_shift.left().node());
inputs[input_count++] = g.UseImmediate(m_shift.right().node());
// We only need at most the last 6 bits of the shift.
inputs[input_count++] =
g.UseImmediate(static_cast<int>(m_shift.right().Value() & 0x3F));
} else {
inputs[input_count++] = g.UseRegisterOrImmediateZero(left_node);
inputs[input_count++] = g.UseRegister(right_node);

View File

@ -6709,6 +6709,29 @@ TEST(ParentFramePointer) {
CHECK_EQ(1, r.Call(1));
}
#if V8_TARGET_ARCH_64_BIT
TEST(Regression5923) {
{
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Int64());
m.Return(m.Int64Add(
m.Word64Shr(m.Parameter(0), m.Int64Constant(4611686018427387888)),
m.Parameter(0)));
int64_t input = 16;
m.Call(input);
}
{
BufferedRawMachineAssemblerTester<int64_t> m(MachineType::Int64());
m.Return(m.Int64Add(
m.Parameter(0),
m.Word64Shr(m.Parameter(0), m.Int64Constant(4611686018427387888))));
int64_t input = 16;
m.Call(input);
}
}
#endif // V8_TARGET_ARCH_64_BIT
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -745,7 +745,7 @@ TEST_F(InstructionSelectorTest, SubZeroOnLeftWithShift) {
EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(0)));
EXPECT_EQ(shift.mode, s[0]->addressing_mode());
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(0x3f & imm, 0x3f & s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
@ -771,7 +771,7 @@ TEST_F(InstructionSelectorTest, SubZeroOnLeftWithShift) {
EXPECT_TRUE(s[0]->InputAt(0)->IsImmediate());
EXPECT_EQ(0, s.ToInt32(s[0]->InputAt(0)));
EXPECT_EQ(shift.mode, s[0]->addressing_mode());
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(0x3f & imm, 0x3f & s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
@ -835,7 +835,7 @@ TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
EXPECT_EQ(kArm64Add32, s[0]->arch_opcode());
EXPECT_EQ(shift.mode, s[0]->addressing_mode());
EXPECT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
EXPECT_EQ(0x3f & imm, 0x3f & s.ToInt64(s[0]->InputAt(2)));
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
@ -859,7 +859,7 @@ TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) {
EXPECT_EQ(kArm64Add, s[0]->arch_opcode());
EXPECT_EQ(shift.mode, s[0]->addressing_mode());
EXPECT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
EXPECT_EQ(0x3f & imm, 0x3f & s.ToInt64(s[0]->InputAt(2)));
EXPECT_EQ(1U, s[0]->OutputCount());
}
}
@ -2924,7 +2924,7 @@ TEST_F(InstructionSelectorTest, Word32EqualWithWord32Shift) {
ASSERT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(0x3f & imm, 0x3f & s.ToInt32(s[0]->InputAt(2)));
ASSERT_EQ(1U, s[0]->OutputCount());
}
TRACED_FORRANGE(int32_t, imm, -32, 63) {
@ -2941,7 +2941,7 @@ TEST_F(InstructionSelectorTest, Word32EqualWithWord32Shift) {
ASSERT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(0x3f & imm, 0x3f & s.ToInt32(s[0]->InputAt(2)));
ASSERT_EQ(1U, s[0]->OutputCount());
}
}
@ -3203,7 +3203,7 @@ TEST_F(InstructionSelectorTest, Word32CompareNegateWithWord32Shift) {
EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
EXPECT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(shift.mode, s[0]->addressing_mode());
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(0x3f & imm, 0x3f & s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
@ -3311,7 +3311,7 @@ TEST_F(InstructionSelectorTest, CmpShiftByImmediateOnLeft) {
EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
EXPECT_EQ(shift.mode, s[0]->addressing_mode());
EXPECT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
EXPECT_EQ(0x3f & imm, 0x3f & s.ToInt64(s[0]->InputAt(2)));
EXPECT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
@ -3345,7 +3345,7 @@ TEST_F(InstructionSelectorTest, CmnShiftByImmediateOnLeft) {
EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
EXPECT_EQ(shift.mode, s[0]->addressing_mode());
EXPECT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2)));
EXPECT_EQ(0x3f & imm, 0x3f & s.ToInt64(s[0]->InputAt(2)));
EXPECT_EQ(1U, s[0]->OutputCount());
EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());