[turbofan] Mark arm64 cbz/cbnz tbz/tbnz instructions as branch instructions.
The instruction selector now selects pseudo instructions: CompareAndBranch or TestAndBranch which are associated with their continuations so that generic code in the code generator will treat them as branch instruction and will be able to apply optimization like avoiding branches when the code can falltrhough. R=bmeurer@chromium.org Review URL: https://codereview.chromium.org/798553002 Cr-Commit-Position: refs/heads/master@{#25773}
This commit is contained in:
parent
8897ab8930
commit
49baecc42b
@ -280,13 +280,6 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode {
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#define ASSEMBLE_BRANCH_TO(target) \
|
|
||||||
do { \
|
|
||||||
bool fallthrough = IsNextInAssemblyOrder(target); \
|
|
||||||
if (!fallthrough) __ B(GetLabel(target)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
// Assembles an instruction after register allocation, producing machine code.
|
// Assembles an instruction after register allocation, producing machine code.
|
||||||
void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
||||||
Arm64OperandConverter i(this, instr);
|
Arm64OperandConverter i(this, instr);
|
||||||
@ -541,29 +534,12 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
|
|||||||
__ Ubfx(i.OutputRegister32(), i.InputRegister32(0), i.InputInt8(1),
|
__ Ubfx(i.OutputRegister32(), i.InputRegister32(0), i.InputInt8(1),
|
||||||
i.InputInt8(2));
|
i.InputInt8(2));
|
||||||
break;
|
break;
|
||||||
case kArm64Tbz:
|
case kArm64TestAndBranch32:
|
||||||
__ Tbz(i.InputRegister64(0), i.InputInt6(1), GetLabel(i.InputRpo(2)));
|
case kArm64TestAndBranch:
|
||||||
ASSEMBLE_BRANCH_TO(i.InputRpo(3));
|
// Pseudo instructions turned into tbz/tbnz in AssembleArchBranch.
|
||||||
break;
|
break;
|
||||||
case kArm64Tbz32:
|
case kArm64CompareAndBranch32:
|
||||||
__ Tbz(i.InputRegister32(0), i.InputInt5(1), GetLabel(i.InputRpo(2)));
|
// Pseudo instruction turned into cbz/cbnz in AssembleArchBranch.
|
||||||
ASSEMBLE_BRANCH_TO(i.InputRpo(3));
|
|
||||||
break;
|
|
||||||
case kArm64Tbnz:
|
|
||||||
__ Tbnz(i.InputRegister64(0), i.InputInt6(1), GetLabel(i.InputRpo(2)));
|
|
||||||
ASSEMBLE_BRANCH_TO(i.InputRpo(3));
|
|
||||||
break;
|
|
||||||
case kArm64Tbnz32:
|
|
||||||
__ Tbnz(i.InputRegister32(0), i.InputInt5(1), GetLabel(i.InputRpo(2)));
|
|
||||||
ASSEMBLE_BRANCH_TO(i.InputRpo(3));
|
|
||||||
break;
|
|
||||||
case kArm64Cbz32:
|
|
||||||
__ Cbz(i.InputRegister32(0), GetLabel(i.InputRpo(1)));
|
|
||||||
ASSEMBLE_BRANCH_TO(i.InputRpo(2));
|
|
||||||
break;
|
|
||||||
case kArm64Cbnz32:
|
|
||||||
__ Cbnz(i.InputRegister32(0), GetLabel(i.InputRpo(1)));
|
|
||||||
ASSEMBLE_BRANCH_TO(i.InputRpo(2));
|
|
||||||
break;
|
break;
|
||||||
case kArm64Claim: {
|
case kArm64Claim: {
|
||||||
int words = MiscField::decode(instr->opcode());
|
int words = MiscField::decode(instr->opcode());
|
||||||
@ -766,61 +742,99 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
|||||||
Arm64OperandConverter i(this, instr);
|
Arm64OperandConverter i(this, instr);
|
||||||
Label* tlabel = branch->true_label;
|
Label* tlabel = branch->true_label;
|
||||||
Label* flabel = branch->false_label;
|
Label* flabel = branch->false_label;
|
||||||
switch (branch->condition) {
|
FlagsCondition condition = branch->condition;
|
||||||
case kUnorderedEqual:
|
ArchOpcode opcode = instr->arch_opcode();
|
||||||
__ B(vs, flabel);
|
|
||||||
// Fall through.
|
if (opcode == kArm64CompareAndBranch32) {
|
||||||
case kEqual:
|
switch (condition) {
|
||||||
__ B(eq, tlabel);
|
case kEqual:
|
||||||
break;
|
__ Cbz(i.InputRegister32(0), tlabel);
|
||||||
case kUnorderedNotEqual:
|
break;
|
||||||
__ B(vs, tlabel);
|
case kNotEqual:
|
||||||
// Fall through.
|
__ Cbnz(i.InputRegister32(0), tlabel);
|
||||||
case kNotEqual:
|
break;
|
||||||
__ B(ne, tlabel);
|
default:
|
||||||
break;
|
UNREACHABLE();
|
||||||
case kSignedLessThan:
|
}
|
||||||
__ B(lt, tlabel);
|
} else if (opcode == kArm64TestAndBranch32) {
|
||||||
break;
|
switch (condition) {
|
||||||
case kSignedGreaterThanOrEqual:
|
case kEqual:
|
||||||
__ B(ge, tlabel);
|
__ Tbz(i.InputRegister32(0), i.InputInt5(1), tlabel);
|
||||||
break;
|
break;
|
||||||
case kSignedLessThanOrEqual:
|
case kNotEqual:
|
||||||
__ B(le, tlabel);
|
__ Tbnz(i.InputRegister32(0), i.InputInt5(1), tlabel);
|
||||||
break;
|
break;
|
||||||
case kSignedGreaterThan:
|
default:
|
||||||
__ B(gt, tlabel);
|
UNREACHABLE();
|
||||||
break;
|
}
|
||||||
case kUnorderedLessThan:
|
} else if (opcode == kArm64TestAndBranch) {
|
||||||
__ B(vs, flabel);
|
switch (condition) {
|
||||||
// Fall through.
|
case kEqual:
|
||||||
case kUnsignedLessThan:
|
__ Tbz(i.InputRegister64(0), i.InputInt6(1), tlabel);
|
||||||
__ B(lo, tlabel);
|
break;
|
||||||
break;
|
case kNotEqual:
|
||||||
case kUnorderedGreaterThanOrEqual:
|
__ Tbnz(i.InputRegister64(0), i.InputInt6(1), tlabel);
|
||||||
__ B(vs, tlabel);
|
break;
|
||||||
// Fall through.
|
default:
|
||||||
case kUnsignedGreaterThanOrEqual:
|
UNREACHABLE();
|
||||||
__ B(hs, tlabel);
|
}
|
||||||
break;
|
} else {
|
||||||
case kUnorderedLessThanOrEqual:
|
switch (condition) {
|
||||||
__ B(vs, flabel);
|
case kUnorderedEqual:
|
||||||
// Fall through.
|
__ B(vs, flabel);
|
||||||
case kUnsignedLessThanOrEqual:
|
// Fall through.
|
||||||
__ B(ls, tlabel);
|
case kEqual:
|
||||||
break;
|
__ B(eq, tlabel);
|
||||||
case kUnorderedGreaterThan:
|
break;
|
||||||
__ B(vs, tlabel);
|
case kUnorderedNotEqual:
|
||||||
// Fall through.
|
__ B(vs, tlabel);
|
||||||
case kUnsignedGreaterThan:
|
// Fall through.
|
||||||
__ B(hi, tlabel);
|
case kNotEqual:
|
||||||
break;
|
__ B(ne, tlabel);
|
||||||
case kOverflow:
|
break;
|
||||||
__ B(vs, tlabel);
|
case kSignedLessThan:
|
||||||
break;
|
__ B(lt, tlabel);
|
||||||
case kNotOverflow:
|
break;
|
||||||
__ B(vc, tlabel);
|
case kSignedGreaterThanOrEqual:
|
||||||
break;
|
__ B(ge, tlabel);
|
||||||
|
break;
|
||||||
|
case kSignedLessThanOrEqual:
|
||||||
|
__ B(le, tlabel);
|
||||||
|
break;
|
||||||
|
case kSignedGreaterThan:
|
||||||
|
__ B(gt, tlabel);
|
||||||
|
break;
|
||||||
|
case kUnorderedLessThan:
|
||||||
|
__ B(vs, flabel);
|
||||||
|
// Fall through.
|
||||||
|
case kUnsignedLessThan:
|
||||||
|
__ B(lo, tlabel);
|
||||||
|
break;
|
||||||
|
case kUnorderedGreaterThanOrEqual:
|
||||||
|
__ B(vs, tlabel);
|
||||||
|
// Fall through.
|
||||||
|
case kUnsignedGreaterThanOrEqual:
|
||||||
|
__ B(hs, tlabel);
|
||||||
|
break;
|
||||||
|
case kUnorderedLessThanOrEqual:
|
||||||
|
__ B(vs, flabel);
|
||||||
|
// Fall through.
|
||||||
|
case kUnsignedLessThanOrEqual:
|
||||||
|
__ B(ls, tlabel);
|
||||||
|
break;
|
||||||
|
case kUnorderedGreaterThan:
|
||||||
|
__ B(vs, tlabel);
|
||||||
|
// Fall through.
|
||||||
|
case kUnsignedGreaterThan:
|
||||||
|
__ B(hi, tlabel);
|
||||||
|
break;
|
||||||
|
case kOverflow:
|
||||||
|
__ B(vs, tlabel);
|
||||||
|
break;
|
||||||
|
case kNotOverflow:
|
||||||
|
__ B(vc, tlabel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!branch->fallthru) __ B(flabel); // no fallthru to flabel.
|
if (!branch->fallthru) __ B(flabel); // no fallthru to flabel.
|
||||||
}
|
}
|
||||||
|
@ -70,12 +70,9 @@ namespace compiler {
|
|||||||
V(Arm64Sxtw) \
|
V(Arm64Sxtw) \
|
||||||
V(Arm64Ubfx) \
|
V(Arm64Ubfx) \
|
||||||
V(Arm64Ubfx32) \
|
V(Arm64Ubfx32) \
|
||||||
V(Arm64Tbz) \
|
V(Arm64TestAndBranch32) \
|
||||||
V(Arm64Tbz32) \
|
V(Arm64TestAndBranch) \
|
||||||
V(Arm64Tbnz) \
|
V(Arm64CompareAndBranch32) \
|
||||||
V(Arm64Tbnz32) \
|
|
||||||
V(Arm64Cbz32) \
|
|
||||||
V(Arm64Cbnz32) \
|
|
||||||
V(Arm64Claim) \
|
V(Arm64Claim) \
|
||||||
V(Arm64Poke) \
|
V(Arm64Poke) \
|
||||||
V(Arm64PokePairZero) \
|
V(Arm64PokePairZero) \
|
||||||
|
@ -1347,9 +1347,8 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
|
|||||||
// If the mask has only one bit set, we can use tbz/tbnz.
|
// If the mask has only one bit set, we can use tbz/tbnz.
|
||||||
DCHECK((cont.condition() == kEqual) ||
|
DCHECK((cont.condition() == kEqual) ||
|
||||||
(cont.condition() == kNotEqual));
|
(cont.condition() == kNotEqual));
|
||||||
ArchOpcode opcode =
|
Emit(cont.Encode(kArm64TestAndBranch32), NULL,
|
||||||
(cont.condition() == kEqual) ? kArm64Tbz32 : kArm64Tbnz32;
|
g.UseRegister(m.left().node()),
|
||||||
Emit(opcode, NULL, g.UseRegister(m.left().node()),
|
|
||||||
g.TempImmediate(
|
g.TempImmediate(
|
||||||
base::bits::CountTrailingZeros32(m.right().Value())),
|
base::bits::CountTrailingZeros32(m.right().Value())),
|
||||||
g.Label(cont.true_block()),
|
g.Label(cont.true_block()),
|
||||||
@ -1366,9 +1365,8 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
|
|||||||
// If the mask has only one bit set, we can use tbz/tbnz.
|
// If the mask has only one bit set, we can use tbz/tbnz.
|
||||||
DCHECK((cont.condition() == kEqual) ||
|
DCHECK((cont.condition() == kEqual) ||
|
||||||
(cont.condition() == kNotEqual));
|
(cont.condition() == kNotEqual));
|
||||||
ArchOpcode opcode =
|
Emit(cont.Encode(kArm64TestAndBranch), NULL,
|
||||||
(cont.condition() == kEqual) ? kArm64Tbz : kArm64Tbnz;
|
g.UseRegister(m.left().node()),
|
||||||
Emit(opcode, NULL, g.UseRegister(m.left().node()),
|
|
||||||
g.TempImmediate(
|
g.TempImmediate(
|
||||||
base::bits::CountTrailingZeros64(m.right().Value())),
|
base::bits::CountTrailingZeros64(m.right().Value())),
|
||||||
g.Label(cont.true_block()),
|
g.Label(cont.true_block()),
|
||||||
@ -1384,9 +1382,8 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Branch could not be combined with a compare, compare against 0 and branch.
|
// Branch could not be combined with a compare, compare against 0 and branch.
|
||||||
DCHECK((cont.condition() == kEqual) || (cont.condition() == kNotEqual));
|
Emit(cont.Encode(kArm64CompareAndBranch32), NULL, g.UseRegister(value),
|
||||||
ArchOpcode opcode = (cont.condition() == kEqual) ? kArm64Cbz32 : kArm64Cbnz32;
|
g.Label(cont.true_block()),
|
||||||
Emit(opcode, NULL, g.UseRegister(value), g.Label(cont.true_block()),
|
|
||||||
g.Label(cont.false_block()))->MarkAsControl();
|
g.Label(cont.false_block()))->MarkAsControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,7 +808,8 @@ TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Tbnz32, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kNotEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(4U, s[0]->InputCount());
|
EXPECT_EQ(4U, s[0]->InputCount());
|
||||||
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
||||||
EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
|
EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
|
||||||
@ -827,7 +828,8 @@ TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnRight) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Tbz32, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(4U, s[0]->InputCount());
|
EXPECT_EQ(4U, s[0]->InputCount());
|
||||||
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
||||||
EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
|
EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
|
||||||
@ -847,7 +849,8 @@ TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Tbnz32, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kNotEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(4U, s[0]->InputCount());
|
EXPECT_EQ(4U, s[0]->InputCount());
|
||||||
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
||||||
EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
|
EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
|
||||||
@ -866,7 +869,8 @@ TEST_F(InstructionSelectorTest, Word32AndBranchWithOneBitMaskOnLeft) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Tbz32, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64TestAndBranch32, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(4U, s[0]->InputCount());
|
EXPECT_EQ(4U, s[0]->InputCount());
|
||||||
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
||||||
EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
|
EXPECT_EQ(bit, s.ToInt32(s[0]->InputAt(1)));
|
||||||
@ -886,7 +890,8 @@ TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Tbnz, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kNotEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(4U, s[0]->InputCount());
|
EXPECT_EQ(4U, s[0]->InputCount());
|
||||||
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
||||||
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
|
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
|
||||||
@ -905,7 +910,8 @@ TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Tbz, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(4U, s[0]->InputCount());
|
EXPECT_EQ(4U, s[0]->InputCount());
|
||||||
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
||||||
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
|
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
|
||||||
@ -925,7 +931,8 @@ TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Tbnz, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kNotEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(4U, s[0]->InputCount());
|
EXPECT_EQ(4U, s[0]->InputCount());
|
||||||
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
||||||
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
|
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
|
||||||
@ -944,7 +951,8 @@ TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Tbz, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64TestAndBranch, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(4U, s[0]->InputCount());
|
EXPECT_EQ(4U, s[0]->InputCount());
|
||||||
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
EXPECT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind());
|
||||||
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
|
EXPECT_EQ(bit, s.ToInt64(s[0]->InputAt(1)));
|
||||||
@ -964,7 +972,8 @@ TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Cbnz32, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kNotEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(3U, s[0]->InputCount());
|
EXPECT_EQ(3U, s[0]->InputCount());
|
||||||
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
|
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
|
||||||
}
|
}
|
||||||
@ -980,7 +989,8 @@ TEST_F(InstructionSelectorTest, CompareAgainstZeroAndBranch) {
|
|||||||
m.Return(m.Int32Constant(0));
|
m.Return(m.Int32Constant(0));
|
||||||
Stream s = m.Build();
|
Stream s = m.Build();
|
||||||
ASSERT_EQ(1U, s.size());
|
ASSERT_EQ(1U, s.size());
|
||||||
EXPECT_EQ(kArm64Cbz32, s[0]->arch_opcode());
|
EXPECT_EQ(kArm64CompareAndBranch32, s[0]->arch_opcode());
|
||||||
|
EXPECT_EQ(kEqual, s[0]->flags_condition());
|
||||||
EXPECT_EQ(3U, s[0]->InputCount());
|
EXPECT_EQ(3U, s[0]->InputCount());
|
||||||
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
|
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user