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);
}
}
// [lifetime]: Only for non-FIXED_SLOT.
- bool IsUsedAtStart() {
+ bool IsUsedAtStart() const {
DCHECK(basic_policy() == EXTENDED_POLICY);
return LifetimeField::decode(value_) == USED_AT_START;
}
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);
}
--- /dev/null
+// 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));
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
}
+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.
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];
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