summaryrefslogtreecommitdiff
path: root/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc')
-rw-r--r--deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc218
1 files changed, 143 insertions, 75 deletions
diff --git a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
index 6ca5e5e684..7892c4bbb9 100644
--- a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
@@ -402,7 +402,6 @@ TEST_P(InstructionSelectorLogicalTest, Parameter) {
TEST_P(InstructionSelectorLogicalTest, Immediate) {
const MachInst2 dpi = GetParam();
const MachineType type = dpi.machine_type;
- // TODO(all): Add support for testing 64-bit immediates.
if (type == MachineType::Int32()) {
// Immediate on the right.
TRACED_FOREACH(int32_t, imm, kLogical32Immediates) {
@@ -429,6 +428,32 @@ TEST_P(InstructionSelectorLogicalTest, Immediate) {
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
EXPECT_EQ(1U, s[0]->OutputCount());
}
+ } else if (type == MachineType::Int64()) {
+ // Immediate on the right.
+ TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
+ StreamBuilder m(this, type, type);
+ m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int64Constant(imm)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
+ EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
+
+ // Immediate on the left; all logical ops should commute.
+ TRACED_FOREACH(int64_t, imm, kLogical64Immediates) {
+ StreamBuilder m(this, type, type);
+ m.Return((m.*dpi.constructor)(m.Int64Constant(imm), m.Parameter(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate());
+ EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(1)));
+ EXPECT_EQ(1U, s[0]->OutputCount());
+ }
}
}
@@ -1067,7 +1092,8 @@ TEST_F(InstructionSelectorTest, SubBranchWithImmediateOnRight) {
m.Return(m.Int32Constant(0));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ((imm == 0) ? kArm64CompareAndBranch32 : kArm64Cmp32,
+ s[0]->arch_opcode());
EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
EXPECT_EQ(kNotEqual, s[0]->flags_condition());
}
@@ -3142,11 +3168,20 @@ const IntegerCmp kIntegerCmpInstructions[] = {
kUnsignedLessThanOrEqual,
kUnsignedGreaterThanOrEqual}};
+const IntegerCmp kIntegerCmpEqualityInstructions[] = {
+ {{&RawMachineAssembler::Word32Equal, "Word32Equal", kArm64Cmp32,
+ MachineType::Int32()},
+ kEqual,
+ kEqual},
+ {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kArm64Cmp32,
+ MachineType::Int32()},
+ kNotEqual,
+ kNotEqual}};
} // namespace
TEST_F(InstructionSelectorTest, Word32CompareNegateWithWord32Shift) {
- TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+ TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpEqualityInstructions) {
TRACED_FOREACH(Shift, shift, kShiftInstructions) {
// Test 32-bit operations. Ignore ROR shifts, as compare-negate does not
// support them.
@@ -3183,19 +3218,16 @@ TEST_F(InstructionSelectorTest, CmpWithImmediateOnLeft) {
// kEqual and kNotEqual trigger the cbz/cbnz optimization, which
// is tested elsewhere.
if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
+ // For signed less than or equal to zero, we generate TBNZ.
+ if (cmp.cond == kSignedLessThanOrEqual && imm == 0) continue;
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Node* const p0 = m.Parameter(0);
- RawMachineLabel a, b;
- m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), p0), &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return((m.*cmp.mi.constructor)(m.Int32Constant(imm), p0));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Cmp32, s[0]->arch_opcode());
ASSERT_LE(2U, s[0]->InputCount());
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.commuted_cond, s[0]->flags_condition());
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
}
@@ -3203,24 +3235,19 @@ TEST_F(InstructionSelectorTest, CmpWithImmediateOnLeft) {
}
TEST_F(InstructionSelectorTest, CmnWithImmediateOnLeft) {
- TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+ TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpEqualityInstructions) {
TRACED_FOREACH(int32_t, imm, kAddSubImmediates) {
// kEqual and kNotEqual trigger the cbz/cbnz optimization, which
// is tested elsewhere.
if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
- RawMachineLabel a, b;
- m.Branch((m.*cmp.mi.constructor)(m.Int32Constant(imm), sub), &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return((m.*cmp.mi.constructor)(m.Int32Constant(imm), sub));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
EXPECT_EQ(kArm64Cmn32, s[0]->arch_opcode());
ASSERT_LE(2U, s[0]->InputCount());
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1)));
}
@@ -3244,7 +3271,7 @@ TEST_F(InstructionSelectorTest, CmpSignedExtendByteOnLeft) {
}
TEST_F(InstructionSelectorTest, CmnSignedExtendByteOnLeft) {
- TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+ TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpEqualityInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
Node* sub = m.Int32Sub(m.Int32Constant(0), m.Parameter(0));
@@ -3294,7 +3321,7 @@ TEST_F(InstructionSelectorTest, CmpShiftByImmediateOnLeft) {
}
TEST_F(InstructionSelectorTest, CmnShiftByImmediateOnLeft) {
- TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpInstructions) {
+ TRACED_FOREACH(IntegerCmp, cmp, kIntegerCmpEqualityInstructions) {
TRACED_FOREACH(Shift, shift, kShiftInstructions) {
// Only test relevant shifted operands.
if (shift.mi.machine_type != MachineType::Int32()) continue;
@@ -3408,21 +3435,15 @@ TEST_P(InstructionSelectorFlagSettingTest, CmpZeroRight) {
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
- RawMachineLabel a, b;
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
- Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return((m.*cmp.mi.constructor)(binop, m.Int32Constant(0)));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3433,21 +3454,15 @@ TEST_P(InstructionSelectorFlagSettingTest, CmpZeroLeft) {
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroLeftInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
- RawMachineLabel a, b;
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
- Node* comp = (m.*cmp.mi.constructor)(m.Int32Constant(0), binop);
- m.Branch(comp, &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return((m.*cmp.mi.constructor)(m.Int32Constant(0), binop));
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3456,25 +3471,23 @@ TEST_P(InstructionSelectorFlagSettingTest, CmpZeroOnlyUserInBasicBlock) {
const FlagSettingInst inst = GetParam();
// Binop with additional users, but in a different basic block.
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
- // For kEqual and kNotEqual, we generate a cbz or cbnz.
- if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
RawMachineLabel a, b;
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
+ m.Branch(m.Parameter(0), &a, &b);
m.Bind(&a);
m.Return(binop);
m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
- ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s.size()); // Flag-setting instruction and branch.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(inst.mi.arch_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3483,8 +3496,6 @@ TEST_P(InstructionSelectorFlagSettingTest, ShiftedOperand) {
const FlagSettingInst inst = GetParam();
// Like the test above, but with a shifted input to the binary operator.
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
- // For kEqual and kNotEqual, we generate a cbz or cbnz.
- if (cmp.cond == kEqual || cmp.cond == kNotEqual) continue;
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
RawMachineLabel a, b;
@@ -3492,20 +3503,20 @@ TEST_P(InstructionSelectorFlagSettingTest, ShiftedOperand) {
Node* shift = m.Word32Shl(m.Parameter(1), imm);
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), shift);
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
+ m.Branch(m.Parameter(0), &a, &b);
m.Bind(&a);
m.Return(binop);
m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
- ASSERT_EQ(1U, s.size());
- ASSERT_EQ(5U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s.size()); // Flag-setting instruction and branch.
+ ASSERT_EQ(3U, s[0]->InputCount());
EXPECT_EQ(inst.mi.arch_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(s.ToVreg(m.Parameter(1)), s.ToVreg(s[0]->InputAt(1)));
EXPECT_EQ(5, s.ToInt32(s[0]->InputAt(2)));
EXPECT_EQ(kMode_Operand2_R_LSL_I, s[0]->addressing_mode());
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3521,19 +3532,18 @@ TEST_P(InstructionSelectorFlagSettingTest, UsersInSameBasicBlock) {
Node* binop = (m.*inst.mi.constructor)(m.Parameter(0), m.Parameter(1));
Node* mul = m.Int32Mul(m.Parameter(0), binop);
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
+ m.Branch(m.Parameter(0), &a, &b);
m.Bind(&a);
m.Return(mul);
m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
- ASSERT_EQ(3U, s.size());
+ ASSERT_EQ(4U, s.size()); // Includes the compare and branch instruction.
EXPECT_EQ(inst.mi.arch_opcode, s[0]->arch_opcode());
- EXPECT_NE(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode());
EXPECT_EQ(kArm64Mul32, s[1]->arch_opcode());
- EXPECT_EQ(cmp.cond == kEqual ? kArm64CompareAndBranch32 : kArm64Cmp32,
- s[2]->arch_opcode());
- EXPECT_EQ(kFlags_branch, s[2]->flags_mode());
+ EXPECT_EQ(kArm64Cmp32, s[2]->arch_opcode());
+ EXPECT_EQ(kFlags_set, s[2]->flags_mode());
EXPECT_EQ(cmp.cond, s[2]->flags_condition());
}
}
@@ -3543,23 +3553,18 @@ TEST_P(InstructionSelectorFlagSettingTest, CommuteImmediate) {
// Immediate on left hand side of the binary operator.
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
- RawMachineLabel a, b;
// 3 can be an immediate on both arithmetic and logical instructions.
Node* imm = m.Int32Constant(3);
Node* binop = (m.*inst.mi.constructor)(imm, m.Parameter(0));
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(inst.no_output_opcode, s[0]->arch_opcode());
EXPECT_EQ(s.ToVreg(m.Parameter(0)), s.ToVreg(s[0]->InputAt(0)));
EXPECT_EQ(3, s.ToInt32(s[0]->InputAt(1)));
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -3606,23 +3611,18 @@ TEST_F(InstructionSelectorTest, TstInvalidImmediate) {
// Make sure we do not generate an invalid immediate for TST.
TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
- RawMachineLabel a, b;
// 5 is not a valid constant for TST.
Node* imm = m.Int32Constant(5);
Node* binop = m.Word32And(imm, m.Parameter(0));
Node* comp = (m.*cmp.mi.constructor)(binop, m.Int32Constant(0));
- m.Branch(comp, &a, &b);
- m.Bind(&a);
- m.Return(m.Int32Constant(1));
- m.Bind(&b);
- m.Return(m.Int32Constant(0));
+ m.Return(comp);
Stream s = m.Build();
ASSERT_EQ(1U, s.size());
- ASSERT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ ASSERT_EQ(2U, s[0]->InputCount());
EXPECT_EQ(kArm64Tst32, s[0]->arch_opcode());
EXPECT_NE(InstructionOperand::IMMEDIATE, s[0]->InputAt(0)->kind());
EXPECT_NE(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
- EXPECT_EQ(kFlags_branch, s[0]->flags_mode());
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
EXPECT_EQ(cmp.cond, s[0]->flags_condition());
}
}
@@ -4311,6 +4311,74 @@ TEST_F(InstructionSelectorTest, LoadAndShiftRight) {
}
}
+TEST_F(InstructionSelectorTest, CompareAgainstZero32) {
+ TRACED_FOREACH(IntegerCmp, cmp, kBinopCmpZeroRightInstructions) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
+ Node* const param = m.Parameter(0);
+ RawMachineLabel a, b;
+ m.Branch((m.*cmp.mi.constructor)(param, m.Int32Constant(0)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(s.ToVreg(param), s.ToVreg(s[0]->InputAt(0)));
+ if (cmp.cond == kNegative || cmp.cond == kPositiveOrZero) {
+ EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
+ EXPECT_EQ(4U, s[0]->InputCount()); // The labels are also inputs.
+ EXPECT_EQ((cmp.cond == kNegative) ? kNotEqual : kEqual,
+ s[0]->flags_condition());
+ EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
+ EXPECT_EQ(31, s.ToInt32(s[0]->InputAt(1)));
+ } else {
+ EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
+ EXPECT_EQ(3U, s[0]->InputCount()); // The labels are also inputs.
+ EXPECT_EQ(cmp.cond, s[0]->flags_condition());
+ }
+ }
+}
+
+TEST_F(InstructionSelectorTest, CompareFloat64HighLessThanZero64) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
+ Node* const param = m.Parameter(0);
+ Node* const high = m.Float64ExtractHighWord32(param);
+ RawMachineLabel a, b;
+ m.Branch(m.Int32LessThan(high, m.Int32Constant(0)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64U64MoveFloat64, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64TestAndBranch, s[1]->arch_opcode());
+ EXPECT_EQ(kNotEqual, s[1]->flags_condition());
+ EXPECT_EQ(4U, s[1]->InputCount());
+ EXPECT_EQ(InstructionOperand::IMMEDIATE, s[1]->InputAt(1)->kind());
+ EXPECT_EQ(63, s.ToInt32(s[1]->InputAt(1)));
+}
+
+TEST_F(InstructionSelectorTest, CompareFloat64HighGreaterThanOrEqualZero64) {
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Float64());
+ Node* const param = m.Parameter(0);
+ Node* const high = m.Float64ExtractHighWord32(param);
+ RawMachineLabel a, b;
+ m.Branch(m.Int32GreaterThanOrEqual(high, m.Int32Constant(0)), &a, &b);
+ m.Bind(&a);
+ m.Return(m.Int32Constant(1));
+ m.Bind(&b);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build();
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArm64U64MoveFloat64, s[0]->arch_opcode());
+ EXPECT_EQ(kArm64TestAndBranch, s[1]->arch_opcode());
+ EXPECT_EQ(kEqual, s[1]->flags_condition());
+ EXPECT_EQ(4U, s[1]->InputCount());
+ EXPECT_EQ(InstructionOperand::IMMEDIATE, s[1]->InputAt(1)->kind());
+ EXPECT_EQ(63, s.ToInt32(s[1]->InputAt(1)));
+}
+
} // namespace compiler
} // namespace internal
} // namespace v8