Commit 64a27175 authored by Benedikt Meurer's avatar Benedikt Meurer

[x64] Improve instruction selection for TruncateInt64ToInt32.

R=svenpanne@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#26739}
parent 206e9136
......@@ -812,12 +812,22 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
Node* value = node->InputAt(0);
if (CanCover(node, value)) {
switch (value->opcode()) {
case IrOpcode::kWord64Sar:
case IrOpcode::kWord64Shr: {
case IrOpcode::kWord64Sar: {
Int64BinopMatcher m(value);
if (m.right().Is(32)) {
if (m.right().IsInRange(1, 32)) {
Emit(kX64Shr, g.DefineSameAsFirst(node),
g.UseRegister(m.left().node()), g.TempImmediate(32));
g.UseRegister(m.left().node()),
g.UseImmediate(m.right().node()));
return;
}
break;
}
case IrOpcode::kWord64Shl: {
Int64BinopMatcher m(value);
if (m.right().IsInRange(1, 31)) {
Emit(kX64Shl32, g.DefineSameAsFirst(node),
g.UseRegister(m.left().node()),
g.UseImmediate(m.right().node()));
return;
}
break;
......@@ -826,7 +836,9 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
break;
}
}
Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
// Otherwise truncation from 64-bit to 32-bit is a no-nop, as 32-bit
// operations just ignore the upper 64-bit.
Emit(kArchNop, g.DefineAsRegister(node), g.Use(value));
}
......
......@@ -63,15 +63,6 @@ TEST_F(InstructionSelectorTest, TruncateFloat64ToFloat32WithParameter) {
}
TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithParameter) {
StreamBuilder m(this, kMachInt32, kMachInt64);
m.Return(m.TruncateInt64ToInt32(m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Movl, s[0]->arch_opcode());
}
// -----------------------------------------------------------------------------
// Loads and stores
......@@ -206,37 +197,49 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
// TruncateInt64ToInt32.
TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithParameter) {
StreamBuilder m(this, kMachInt32, kMachInt64);
Node* const p = m.Parameter(0);
Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(32)));
m.Return(t);
m.Return(m.TruncateInt64ToInt32(m.Parameter(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Shr, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(32, s.ToInt32(s[0]->InputAt(1)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
ASSERT_EQ(0U, s.size());
}
TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shr) {
StreamBuilder m(this, kMachInt32, kMachInt64);
Node* const p = m.Parameter(0);
Node* const t = m.TruncateInt64ToInt32(m.Word64Shr(p, m.Int64Constant(32)));
m.Return(t);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Shr, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(32, s.ToInt32(s[0]->InputAt(1)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Sar) {
TRACED_FORRANGE(int32_t, k, 1, 32) {
StreamBuilder m(this, kMachInt32, kMachInt64);
Node* const p = m.Parameter(0);
Node* const t = m.TruncateInt64ToInt32(m.Word64Sar(p, m.Int64Constant(k)));
m.Return(t);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Shr, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(1)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
}
}
TEST_F(InstructionSelectorTest, TruncateInt64ToInt32WithWord64Shl) {
TRACED_FORRANGE(int32_t, k, 1, 31) {
StreamBuilder m(this, kMachInt32, kMachInt64);
Node* const p = m.Parameter(0);
Node* const t = m.TruncateInt64ToInt32(m.Word64Shl(p, m.Int64Constant(k)));
m.Return(t);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kX64Shl32, s[0]->arch_opcode());
ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(s.ToVreg(p), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(k, s.ToInt32(s[0]->InputAt(1)));
ASSERT_EQ(1U, s[0]->OutputCount());
EXPECT_TRUE(s.IsSameAsFirst(s[0]->OutputAt(0)));
EXPECT_EQ(s.ToVreg(t), s.ToVreg(s[0]->OutputAt(0)));
}
}
......
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