From 1ef9e2290036e2db7d3c47e4d84f7d33b0102d16 Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Wed, 5 Nov 2014 05:57:56 +0000 Subject: [PATCH] [x64] 64-bit shift left by 32 or more covers sign/zero extend. TEST=unittests R=jarin@chromium.org Review URL: https://codereview.chromium.org/704703002 Cr-Commit-Position: refs/heads/master@{#25123} git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25123 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler/x64/instruction-selector-x64.cc | 11 ++++++ .../x64/instruction-selector-x64-unittest.cc | 42 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/compiler/x64/instruction-selector-x64.cc b/src/compiler/x64/instruction-selector-x64.cc index f927501..c70944b 100644 --- a/src/compiler/x64/instruction-selector-x64.cc +++ b/src/compiler/x64/instruction-selector-x64.cc @@ -320,6 +320,17 @@ void InstructionSelector::VisitWord32Shl(Node* node) { void InstructionSelector::VisitWord64Shl(Node* node) { + X64OperandGenerator g(this); + Int64BinopMatcher m(node); + if ((m.left().IsChangeInt32ToInt64() || m.left().IsChangeUint32ToUint64()) && + m.right().IsInRange(32, 63)) { + // There's no need to sign/zero-extend to 64-bit if we shift out the upper + // 32 bits anyway. + Emit(kX64Shl, g.DefineSameAsFirst(node), + g.UseRegister(m.left().node()->InputAt(0)), + g.UseImmediate(m.right().node())); + return; + } VisitWord64Shift(this, node, kX64Shl); } diff --git a/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc b/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc index fe50ca5..48c074e 100644 --- a/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc +++ b/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc @@ -323,6 +323,48 @@ TEST_F(InstructionSelectorTest, Uint32MulHigh) { EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), rdx)); } + +// ----------------------------------------------------------------------------- +// Word64Shl. + + +TEST_F(InstructionSelectorTest, Word64ShlWithChangeInt32ToInt64) { + TRACED_FORRANGE(int64_t, x, 32, 63) { + StreamBuilder m(this, kMachInt64, kMachInt32); + Node* const p0 = m.Parameter(0); + Node* const n = m.Word64Shl(m.ChangeInt32ToInt64(p0), m.Int64Constant(x)); + m.Return(n); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kX64Shl, s[0]->arch_opcode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); + EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); + } +} + + +TEST_F(InstructionSelectorTest, Word64ShlWithChangeUint32ToUint64) { + TRACED_FORRANGE(int64_t, x, 32, 63) { + StreamBuilder m(this, kMachInt64, kMachUint32); + Node* const p0 = m.Parameter(0); + Node* const n = m.Word64Shl(m.ChangeUint32ToUint64(p0), m.Int64Constant(x)); + m.Return(n); + Stream s = m.Build(); + ASSERT_EQ(1U, s.size()); + EXPECT_EQ(kX64Shl, s[0]->arch_opcode()); + ASSERT_EQ(2U, s[0]->InputCount()); + EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); + EXPECT_EQ(x, s.ToInt32(s[0]->InputAt(1))); + ASSERT_EQ(1U, s[0]->OutputCount()); + EXPECT_TRUE(s.IsSameAsFirst(s[0]->Output())); + EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); + } +} + } // namespace compiler } // namespace internal } // namespace v8 -- 2.7.4