[turbofan] Improve code generation for unordered comparisons.
TEST=cctest,unittests Review URL: https://codereview.chromium.org/850653002 Cr-Commit-Position: refs/heads/master@{#26034}
This commit is contained in:
parent
527e19afd5
commit
c24220c0c1
@ -200,6 +200,41 @@ class OutOfLineLoadInteger FINAL : public OutOfLineCode {
|
||||
Register const result_;
|
||||
};
|
||||
|
||||
|
||||
Condition FlagsConditionToCondition(FlagsCondition condition) {
|
||||
switch (condition) {
|
||||
case kEqual:
|
||||
return eq;
|
||||
case kNotEqual:
|
||||
return ne;
|
||||
case kSignedLessThan:
|
||||
return lt;
|
||||
case kSignedGreaterThanOrEqual:
|
||||
return ge;
|
||||
case kSignedLessThanOrEqual:
|
||||
return le;
|
||||
case kSignedGreaterThan:
|
||||
return gt;
|
||||
case kUnsignedLessThan:
|
||||
return lo;
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
return hs;
|
||||
case kUnsignedLessThanOrEqual:
|
||||
return ls;
|
||||
case kUnsignedGreaterThan:
|
||||
return hi;
|
||||
case kOverflow:
|
||||
return vs;
|
||||
case kNotOverflow:
|
||||
return vc;
|
||||
case kUnorderedEqual:
|
||||
case kUnorderedNotEqual:
|
||||
break;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return kNoCondition;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -686,65 +721,8 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
||||
ArmOperandConverter i(this, instr);
|
||||
Label* tlabel = branch->true_label;
|
||||
Label* flabel = branch->false_label;
|
||||
switch (branch->condition) {
|
||||
case kUnorderedEqual:
|
||||
// The "eq" condition will not catch the unordered case.
|
||||
// The jump/fall through to false label will be used if the comparison
|
||||
// was unordered.
|
||||
case kEqual:
|
||||
__ b(eq, tlabel);
|
||||
break;
|
||||
case kUnorderedNotEqual:
|
||||
// Unordered or not equal can be tested with "ne" condtion.
|
||||
// See ARMv7 manual A8.3 - Conditional execution.
|
||||
case kNotEqual:
|
||||
__ b(ne, tlabel);
|
||||
break;
|
||||
case kSignedLessThan:
|
||||
__ b(lt, tlabel);
|
||||
break;
|
||||
case kSignedGreaterThanOrEqual:
|
||||
__ b(ge, tlabel);
|
||||
break;
|
||||
case kSignedLessThanOrEqual:
|
||||
__ b(le, tlabel);
|
||||
break;
|
||||
case kSignedGreaterThan:
|
||||
__ b(gt, tlabel);
|
||||
break;
|
||||
case kUnorderedLessThan:
|
||||
// The "lo" condition will not catch the unordered case.
|
||||
// The jump/fall through to false label will be used if the comparison
|
||||
// was unordered.
|
||||
case kUnsignedLessThan:
|
||||
__ b(lo, tlabel);
|
||||
break;
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
// Unordered, greater than or equal can be tested with "hs" condtion.
|
||||
// See ARMv7 manual A8.3 - Conditional execution.
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
__ b(hs, tlabel);
|
||||
break;
|
||||
case kUnorderedLessThanOrEqual:
|
||||
// The "ls" condition will not catch the unordered case.
|
||||
// The jump/fall through to false label will be used if the comparison
|
||||
// was unordered.
|
||||
case kUnsignedLessThanOrEqual:
|
||||
__ b(ls, tlabel);
|
||||
break;
|
||||
case kUnorderedGreaterThan:
|
||||
// Unordered or greater than can be tested with "hi" condtion.
|
||||
// See ARMv7 manual A8.3 - Conditional execution.
|
||||
case kUnsignedGreaterThan:
|
||||
__ b(hi, tlabel);
|
||||
break;
|
||||
case kOverflow:
|
||||
__ b(vs, tlabel);
|
||||
break;
|
||||
case kNotOverflow:
|
||||
__ b(vc, tlabel);
|
||||
break;
|
||||
}
|
||||
Condition cc = FlagsConditionToCondition(branch->condition);
|
||||
__ b(cc, tlabel);
|
||||
if (!branch->fallthru) __ b(flabel); // no fallthru to flabel.
|
||||
}
|
||||
|
||||
@ -758,86 +736,14 @@ void CodeGenerator::AssembleArchJump(BasicBlock::RpoNumber target) {
|
||||
void CodeGenerator::AssembleArchBoolean(Instruction* instr,
|
||||
FlagsCondition condition) {
|
||||
ArmOperandConverter i(this, instr);
|
||||
Label done;
|
||||
|
||||
// Materialize a full 32-bit 1 or 0 value. The result register is always the
|
||||
// last output of the instruction.
|
||||
Label check;
|
||||
DCHECK_NE(0, instr->OutputCount());
|
||||
Register reg = i.OutputRegister(instr->OutputCount() - 1);
|
||||
Condition cc = kNoCondition;
|
||||
switch (condition) {
|
||||
case kUnorderedEqual:
|
||||
__ b(vc, &check);
|
||||
__ mov(reg, Operand(0));
|
||||
__ b(&done);
|
||||
// Fall through.
|
||||
case kEqual:
|
||||
cc = eq;
|
||||
break;
|
||||
case kUnorderedNotEqual:
|
||||
__ b(vc, &check);
|
||||
__ mov(reg, Operand(1));
|
||||
__ b(&done);
|
||||
// Fall through.
|
||||
case kNotEqual:
|
||||
cc = ne;
|
||||
break;
|
||||
case kSignedLessThan:
|
||||
cc = lt;
|
||||
break;
|
||||
case kSignedGreaterThanOrEqual:
|
||||
cc = ge;
|
||||
break;
|
||||
case kSignedLessThanOrEqual:
|
||||
cc = le;
|
||||
break;
|
||||
case kSignedGreaterThan:
|
||||
cc = gt;
|
||||
break;
|
||||
case kUnorderedLessThan:
|
||||
__ b(vc, &check);
|
||||
__ mov(reg, Operand(0));
|
||||
__ b(&done);
|
||||
// Fall through.
|
||||
case kUnsignedLessThan:
|
||||
cc = lo;
|
||||
break;
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
__ b(vc, &check);
|
||||
__ mov(reg, Operand(1));
|
||||
__ b(&done);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
cc = hs;
|
||||
break;
|
||||
case kUnorderedLessThanOrEqual:
|
||||
__ b(vc, &check);
|
||||
__ mov(reg, Operand(0));
|
||||
__ b(&done);
|
||||
// Fall through.
|
||||
case kUnsignedLessThanOrEqual:
|
||||
cc = ls;
|
||||
break;
|
||||
case kUnorderedGreaterThan:
|
||||
__ b(vc, &check);
|
||||
__ mov(reg, Operand(1));
|
||||
__ b(&done);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThan:
|
||||
cc = hi;
|
||||
break;
|
||||
case kOverflow:
|
||||
cc = vs;
|
||||
break;
|
||||
case kNotOverflow:
|
||||
cc = vc;
|
||||
break;
|
||||
}
|
||||
__ bind(&check);
|
||||
Condition cc = FlagsConditionToCondition(condition);
|
||||
__ mov(reg, Operand(0));
|
||||
__ mov(reg, Operand(1), LeaveCC, cc);
|
||||
__ bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1167,13 +1167,13 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
|
||||
cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
|
||||
return VisitWordCompare(selector, value, cont);
|
||||
case IrOpcode::kFloat64Equal:
|
||||
cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
|
||||
cont->OverwriteAndNegateIfEqual(kEqual);
|
||||
return VisitFloat64Compare(selector, value, cont);
|
||||
case IrOpcode::kFloat64LessThan:
|
||||
cont->OverwriteAndNegateIfEqual(kUnorderedLessThan);
|
||||
cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
|
||||
return VisitFloat64Compare(selector, value, cont);
|
||||
case IrOpcode::kFloat64LessThanOrEqual:
|
||||
cont->OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
|
||||
cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
|
||||
return VisitFloat64Compare(selector, value, cont);
|
||||
case IrOpcode::kProjection:
|
||||
// Check if this is the overflow output projection of an
|
||||
@ -1304,19 +1304,19 @@ void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64Equal(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedEqual, node);
|
||||
FlagsContinuation cont(kEqual, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThan(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedLessThan, node);
|
||||
FlagsContinuation cont(kUnsignedLessThan, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedLessThanOrEqual, node);
|
||||
FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
@ -216,6 +216,41 @@ class OutOfLineLoadZero FINAL : public OutOfLineCode {
|
||||
Register const result_;
|
||||
};
|
||||
|
||||
|
||||
Condition FlagsConditionToCondition(FlagsCondition condition) {
|
||||
switch (condition) {
|
||||
case kEqual:
|
||||
return eq;
|
||||
case kNotEqual:
|
||||
return ne;
|
||||
case kSignedLessThan:
|
||||
return lt;
|
||||
case kSignedGreaterThanOrEqual:
|
||||
return ge;
|
||||
case kSignedLessThanOrEqual:
|
||||
return le;
|
||||
case kSignedGreaterThan:
|
||||
return gt;
|
||||
case kUnsignedLessThan:
|
||||
return lo;
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
return hs;
|
||||
case kUnsignedLessThanOrEqual:
|
||||
return ls;
|
||||
case kUnsignedGreaterThan:
|
||||
return hi;
|
||||
case kOverflow:
|
||||
return vs;
|
||||
case kNotOverflow:
|
||||
return vc;
|
||||
case kUnorderedEqual:
|
||||
case kUnorderedNotEqual:
|
||||
break;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return nv;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
@ -786,65 +821,8 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
} else {
|
||||
switch (condition) {
|
||||
case kUnorderedEqual:
|
||||
// The "eq" condition will not catch the unordered case.
|
||||
// The jump/fall through to false label will be used if the comparison
|
||||
// was unordered.
|
||||
case kEqual:
|
||||
__ B(eq, tlabel);
|
||||
break;
|
||||
case kUnorderedNotEqual:
|
||||
// Unordered or not equal can be tested with "ne" condtion.
|
||||
// See ARMv8 manual C1.2.3 - Condition Code.
|
||||
case kNotEqual:
|
||||
__ B(ne, tlabel);
|
||||
break;
|
||||
case kSignedLessThan:
|
||||
__ B(lt, tlabel);
|
||||
break;
|
||||
case kSignedGreaterThanOrEqual:
|
||||
__ B(ge, tlabel);
|
||||
break;
|
||||
case kSignedLessThanOrEqual:
|
||||
__ B(le, tlabel);
|
||||
break;
|
||||
case kSignedGreaterThan:
|
||||
__ B(gt, tlabel);
|
||||
break;
|
||||
case kUnorderedLessThan:
|
||||
// The "lo" condition will not catch the unordered case.
|
||||
// The jump/fall through to false label will be used if the comparison
|
||||
// was unordered.
|
||||
case kUnsignedLessThan:
|
||||
__ B(lo, tlabel);
|
||||
break;
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
// Unordered, greater than or equal can be tested with "hs" condtion.
|
||||
// See ARMv8 manual C1.2.3 - Condition Code.
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
__ B(hs, tlabel);
|
||||
break;
|
||||
case kUnorderedLessThanOrEqual:
|
||||
// The "ls" condition will not catch the unordered case.
|
||||
// The jump/fall through to false label will be used if the comparison
|
||||
// was unordered.
|
||||
case kUnsignedLessThanOrEqual:
|
||||
__ B(ls, tlabel);
|
||||
break;
|
||||
case kUnorderedGreaterThan:
|
||||
// Unordered or greater than can be tested with "hi" condtion.
|
||||
// See ARMv8 manual C1.2.3 - Condition Code.
|
||||
case kUnsignedGreaterThan:
|
||||
__ B(hi, tlabel);
|
||||
break;
|
||||
case kOverflow:
|
||||
__ B(vs, tlabel);
|
||||
break;
|
||||
case kNotOverflow:
|
||||
__ B(vc, tlabel);
|
||||
break;
|
||||
}
|
||||
Condition cc = FlagsConditionToCondition(condition);
|
||||
__ B(cc, tlabel);
|
||||
}
|
||||
if (!branch->fallthru) __ B(flabel); // no fallthru to flabel.
|
||||
}
|
||||
@ -859,85 +837,13 @@ void CodeGenerator::AssembleArchJump(BasicBlock::RpoNumber target) {
|
||||
void CodeGenerator::AssembleArchBoolean(Instruction* instr,
|
||||
FlagsCondition condition) {
|
||||
Arm64OperandConverter i(this, instr);
|
||||
Label done;
|
||||
|
||||
// Materialize a full 64-bit 1 or 0 value. The result register is always the
|
||||
// last output of the instruction.
|
||||
Label check;
|
||||
DCHECK_NE(0, instr->OutputCount());
|
||||
Register reg = i.OutputRegister(instr->OutputCount() - 1);
|
||||
Condition cc = nv;
|
||||
switch (condition) {
|
||||
case kUnorderedEqual:
|
||||
__ B(vc, &check);
|
||||
__ Mov(reg, 0);
|
||||
__ B(&done);
|
||||
// Fall through.
|
||||
case kEqual:
|
||||
cc = eq;
|
||||
break;
|
||||
case kUnorderedNotEqual:
|
||||
__ B(vc, &check);
|
||||
__ Mov(reg, 1);
|
||||
__ B(&done);
|
||||
// Fall through.
|
||||
case kNotEqual:
|
||||
cc = ne;
|
||||
break;
|
||||
case kSignedLessThan:
|
||||
cc = lt;
|
||||
break;
|
||||
case kSignedGreaterThanOrEqual:
|
||||
cc = ge;
|
||||
break;
|
||||
case kSignedLessThanOrEqual:
|
||||
cc = le;
|
||||
break;
|
||||
case kSignedGreaterThan:
|
||||
cc = gt;
|
||||
break;
|
||||
case kUnorderedLessThan:
|
||||
__ B(vc, &check);
|
||||
__ Mov(reg, 0);
|
||||
__ B(&done);
|
||||
// Fall through.
|
||||
case kUnsignedLessThan:
|
||||
cc = lo;
|
||||
break;
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
__ B(vc, &check);
|
||||
__ Mov(reg, 1);
|
||||
__ B(&done);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
cc = hs;
|
||||
break;
|
||||
case kUnorderedLessThanOrEqual:
|
||||
__ B(vc, &check);
|
||||
__ Mov(reg, 0);
|
||||
__ B(&done);
|
||||
// Fall through.
|
||||
case kUnsignedLessThanOrEqual:
|
||||
cc = ls;
|
||||
break;
|
||||
case kUnorderedGreaterThan:
|
||||
__ B(vc, &check);
|
||||
__ Mov(reg, 1);
|
||||
__ B(&done);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThan:
|
||||
cc = hi;
|
||||
break;
|
||||
case kOverflow:
|
||||
cc = vs;
|
||||
break;
|
||||
case kNotOverflow:
|
||||
cc = vc;
|
||||
break;
|
||||
}
|
||||
__ Bind(&check);
|
||||
Condition cc = FlagsConditionToCondition(condition);
|
||||
__ Cset(reg, cc);
|
||||
__ Bind(&done);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1295,13 +1295,13 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
|
||||
return VisitWordCompare(this, value, kArm64Cmp, &cont, false,
|
||||
kArithmeticImm);
|
||||
case IrOpcode::kFloat64Equal:
|
||||
cont.OverwriteAndNegateIfEqual(kUnorderedEqual);
|
||||
cont.OverwriteAndNegateIfEqual(kEqual);
|
||||
return VisitFloat64Compare(this, value, &cont);
|
||||
case IrOpcode::kFloat64LessThan:
|
||||
cont.OverwriteAndNegateIfEqual(kUnorderedLessThan);
|
||||
cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
|
||||
return VisitFloat64Compare(this, value, &cont);
|
||||
case IrOpcode::kFloat64LessThanOrEqual:
|
||||
cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
|
||||
cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
|
||||
return VisitFloat64Compare(this, value, &cont);
|
||||
case IrOpcode::kProjection:
|
||||
// Check if this is the overflow output projection of an
|
||||
@ -1497,19 +1497,19 @@ void InstructionSelector::VisitUint64LessThan(Node* node) {
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64Equal(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedEqual, node);
|
||||
FlagsContinuation cont(kEqual, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThan(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedLessThan, node);
|
||||
FlagsContinuation cont(kUnsignedLessThan, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedLessThanOrEqual, node);
|
||||
FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
@ -1525,6 +1525,7 @@ InstructionSelector::SupportedMachineOperatorFlags() {
|
||||
MachineOperatorBuilder::kInt32DivIsSafe |
|
||||
MachineOperatorBuilder::kUint32DivIsSafe;
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -731,27 +731,15 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
||||
case kSignedGreaterThan:
|
||||
__ j(greater, tlabel);
|
||||
break;
|
||||
case kUnorderedLessThan:
|
||||
__ j(parity_even, flabel, flabel_distance);
|
||||
// Fall through.
|
||||
case kUnsignedLessThan:
|
||||
__ j(below, tlabel);
|
||||
break;
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
__ j(parity_even, tlabel);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
__ j(above_equal, tlabel);
|
||||
break;
|
||||
case kUnorderedLessThanOrEqual:
|
||||
__ j(parity_even, flabel, flabel_distance);
|
||||
// Fall through.
|
||||
case kUnsignedLessThanOrEqual:
|
||||
__ j(below_equal, tlabel);
|
||||
break;
|
||||
case kUnorderedGreaterThan:
|
||||
__ j(parity_even, tlabel);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThan:
|
||||
__ j(above, tlabel);
|
||||
break;
|
||||
@ -813,35 +801,15 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
|
||||
case kSignedGreaterThan:
|
||||
cc = greater;
|
||||
break;
|
||||
case kUnorderedLessThan:
|
||||
__ j(parity_odd, &check, Label::kNear);
|
||||
__ Move(reg, Immediate(0));
|
||||
__ jmp(&done, Label::kNear);
|
||||
// Fall through.
|
||||
case kUnsignedLessThan:
|
||||
cc = below;
|
||||
break;
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
__ j(parity_odd, &check, Label::kNear);
|
||||
__ mov(reg, Immediate(1));
|
||||
__ jmp(&done, Label::kNear);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
cc = above_equal;
|
||||
break;
|
||||
case kUnorderedLessThanOrEqual:
|
||||
__ j(parity_odd, &check, Label::kNear);
|
||||
__ Move(reg, Immediate(0));
|
||||
__ jmp(&done, Label::kNear);
|
||||
// Fall through.
|
||||
case kUnsignedLessThanOrEqual:
|
||||
cc = below_equal;
|
||||
break;
|
||||
case kUnorderedGreaterThan:
|
||||
__ j(parity_odd, &check, Label::kNear);
|
||||
__ mov(reg, Immediate(1));
|
||||
__ jmp(&done, Label::kNear);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThan:
|
||||
cc = above;
|
||||
break;
|
||||
|
@ -799,11 +799,12 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
|
||||
}
|
||||
|
||||
|
||||
// Shared routine for multiple float compare operations.
|
||||
// Shared routine for multiple float64 compare operations (inputs commuted).
|
||||
void VisitFloat64Compare(InstructionSelector* selector, Node* node,
|
||||
FlagsContinuation* cont) {
|
||||
VisitCompare(selector, kSSEFloat64Cmp, node->InputAt(0), node->InputAt(1),
|
||||
cont, node->op()->HasProperty(Operator::kCommutative));
|
||||
Node* const left = node->InputAt(0);
|
||||
Node* const right = node->InputAt(1);
|
||||
VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false);
|
||||
}
|
||||
|
||||
|
||||
@ -868,10 +869,10 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user,
|
||||
cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
|
||||
return VisitFloat64Compare(selector, value, cont);
|
||||
case IrOpcode::kFloat64LessThan:
|
||||
cont->OverwriteAndNegateIfEqual(kUnorderedLessThan);
|
||||
cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
|
||||
return VisitFloat64Compare(selector, value, cont);
|
||||
case IrOpcode::kFloat64LessThanOrEqual:
|
||||
cont->OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
|
||||
cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
|
||||
return VisitFloat64Compare(selector, value, cont);
|
||||
case IrOpcode::kProjection:
|
||||
// Check if this is the overflow output projection of an
|
||||
@ -984,13 +985,13 @@ void InstructionSelector::VisitFloat64Equal(Node* node) {
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThan(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedLessThan, node);
|
||||
FlagsContinuation cont(kUnsignedGreaterThan, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedLessThanOrEqual, node);
|
||||
FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
@ -1006,6 +1007,7 @@ InstructionSelector::SupportedMachineOperatorFlags() {
|
||||
}
|
||||
return MachineOperatorBuilder::Flag::kNoFlags;
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -102,10 +102,6 @@ enum FlagsCondition {
|
||||
kUnsignedGreaterThan,
|
||||
kUnorderedEqual,
|
||||
kUnorderedNotEqual,
|
||||
kUnorderedLessThan,
|
||||
kUnorderedGreaterThanOrEqual,
|
||||
kUnorderedLessThanOrEqual,
|
||||
kUnorderedGreaterThan,
|
||||
kOverflow,
|
||||
kNotOverflow
|
||||
};
|
||||
@ -129,7 +125,7 @@ typedef int32_t InstructionCode;
|
||||
typedef BitField<ArchOpcode, 0, 7> ArchOpcodeField;
|
||||
typedef BitField<AddressingMode, 7, 5> AddressingModeField;
|
||||
typedef BitField<FlagsMode, 12, 2> FlagsModeField;
|
||||
typedef BitField<FlagsCondition, 14, 5> FlagsConditionField;
|
||||
typedef BitField<FlagsCondition, 14, 4> FlagsConditionField;
|
||||
typedef BitField<int, 14, 18> MiscField;
|
||||
|
||||
} // namespace compiler
|
||||
|
@ -303,18 +303,6 @@ class FlagsContinuation FINAL {
|
||||
case kUnorderedEqual:
|
||||
case kUnorderedNotEqual:
|
||||
return;
|
||||
case kUnorderedLessThan:
|
||||
condition_ = kUnorderedGreaterThan;
|
||||
return;
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
condition_ = kUnorderedLessThanOrEqual;
|
||||
return;
|
||||
case kUnorderedLessThanOrEqual:
|
||||
condition_ = kUnorderedGreaterThanOrEqual;
|
||||
return;
|
||||
case kUnorderedGreaterThan:
|
||||
condition_ = kUnorderedLessThan;
|
||||
return;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -252,14 +252,6 @@ std::ostream& operator<<(std::ostream& os, const FlagsCondition& fc) {
|
||||
return os << "unordered equal";
|
||||
case kUnorderedNotEqual:
|
||||
return os << "unordered not equal";
|
||||
case kUnorderedLessThan:
|
||||
return os << "unordered less than";
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
return os << "unordered greater than or equal";
|
||||
case kUnorderedLessThanOrEqual:
|
||||
return os << "unordered less than or equal";
|
||||
case kUnorderedGreaterThan:
|
||||
return os << "unordered greater than";
|
||||
case kOverflow:
|
||||
return os << "overflow";
|
||||
case kNotOverflow:
|
||||
|
@ -1042,27 +1042,15 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
||||
case kSignedGreaterThan:
|
||||
__ j(greater, tlabel);
|
||||
break;
|
||||
case kUnorderedLessThan:
|
||||
__ j(parity_even, flabel, flabel_distance);
|
||||
// Fall through.
|
||||
case kUnsignedLessThan:
|
||||
__ j(below, tlabel);
|
||||
break;
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
__ j(parity_even, tlabel);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
__ j(above_equal, tlabel);
|
||||
break;
|
||||
case kUnorderedLessThanOrEqual:
|
||||
__ j(parity_even, flabel, flabel_distance);
|
||||
// Fall through.
|
||||
case kUnsignedLessThanOrEqual:
|
||||
__ j(below_equal, tlabel);
|
||||
break;
|
||||
case kUnorderedGreaterThan:
|
||||
__ j(parity_even, tlabel);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThan:
|
||||
__ j(above, tlabel);
|
||||
break;
|
||||
@ -1123,35 +1111,15 @@ void CodeGenerator::AssembleArchBoolean(Instruction* instr,
|
||||
case kSignedGreaterThan:
|
||||
cc = greater;
|
||||
break;
|
||||
case kUnorderedLessThan:
|
||||
__ j(parity_odd, &check, Label::kNear);
|
||||
__ movl(reg, Immediate(0));
|
||||
__ jmp(&done, Label::kNear);
|
||||
// Fall through.
|
||||
case kUnsignedLessThan:
|
||||
cc = below;
|
||||
break;
|
||||
case kUnorderedGreaterThanOrEqual:
|
||||
__ j(parity_odd, &check, Label::kNear);
|
||||
__ movl(reg, Immediate(1));
|
||||
__ jmp(&done, Label::kNear);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThanOrEqual:
|
||||
cc = above_equal;
|
||||
break;
|
||||
case kUnorderedLessThanOrEqual:
|
||||
__ j(parity_odd, &check, Label::kNear);
|
||||
__ movl(reg, Immediate(0));
|
||||
__ jmp(&done, Label::kNear);
|
||||
// Fall through.
|
||||
case kUnsignedLessThanOrEqual:
|
||||
cc = below_equal;
|
||||
break;
|
||||
case kUnorderedGreaterThan:
|
||||
__ j(parity_odd, &check, Label::kNear);
|
||||
__ movl(reg, Immediate(1));
|
||||
__ jmp(&done, Label::kNear);
|
||||
// Fall through.
|
||||
case kUnsignedGreaterThan:
|
||||
cc = above;
|
||||
break;
|
||||
|
@ -1027,11 +1027,12 @@ static void VisitCompareZero(InstructionSelector* selector, Node* node,
|
||||
}
|
||||
|
||||
|
||||
// Shared routine for multiple float64 compare operations.
|
||||
// Shared routine for multiple float64 compare operations (inputs commuted).
|
||||
static void VisitFloat64Compare(InstructionSelector* selector, Node* node,
|
||||
FlagsContinuation* cont) {
|
||||
VisitCompare(selector, kSSEFloat64Cmp, node->InputAt(0), node->InputAt(1),
|
||||
cont, node->op()->HasProperty(Operator::kCommutative));
|
||||
Node* const left = node->InputAt(0);
|
||||
Node* const right = node->InputAt(1);
|
||||
VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false);
|
||||
}
|
||||
|
||||
|
||||
@ -1102,10 +1103,10 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
|
||||
cont.OverwriteAndNegateIfEqual(kUnorderedEqual);
|
||||
return VisitFloat64Compare(this, value, &cont);
|
||||
case IrOpcode::kFloat64LessThan:
|
||||
cont.OverwriteAndNegateIfEqual(kUnorderedLessThan);
|
||||
cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
|
||||
return VisitFloat64Compare(this, value, &cont);
|
||||
case IrOpcode::kFloat64LessThanOrEqual:
|
||||
cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
|
||||
cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
|
||||
return VisitFloat64Compare(this, value, &cont);
|
||||
case IrOpcode::kProjection:
|
||||
// Check if this is the overflow output projection of an
|
||||
@ -1291,13 +1292,13 @@ void InstructionSelector::VisitFloat64Equal(Node* node) {
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThan(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedLessThan, node);
|
||||
FlagsContinuation cont(kUnsignedGreaterThan, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
||||
void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
|
||||
FlagsContinuation cont(kUnorderedLessThanOrEqual, node);
|
||||
FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node);
|
||||
VisitFloat64Compare(this, node, &cont);
|
||||
}
|
||||
|
||||
|
@ -444,10 +444,10 @@ TEST(BranchCombineFloat64Compares) {
|
||||
m.Bind(&blockb);
|
||||
m.Return(m.Int32Constant(ne_constant));
|
||||
|
||||
for (size_t i = 0; i < arraysize(inputs); i++) {
|
||||
for (size_t j = 0; j < arraysize(inputs); j += 2) {
|
||||
for (size_t i = 0; i < arraysize(inputs); ++i) {
|
||||
for (size_t j = 0; j < arraysize(inputs); ++j) {
|
||||
input_a = inputs[i];
|
||||
input_b = inputs[i];
|
||||
input_b = inputs[j];
|
||||
int32_t expected =
|
||||
invert ? (cmp.Float64Compare(input_a, input_b) ? ne_constant
|
||||
: eq_constant)
|
||||
|
@ -62,7 +62,7 @@ Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type,
|
||||
|
||||
|
||||
// ARM64 logical instructions.
|
||||
static const MachInst2 kLogicalInstructions[] = {
|
||||
const MachInst2 kLogicalInstructions[] = {
|
||||
{&RawMachineAssembler::Word32And, "Word32And", kArm64And32, kMachInt32},
|
||||
{&RawMachineAssembler::Word64And, "Word64And", kArm64And, kMachInt64},
|
||||
{&RawMachineAssembler::Word32Or, "Word32Or", kArm64Or32, kMachInt32},
|
||||
@ -74,7 +74,7 @@ static const MachInst2 kLogicalInstructions[] = {
|
||||
// ARM64 logical immediates: contiguous set bits, rotated about a power of two
|
||||
// sized block. The block is then duplicated across the word. Below is a random
|
||||
// subset of the 32-bit immediates.
|
||||
static const uint32_t kLogical32Immediates[] = {
|
||||
const uint32_t kLogical32Immediates[] = {
|
||||
0x00000002, 0x00000003, 0x00000070, 0x00000080, 0x00000100, 0x000001c0,
|
||||
0x00000300, 0x000007e0, 0x00003ffc, 0x00007fc0, 0x0003c000, 0x0003f000,
|
||||
0x0003ffc0, 0x0003fff8, 0x0007ff00, 0x0007ffe0, 0x000e0000, 0x001e0000,
|
||||
@ -95,7 +95,7 @@ static const uint32_t kLogical32Immediates[] = {
|
||||
|
||||
|
||||
// Random subset of 64-bit logical immediates.
|
||||
static const uint64_t kLogical64Immediates[] = {
|
||||
const uint64_t kLogical64Immediates[] = {
|
||||
0x0000000000000001, 0x0000000000000002, 0x0000000000000003,
|
||||
0x0000000000000070, 0x0000000000000080, 0x0000000000000100,
|
||||
0x00000000000001c0, 0x0000000000000300, 0x0000000000000600,
|
||||
@ -131,7 +131,7 @@ std::ostream& operator<<(std::ostream& os, const AddSub& op) {
|
||||
}
|
||||
|
||||
|
||||
static const AddSub kAddSubInstructions[] = {
|
||||
const AddSub kAddSubInstructions[] = {
|
||||
{{&RawMachineAssembler::Int32Add, "Int32Add", kArm64Add32, kMachInt32},
|
||||
kArm64Sub32},
|
||||
{{&RawMachineAssembler::Int64Add, "Int64Add", kArm64Add, kMachInt64},
|
||||
@ -144,7 +144,7 @@ static const AddSub kAddSubInstructions[] = {
|
||||
|
||||
// ARM64 Add/Sub immediates: 12-bit immediate optionally shifted by 12.
|
||||
// Below is a combination of a random subset and some edge values.
|
||||
static const int32_t kAddSubImmediates[] = {
|
||||
const int32_t kAddSubImmediates[] = {
|
||||
0, 1, 69, 493, 599, 701, 719,
|
||||
768, 818, 842, 945, 1246, 1286, 1429,
|
||||
1669, 2171, 2179, 2182, 2254, 2334, 2338,
|
||||
@ -160,7 +160,7 @@ static const int32_t kAddSubImmediates[] = {
|
||||
|
||||
|
||||
// ARM64 flag setting data processing instructions.
|
||||
static const MachInst2 kDPFlagSetInstructions[] = {
|
||||
const MachInst2 kDPFlagSetInstructions[] = {
|
||||
{&RawMachineAssembler::Word32And, "Word32And", kArm64Tst32, kMachInt32},
|
||||
{&RawMachineAssembler::Int32Add, "Int32Add", kArm64Cmn32, kMachInt32},
|
||||
{&RawMachineAssembler::Int32Sub, "Int32Sub", kArm64Cmp32, kMachInt32},
|
||||
@ -168,7 +168,7 @@ static const MachInst2 kDPFlagSetInstructions[] = {
|
||||
|
||||
|
||||
// ARM64 arithmetic with overflow instructions.
|
||||
static const MachInst2 kOvfAddSubInstructions[] = {
|
||||
const MachInst2 kOvfAddSubInstructions[] = {
|
||||
{&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow",
|
||||
kArm64Add32, kMachInt32},
|
||||
{&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow",
|
||||
@ -176,7 +176,7 @@ static const MachInst2 kOvfAddSubInstructions[] = {
|
||||
|
||||
|
||||
// ARM64 shift instructions.
|
||||
static const Shift kShiftInstructions[] = {
|
||||
const Shift kShiftInstructions[] = {
|
||||
{{&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32, kMachInt32},
|
||||
kMode_Operand2_R_LSL_I},
|
||||
{{&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Lsl, kMachInt64},
|
||||
@ -196,7 +196,7 @@ static const Shift kShiftInstructions[] = {
|
||||
|
||||
|
||||
// ARM64 Mul/Div instructions.
|
||||
static const MachInst2 kMulDivInstructions[] = {
|
||||
const MachInst2 kMulDivInstructions[] = {
|
||||
{&RawMachineAssembler::Int32Mul, "Int32Mul", kArm64Mul32, kMachInt32},
|
||||
{&RawMachineAssembler::Int64Mul, "Int64Mul", kArm64Mul, kMachInt64},
|
||||
{&RawMachineAssembler::Int32Div, "Int32Div", kArm64Idiv32, kMachInt32},
|
||||
@ -206,7 +206,7 @@ static const MachInst2 kMulDivInstructions[] = {
|
||||
|
||||
|
||||
// ARM64 FP arithmetic instructions.
|
||||
static const MachInst2 kFPArithInstructions[] = {
|
||||
const MachInst2 kFPArithInstructions[] = {
|
||||
{&RawMachineAssembler::Float64Add, "Float64Add", kArm64Float64Add,
|
||||
kMachFloat64},
|
||||
{&RawMachineAssembler::Float64Sub, "Float64Sub", kArm64Float64Sub,
|
||||
@ -229,16 +229,16 @@ std::ostream& operator<<(std::ostream& os, const FPCmp& cmp) {
|
||||
|
||||
|
||||
// ARM64 FP comparison instructions.
|
||||
static const FPCmp kFPCmpInstructions[] = {
|
||||
const FPCmp kFPCmpInstructions[] = {
|
||||
{{&RawMachineAssembler::Float64Equal, "Float64Equal", kArm64Float64Cmp,
|
||||
kMachFloat64},
|
||||
kUnorderedEqual},
|
||||
kEqual},
|
||||
{{&RawMachineAssembler::Float64LessThan, "Float64LessThan",
|
||||
kArm64Float64Cmp, kMachFloat64},
|
||||
kUnorderedLessThan},
|
||||
kUnsignedLessThan},
|
||||
{{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual",
|
||||
kArm64Float64Cmp, kMachFloat64},
|
||||
kUnorderedLessThanOrEqual}};
|
||||
kUnsignedLessThanOrEqual}};
|
||||
|
||||
|
||||
struct Conversion {
|
||||
@ -254,7 +254,7 @@ std::ostream& operator<<(std::ostream& os, const Conversion& conv) {
|
||||
|
||||
|
||||
// ARM64 type conversion instructions.
|
||||
static const Conversion kConversionInstructions[] = {
|
||||
const Conversion kConversionInstructions[] = {
|
||||
{{&RawMachineAssembler::ChangeFloat32ToFloat64, "ChangeFloat32ToFloat64",
|
||||
kArm64Float32ToFloat64, kMachFloat64},
|
||||
kMachFloat32},
|
||||
|
Loading…
Reference in New Issue
Block a user