summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/x64/instruction-selector-x64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/x64/instruction-selector-x64.cc')
-rw-r--r--deps/v8/src/compiler/x64/instruction-selector-x64.cc419
1 files changed, 291 insertions, 128 deletions
diff --git a/deps/v8/src/compiler/x64/instruction-selector-x64.cc b/deps/v8/src/compiler/x64/instruction-selector-x64.cc
index d3a2a8e753..f46ff5946d 100644
--- a/deps/v8/src/compiler/x64/instruction-selector-x64.cc
+++ b/deps/v8/src/compiler/x64/instruction-selector-x64.cc
@@ -36,6 +36,37 @@ class X64OperandGenerator final : public OperandGenerator {
}
}
+ bool CanBeMemoryOperand(InstructionCode opcode, Node* node, Node* input,
+ int effect_level) {
+ if (input->opcode() != IrOpcode::kLoad ||
+ !selector()->CanCover(node, input)) {
+ return false;
+ }
+ if (effect_level != selector()->GetEffectLevel(input)) {
+ return false;
+ }
+ MachineRepresentation rep =
+ LoadRepresentationOf(input->op()).representation();
+ switch (opcode) {
+ case kX64Cmp:
+ case kX64Test:
+ return rep == MachineRepresentation::kWord64 ||
+ rep == MachineRepresentation::kTagged;
+ case kX64Cmp32:
+ case kX64Test32:
+ return rep == MachineRepresentation::kWord32;
+ case kX64Cmp16:
+ case kX64Test16:
+ return rep == MachineRepresentation::kWord16;
+ case kX64Cmp8:
+ case kX64Test8:
+ return rep == MachineRepresentation::kWord8;
+ default:
+ break;
+ }
+ return false;
+ }
+
AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent,
Node* base, Node* displacement,
InstructionOperand inputs[],
@@ -173,9 +204,7 @@ void InstructionSelector::VisitStore(Node* node) {
inputs[input_count++] = g.UseUniqueRegister(index);
addressing_mode = kMode_MR1;
}
- inputs[input_count++] = (write_barrier_kind == kMapWriteBarrier)
- ? g.UseRegister(value)
- : g.UseUniqueRegister(value);
+ inputs[input_count++] = g.UseUniqueRegister(value);
RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny;
switch (write_barrier_kind) {
case kNoWriteBarrier:
@@ -399,8 +428,13 @@ static void VisitBinop(InstructionSelector* selector, Node* node,
DCHECK_GE(arraysize(inputs), input_count);
DCHECK_GE(arraysize(outputs), output_count);
- selector->Emit(cont->Encode(opcode), output_count, outputs, input_count,
- inputs);
+ opcode = cont->Encode(opcode);
+ if (cont->IsDeoptimize()) {
+ selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
+ cont->frame_state());
+ } else {
+ selector->Emit(opcode, output_count, outputs, input_count, inputs);
+ }
}
@@ -588,6 +622,75 @@ void InstructionSelector::VisitWord32Sar(Node* node) {
void InstructionSelector::VisitWord64Sar(Node* node) {
+ X64OperandGenerator g(this);
+ Int64BinopMatcher m(node);
+ if (CanCover(m.node(), m.left().node()) && m.left().IsLoad() &&
+ m.right().Is(32)) {
+ // Just load and sign-extend the interesting 4 bytes instead. This happens,
+ // for example, when we're loading and untagging SMIs.
+ BaseWithIndexAndDisplacement64Matcher mleft(m.left().node(), true);
+ if (mleft.matches() && (mleft.displacement() == nullptr ||
+ g.CanBeImmediate(mleft.displacement()))) {
+ size_t input_count = 0;
+ InstructionOperand inputs[3];
+ AddressingMode mode = g.GetEffectiveAddressMemoryOperand(
+ m.left().node(), inputs, &input_count);
+ if (mleft.displacement() == nullptr) {
+ // Make sure that the addressing mode indicates the presence of an
+ // immediate displacement. It seems that we never use M1 and M2, but we
+ // handle them here anyways.
+ switch (mode) {
+ case kMode_MR:
+ mode = kMode_MRI;
+ break;
+ case kMode_MR1:
+ mode = kMode_MR1I;
+ break;
+ case kMode_MR2:
+ mode = kMode_MR2I;
+ break;
+ case kMode_MR4:
+ mode = kMode_MR4I;
+ break;
+ case kMode_MR8:
+ mode = kMode_MR8I;
+ break;
+ case kMode_M1:
+ mode = kMode_M1I;
+ break;
+ case kMode_M2:
+ mode = kMode_M2I;
+ break;
+ case kMode_M4:
+ mode = kMode_M4I;
+ break;
+ case kMode_M8:
+ mode = kMode_M8I;
+ break;
+ case kMode_None:
+ case kMode_MRI:
+ case kMode_MR1I:
+ case kMode_MR2I:
+ case kMode_MR4I:
+ case kMode_MR8I:
+ case kMode_M1I:
+ case kMode_M2I:
+ case kMode_M4I:
+ case kMode_M8I:
+ UNREACHABLE();
+ }
+ inputs[input_count++] = ImmediateOperand(ImmediateOperand::INLINE, 4);
+ } else {
+ ImmediateOperand* op = ImmediateOperand::cast(&inputs[input_count - 1]);
+ int32_t displacement = sequence()->GetImmediate(op).ToInt32();
+ *op = ImmediateOperand(ImmediateOperand::INLINE, displacement + 4);
+ }
+ InstructionOperand outputs[] = {g.DefineAsRegister(node)};
+ InstructionCode code = kX64Movsxlq | AddressingModeField::encode(mode);
+ Emit(code, 1, outputs, input_count, inputs);
+ return;
+ }
+ }
VisitWord64Shift(this, node, kX64Sar);
}
@@ -668,8 +771,8 @@ void InstructionSelector::VisitInt64Add(Node* node) {
void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
- FlagsContinuation cont(kOverflow, ovf);
- VisitBinop(this, node, kX64Add, &cont);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
+ return VisitBinop(this, node, kX64Add, &cont);
}
FlagsContinuation cont;
VisitBinop(this, node, kX64Add, &cont);
@@ -708,7 +811,7 @@ void InstructionSelector::VisitInt64Sub(Node* node) {
void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
- FlagsContinuation cont(kOverflow, ovf);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
return VisitBinop(this, node, kX64Sub, &cont);
}
FlagsContinuation cont;
@@ -865,9 +968,15 @@ void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
X64OperandGenerator g(this);
- Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
+ Emit(kSSEFloat64ToUint32 | MiscField::encode(1), g.DefineAsRegister(node),
+ g.Use(node->InputAt(0)));
}
+void InstructionSelector::VisitTruncateFloat64ToUint32(Node* node) {
+ X64OperandGenerator g(this);
+ Emit(kSSEFloat64ToUint32 | MiscField::encode(0), g.DefineAsRegister(node),
+ g.Use(node->InputAt(0)));
+}
void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
X64OperandGenerator g(this);
@@ -1336,6 +1445,7 @@ void InstructionSelector::EmitPrepareArguments(
bool InstructionSelector::IsTailCallAddressImmediate() { return true; }
+int InstructionSelector::GetTempsCountForTailCallFromJSFunction() { return 3; }
namespace {
@@ -1357,6 +1467,9 @@ void VisitCompareWithMemoryOperand(InstructionSelector* selector,
inputs[input_count++] = g.Label(cont->true_block());
inputs[input_count++] = g.Label(cont->false_block());
selector->Emit(opcode, 0, nullptr, input_count, inputs);
+ } else if (cont->IsDeoptimize()) {
+ selector->EmitDeoptimize(opcode, 0, nullptr, input_count, inputs,
+ cont->frame_state());
} else {
DCHECK(cont->IsSet());
InstructionOperand output = g.DefineAsRegister(cont->result());
@@ -1364,23 +1477,6 @@ void VisitCompareWithMemoryOperand(InstructionSelector* selector,
}
}
-// Determines if {input} of {node} can be replaced by a memory operand.
-bool CanUseMemoryOperand(InstructionSelector* selector, InstructionCode opcode,
- Node* node, Node* input) {
- if (input->opcode() != IrOpcode::kLoad || !selector->CanCover(node, input)) {
- return false;
- }
- MachineRepresentation rep =
- LoadRepresentationOf(input->op()).representation();
- if (rep == MachineRepresentation::kWord64 ||
- rep == MachineRepresentation::kTagged) {
- return opcode == kX64Cmp || opcode == kX64Test;
- } else if (rep == MachineRepresentation::kWord32) {
- return opcode == kX64Cmp32 || opcode == kX64Test32;
- }
- return false;
-}
-
// Shared routine for multiple compare operations.
void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
InstructionOperand left, InstructionOperand right,
@@ -1390,6 +1486,9 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
if (cont->IsBranch()) {
selector->Emit(opcode, g.NoOutput(), left, right,
g.Label(cont->true_block()), g.Label(cont->false_block()));
+ } else if (cont->IsDeoptimize()) {
+ selector->EmitDeoptimize(opcode, g.NoOutput(), left, right,
+ cont->frame_state());
} else {
DCHECK(cont->IsSet());
selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right);
@@ -1408,6 +1507,37 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
}
+// Tries to match the size of the given opcode to that of the operands, if
+// possible.
+InstructionCode TryNarrowOpcodeSize(InstructionCode opcode, Node* left,
+ Node* right) {
+ if (opcode != kX64Cmp32 && opcode != kX64Test32) {
+ return opcode;
+ }
+ // Currently, if one of the two operands is not a Load, we don't know what its
+ // machine representation is, so we bail out.
+ // TODO(epertoso): we can probably get some size information out of immediates
+ // and phi nodes.
+ if (left->opcode() != IrOpcode::kLoad || right->opcode() != IrOpcode::kLoad) {
+ return opcode;
+ }
+ // If the load representations don't match, both operands will be
+ // zero/sign-extended to 32bit.
+ LoadRepresentation left_representation = LoadRepresentationOf(left->op());
+ if (left_representation != LoadRepresentationOf(right->op())) {
+ return opcode;
+ }
+ switch (left_representation.representation()) {
+ case MachineRepresentation::kBit:
+ case MachineRepresentation::kWord8:
+ return opcode == kX64Cmp32 ? kX64Cmp8 : kX64Test8;
+ case MachineRepresentation::kWord16:
+ return opcode == kX64Cmp32 ? kX64Cmp16 : kX64Test16;
+ default:
+ return opcode;
+ }
+}
+
// Shared routine for multiple word compare operations.
void VisitWordCompare(InstructionSelector* selector, Node* node,
InstructionCode opcode, FlagsContinuation* cont) {
@@ -1415,15 +1545,26 @@ void VisitWordCompare(InstructionSelector* selector, Node* node,
Node* left = node->InputAt(0);
Node* right = node->InputAt(1);
- // If one of the two inputs is an immediate, make sure it's on the right.
- if (!g.CanBeImmediate(right) && g.CanBeImmediate(left)) {
+ opcode = TryNarrowOpcodeSize(opcode, left, right);
+
+ // If one of the two inputs is an immediate, make sure it's on the right, or
+ // if one of the two inputs is a memory operand, make sure it's on the left.
+ int effect_level = selector->GetEffectLevel(node);
+ if (cont->IsBranch()) {
+ effect_level = selector->GetEffectLevel(
+ cont->true_block()->PredecessorAt(0)->control_input());
+ }
+
+ if ((!g.CanBeImmediate(right) && g.CanBeImmediate(left)) ||
+ (g.CanBeMemoryOperand(opcode, node, right, effect_level) &&
+ !g.CanBeMemoryOperand(opcode, node, left, effect_level))) {
if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
std::swap(left, right);
}
// Match immediates on right side of comparison.
if (g.CanBeImmediate(right)) {
- if (CanUseMemoryOperand(selector, opcode, node, left)) {
+ if (g.CanBeMemoryOperand(opcode, node, left, effect_level)) {
return VisitCompareWithMemoryOperand(selector, opcode, left,
g.UseImmediate(right), cont);
}
@@ -1431,15 +1572,17 @@ void VisitWordCompare(InstructionSelector* selector, Node* node,
cont);
}
+ // Match memory operands on left side of comparison.
+ if (g.CanBeMemoryOperand(opcode, node, left, effect_level)) {
+ return VisitCompareWithMemoryOperand(selector, opcode, left,
+ g.UseRegister(right), cont);
+ }
+
if (g.CanBeBetterLeftOperand(right)) {
if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
std::swap(left, right);
}
- if (CanUseMemoryOperand(selector, opcode, node, left)) {
- return VisitCompareWithMemoryOperand(selector, opcode, left,
- g.UseRegister(right), cont);
- }
return VisitCompare(selector, opcode, left, right, cont,
node->op()->HasProperty(Operator::kCommutative));
}
@@ -1460,6 +1603,9 @@ void VisitWord64Compare(InstructionSelector* selector, Node* node,
if (cont->IsBranch()) {
selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()),
g.Label(cont->false_block()));
+ } else if (cont->IsDeoptimize()) {
+ selector->EmitDeoptimize(opcode, 0, nullptr, 0, nullptr,
+ cont->frame_state());
} else {
DCHECK(cont->IsSet());
selector->Emit(opcode, g.DefineAsRegister(cont->result()));
@@ -1500,98 +1646,87 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node,
VisitCompare(selector, opcode, right, left, cont, false);
}
-} // namespace
-
-
-void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
- BasicBlock* fbranch) {
- X64OperandGenerator g(this);
- Node* user = branch;
- Node* value = branch->InputAt(0);
-
- FlagsContinuation cont(kNotEqual, tbranch, fbranch);
-
- // Try to combine with comparisons against 0 by simply inverting the branch.
- while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) {
- Int32BinopMatcher m(value);
- if (m.right().Is(0)) {
- user = value;
- value = m.left().node();
- cont.Negate();
- } else {
- break;
- }
- }
-
- // Try to combine the branch with a comparison.
- if (CanCover(user, value)) {
+// Shared routine for word comparison against zero.
+void VisitWordCompareZero(InstructionSelector* selector, Node* user,
+ Node* value, FlagsContinuation* cont) {
+ while (selector->CanCover(user, value)) {
switch (value->opcode()) {
- case IrOpcode::kWord32Equal:
- cont.OverwriteAndNegateIfEqual(kEqual);
- return VisitWordCompare(this, value, kX64Cmp32, &cont);
+ case IrOpcode::kWord32Equal: {
+ // Combine with comparisons against 0 by simply inverting the
+ // continuation.
+ Int32BinopMatcher m(value);
+ if (m.right().Is(0)) {
+ user = value;
+ value = m.left().node();
+ cont->Negate();
+ continue;
+ }
+ cont->OverwriteAndNegateIfEqual(kEqual);
+ return VisitWordCompare(selector, value, kX64Cmp32, cont);
+ }
case IrOpcode::kInt32LessThan:
- cont.OverwriteAndNegateIfEqual(kSignedLessThan);
- return VisitWordCompare(this, value, kX64Cmp32, &cont);
+ cont->OverwriteAndNegateIfEqual(kSignedLessThan);
+ return VisitWordCompare(selector, value, kX64Cmp32, cont);
case IrOpcode::kInt32LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
- return VisitWordCompare(this, value, kX64Cmp32, &cont);
+ cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
+ return VisitWordCompare(selector, value, kX64Cmp32, cont);
case IrOpcode::kUint32LessThan:
- cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
- return VisitWordCompare(this, value, kX64Cmp32, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
+ return VisitWordCompare(selector, value, kX64Cmp32, cont);
case IrOpcode::kUint32LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
- return VisitWordCompare(this, value, kX64Cmp32, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
+ return VisitWordCompare(selector, value, kX64Cmp32, cont);
case IrOpcode::kWord64Equal: {
- cont.OverwriteAndNegateIfEqual(kEqual);
+ cont->OverwriteAndNegateIfEqual(kEqual);
Int64BinopMatcher m(value);
if (m.right().Is(0)) {
// Try to combine the branch with a comparison.
Node* const user = m.node();
Node* const value = m.left().node();
- if (CanCover(user, value)) {
+ if (selector->CanCover(user, value)) {
switch (value->opcode()) {
case IrOpcode::kInt64Sub:
- return VisitWord64Compare(this, value, &cont);
+ return VisitWord64Compare(selector, value, cont);
case IrOpcode::kWord64And:
- return VisitWordCompare(this, value, kX64Test, &cont);
+ return VisitWordCompare(selector, value, kX64Test, cont);
default:
break;
}
}
- return VisitCompareZero(this, value, kX64Cmp, &cont);
+ return VisitCompareZero(selector, value, kX64Cmp, cont);
}
- return VisitWord64Compare(this, value, &cont);
+ return VisitWord64Compare(selector, value, cont);
}
case IrOpcode::kInt64LessThan:
- cont.OverwriteAndNegateIfEqual(kSignedLessThan);
- return VisitWord64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kSignedLessThan);
+ return VisitWord64Compare(selector, value, cont);
case IrOpcode::kInt64LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
- return VisitWord64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
+ return VisitWord64Compare(selector, value, cont);
case IrOpcode::kUint64LessThan:
- cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
- return VisitWord64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
+ return VisitWord64Compare(selector, value, cont);
case IrOpcode::kUint64LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
- return VisitWord64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
+ return VisitWord64Compare(selector, value, cont);
case IrOpcode::kFloat32Equal:
- cont.OverwriteAndNegateIfEqual(kUnorderedEqual);
- return VisitFloat32Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
+ return VisitFloat32Compare(selector, value, cont);
case IrOpcode::kFloat32LessThan:
- cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
- return VisitFloat32Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
+ return VisitFloat32Compare(selector, value, cont);
case IrOpcode::kFloat32LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
- return VisitFloat32Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
+ return VisitFloat32Compare(selector, value, cont);
case IrOpcode::kFloat64Equal:
- cont.OverwriteAndNegateIfEqual(kUnorderedEqual);
- return VisitFloat64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
+ return VisitFloat64Compare(selector, value, cont);
case IrOpcode::kFloat64LessThan:
- cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
- return VisitFloat64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
+ return VisitFloat64Compare(selector, value, cont);
case IrOpcode::kFloat64LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
- return VisitFloat64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
+ return VisitFloat64Compare(selector, value, cont);
case IrOpcode::kProjection:
// Check if this is the overflow output projection of an
// <Operation>WithOverflow node.
@@ -1603,20 +1738,20 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
// *AFTER* this branch).
Node* const node = value->InputAt(0);
Node* const result = NodeProperties::FindProjection(node, 0);
- if (result == nullptr || IsDefined(result)) {
+ if (result == nullptr || selector->IsDefined(result)) {
switch (node->opcode()) {
case IrOpcode::kInt32AddWithOverflow:
- cont.OverwriteAndNegateIfEqual(kOverflow);
- return VisitBinop(this, node, kX64Add32, &cont);
+ cont->OverwriteAndNegateIfEqual(kOverflow);
+ return VisitBinop(selector, node, kX64Add32, cont);
case IrOpcode::kInt32SubWithOverflow:
- cont.OverwriteAndNegateIfEqual(kOverflow);
- return VisitBinop(this, node, kX64Sub32, &cont);
+ cont->OverwriteAndNegateIfEqual(kOverflow);
+ return VisitBinop(selector, node, kX64Sub32, cont);
case IrOpcode::kInt64AddWithOverflow:
- cont.OverwriteAndNegateIfEqual(kOverflow);
- return VisitBinop(this, node, kX64Add, &cont);
+ cont->OverwriteAndNegateIfEqual(kOverflow);
+ return VisitBinop(selector, node, kX64Add, cont);
case IrOpcode::kInt64SubWithOverflow:
- cont.OverwriteAndNegateIfEqual(kOverflow);
- return VisitBinop(this, node, kX64Sub, &cont);
+ cont->OverwriteAndNegateIfEqual(kOverflow);
+ return VisitBinop(selector, node, kX64Sub, cont);
default:
break;
}
@@ -1624,22 +1759,42 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
}
break;
case IrOpcode::kInt32Sub:
- return VisitWordCompare(this, value, kX64Cmp32, &cont);
+ return VisitWordCompare(selector, value, kX64Cmp32, cont);
case IrOpcode::kInt64Sub:
- return VisitWord64Compare(this, value, &cont);
+ return VisitWord64Compare(selector, value, cont);
case IrOpcode::kWord32And:
- return VisitWordCompare(this, value, kX64Test32, &cont);
+ return VisitWordCompare(selector, value, kX64Test32, cont);
case IrOpcode::kWord64And:
- return VisitWordCompare(this, value, kX64Test, &cont);
+ return VisitWordCompare(selector, value, kX64Test, cont);
default:
break;
}
+ break;
}
// Branch could not be combined with a compare, emit compare against 0.
- VisitCompareZero(this, value, kX64Cmp32, &cont);
+ VisitCompareZero(selector, value, kX64Cmp32, cont);
+}
+
+} // namespace
+
+void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
+ BasicBlock* fbranch) {
+ FlagsContinuation cont(kNotEqual, tbranch, fbranch);
+ VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
+}
+
+void InstructionSelector::VisitDeoptimizeIf(Node* node) {
+ FlagsContinuation cont =
+ FlagsContinuation::ForDeoptimize(kNotEqual, node->InputAt(1));
+ VisitWordCompareZero(this, node, node->InputAt(0), &cont);
}
+void InstructionSelector::VisitDeoptimizeUnless(Node* node) {
+ FlagsContinuation cont =
+ FlagsContinuation::ForDeoptimize(kEqual, node->InputAt(1));
+ VisitWordCompareZero(this, node, node->InputAt(0), &cont);
+}
void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
X64OperandGenerator g(this);
@@ -1674,7 +1829,7 @@ void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
void InstructionSelector::VisitWord32Equal(Node* const node) {
Node* user = node;
- FlagsContinuation cont(kEqual, node);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
Int32BinopMatcher m(user);
if (m.right().Is(0)) {
Node* value = m.left().node();
@@ -1709,31 +1864,33 @@ void InstructionSelector::VisitWord32Equal(Node* const node) {
void InstructionSelector::VisitInt32LessThan(Node* node) {
- FlagsContinuation cont(kSignedLessThan, node);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
VisitWordCompare(this, node, kX64Cmp32, &cont);
}
void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
- FlagsContinuation cont(kSignedLessThanOrEqual, node);
+ FlagsContinuation cont =
+ FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
VisitWordCompare(this, node, kX64Cmp32, &cont);
}
void InstructionSelector::VisitUint32LessThan(Node* node) {
- FlagsContinuation cont(kUnsignedLessThan, node);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
VisitWordCompare(this, node, kX64Cmp32, &cont);
}
void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
- FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
+ FlagsContinuation cont =
+ FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
VisitWordCompare(this, node, kX64Cmp32, &cont);
}
void InstructionSelector::VisitWord64Equal(Node* const node) {
- FlagsContinuation cont(kEqual, node);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
Int64BinopMatcher m(node);
if (m.right().Is(0)) {
// Try to combine the equality check with a comparison.
@@ -1756,8 +1913,8 @@ void InstructionSelector::VisitWord64Equal(Node* const node) {
void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
- FlagsContinuation cont(kOverflow, ovf);
- VisitBinop(this, node, kX64Add32, &cont);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
+ return VisitBinop(this, node, kX64Add32, &cont);
}
FlagsContinuation cont;
VisitBinop(this, node, kX64Add32, &cont);
@@ -1766,7 +1923,7 @@ void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
- FlagsContinuation cont(kOverflow, ovf);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
return VisitBinop(this, node, kX64Sub32, &cont);
}
FlagsContinuation cont;
@@ -1775,61 +1932,67 @@ void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
void InstructionSelector::VisitInt64LessThan(Node* node) {
- FlagsContinuation cont(kSignedLessThan, node);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
VisitWord64Compare(this, node, &cont);
}
void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
- FlagsContinuation cont(kSignedLessThanOrEqual, node);
+ FlagsContinuation cont =
+ FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
VisitWord64Compare(this, node, &cont);
}
void InstructionSelector::VisitUint64LessThan(Node* node) {
- FlagsContinuation cont(kUnsignedLessThan, node);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
VisitWord64Compare(this, node, &cont);
}
void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) {
- FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
+ FlagsContinuation cont =
+ FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
VisitWord64Compare(this, node, &cont);
}
void InstructionSelector::VisitFloat32Equal(Node* node) {
- FlagsContinuation cont(kUnorderedEqual, node);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node);
VisitFloat32Compare(this, node, &cont);
}
void InstructionSelector::VisitFloat32LessThan(Node* node) {
- FlagsContinuation cont(kUnsignedGreaterThan, node);
+ FlagsContinuation cont =
+ FlagsContinuation::ForSet(kUnsignedGreaterThan, node);
VisitFloat32Compare(this, node, &cont);
}
void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) {
- FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node);
+ FlagsContinuation cont =
+ FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node);
VisitFloat32Compare(this, node, &cont);
}
void InstructionSelector::VisitFloat64Equal(Node* node) {
- FlagsContinuation cont(kUnorderedEqual, node);
+ FlagsContinuation cont = FlagsContinuation::ForSet(kUnorderedEqual, node);
VisitFloat64Compare(this, node, &cont);
}
void InstructionSelector::VisitFloat64LessThan(Node* node) {
- FlagsContinuation cont(kUnsignedGreaterThan, node);
+ FlagsContinuation cont =
+ FlagsContinuation::ForSet(kUnsignedGreaterThan, node);
VisitFloat64Compare(this, node, &cont);
}
void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
- FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node);
+ FlagsContinuation cont =
+ FlagsContinuation::ForSet(kUnsignedGreaterThanOrEqual, node);
VisitFloat64Compare(this, node, &cont);
}