[x86] Fix register constraints for multiply-high.
authorbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 24 Oct 2014 09:36:40 +0000 (09:36 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 24 Oct 2014 09:36:40 +0000 (09:36 +0000)
TEST=mjsunit/compiler,unittests
R=titzer@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24862 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/compiler/ia32/instruction-selector-ia32.cc
src/compiler/instruction.h
src/compiler/x64/instruction-selector-x64.cc
test/mjsunit/compiler/regress-register-allocator.js [new file with mode: 0644]
test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
test/unittests/compiler/instruction-selector-unittest.cc
test/unittests/compiler/instruction-selector-unittest.h
test/unittests/compiler/x64/instruction-selector-x64-unittest.cc

index b56230f..894794b 100644 (file)
@@ -469,10 +469,9 @@ void InstructionSelector::VisitInt32Mul(Node* node) {
 void InstructionSelector::VisitInt32MulHigh(Node* node) {
   IA32OperandGenerator g(this);
   InstructionOperand* temps[] = {g.TempRegister(eax)};
-  size_t temp_count = arraysize(temps);
   Emit(kIA32ImulHigh, g.DefineAsFixed(node, edx),
-       g.UseFixed(node->InputAt(0), eax), g.UseRegister(node->InputAt(1)),
-       temp_count, temps);
+       g.UseFixed(node->InputAt(0), eax), g.UseUniqueRegister(node->InputAt(1)),
+       arraysize(temps), temps);
 }
 
 
index d3b8a2c..3a82c11 100644 (file)
@@ -257,7 +257,7 @@ class UnallocatedOperand : public InstructionOperand {
   }
 
   // [lifetime]: Only for non-FIXED_SLOT.
-  bool IsUsedAtStart() {
+  bool IsUsedAtStart() const {
     DCHECK(basic_policy() == EXTENDED_POLICY);
     return LifetimeField::decode(value_) == USED_AT_START;
   }
index 230e000..03240c2 100644 (file)
@@ -560,10 +560,9 @@ void InstructionSelector::VisitInt64Mul(Node* node) {
 void InstructionSelector::VisitInt32MulHigh(Node* node) {
   X64OperandGenerator g(this);
   InstructionOperand* temps[] = {g.TempRegister(rax)};
-  size_t temp_count = arraysize(temps);
   Emit(kX64ImulHigh32, g.DefineAsFixed(node, rdx),
-       g.UseFixed(node->InputAt(0), rax), g.UseRegister(node->InputAt(1)),
-       temp_count, temps);
+       g.UseFixed(node->InputAt(0), rax), g.UseUniqueRegister(node->InputAt(1)),
+       arraysize(temps), temps);
 }
 
 
diff --git a/test/mjsunit/compiler/regress-register-allocator.js b/test/mjsunit/compiler/regress-register-allocator.js
new file mode 100644 (file)
index 0000000..08877ee
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function Module(stdlib, foreign, buffer) {
+  "use asm";
+  var HEAP32 = new stdlib.Int32Array(buffer);
+  function g(a) {
+    HEAP32[a] = 9982 * 100;
+    return a;
+  }
+  function f(i1) {
+    i1 = i1 | 0;
+    var i2 = HEAP32[i1 >> 2] | 0;
+    g(i1);
+    L2909: {
+      L2: {
+        if (0) {
+          if (0) break L2;
+          g(i2);
+          break L2909;
+        }
+      }
+      var r = (HEAP32[1] | 0) / 100 | 0;
+      g(r);
+      return r;
+    }
+  }
+  return {f: f};
+}
+
+var f = Module(this, {}, new ArrayBuffer(64 * 1024)).f;
+assertEquals(9982, f(1));
index 2ce7bca..d1a1726 100644 (file)
@@ -593,9 +593,12 @@ TEST_F(InstructionSelectorTest, Int32MulHigh) {
   EXPECT_EQ(kIA32ImulHigh, s[0]->arch_opcode());
   ASSERT_EQ(2U, s[0]->InputCount());
   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), eax));
   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+  EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1)));
   ASSERT_EQ(1U, s[0]->OutputCount());
   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+  EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), edx));
 }
 
 }  // namespace compiler
index 0b58dc0..defc953 100644 (file)
@@ -129,6 +129,24 @@ int InstructionSelectorTest::Stream::ToVreg(const Node* node) const {
 }
 
 
+bool InstructionSelectorTest::Stream::IsFixed(const InstructionOperand* operand,
+                                              Register reg) const {
+  if (!operand->IsUnallocated()) return false;
+  const UnallocatedOperand* unallocated = UnallocatedOperand::cast(operand);
+  if (!unallocated->HasFixedRegisterPolicy()) return false;
+  const int index = Register::ToAllocationIndex(reg);
+  return unallocated->fixed_register_index() == index;
+}
+
+
+bool InstructionSelectorTest::Stream::IsUsedAtStart(
+    const InstructionOperand* operand) const {
+  if (!operand->IsUnallocated()) return false;
+  const UnallocatedOperand* unallocated = UnallocatedOperand::cast(operand);
+  return unallocated->IsUsedAtStart();
+}
+
+
 // -----------------------------------------------------------------------------
 // Return.
 
index ee5f610..4e49862 100644 (file)
@@ -170,6 +170,9 @@ class InstructionSelectorTest : public TestWithContext, public TestWithZone {
 
     int ToVreg(const Node* node) const;
 
+    bool IsFixed(const InstructionOperand* operand, Register reg) const;
+    bool IsUsedAtStart(const InstructionOperand* operand) const;
+
     FrameStateDescriptor* GetFrameStateDescriptor(int deoptimization_id) {
       EXPECT_LT(deoptimization_id, GetFrameStateDescriptorCount());
       return deoptimization_entries_[deoptimization_id];
index 8470818..dddb70c 100644 (file)
@@ -510,9 +510,12 @@ TEST_F(InstructionSelectorTest, Int32MulHigh) {
   EXPECT_EQ(kX64ImulHigh32, s[0]->arch_opcode());
   ASSERT_EQ(2U, s[0]->InputCount());
   EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+  EXPECT_TRUE(s.IsFixed(s[0]->InputAt(0), rax));
   EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+  EXPECT_TRUE(!s.IsUsedAtStart(s[0]->InputAt(1)));
   ASSERT_EQ(1U, s[0]->OutputCount());
   EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output()));
+  EXPECT_TRUE(s.IsFixed(s[0]->OutputAt(0), rdx));
 }
 
 }  // namespace compiler