Revision: 24832
Author: [email protected]
Date: Thu Oct 23 10:22:06 2014 UTC
Log: [turbofan] Improve code generation for inline comparisons with
zero.
TEST=cctest,unittests
[email protected]
Review URL: https://codereview.chromium.org/669133004
https://code.google.com/p/v8/source/detail?r=24832
Modified:
/branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
/branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
/branches/bleeding_edge/src/compiler/instruction-selector.h
/branches/bleeding_edge/src/compiler/machine-operator-reducer.cc
/branches/bleeding_edge/src/compiler/simplified-lowering.cc
/branches/bleeding_edge/src/compiler/typer.cc
/branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
/branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc
/branches/bleeding_edge/test/cctest/compiler/test-simplified-lowering.cc
/branches/bleeding_edge/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
=======================================
--- /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Fri Oct 17 11:26:26 2014 UTC
+++ /branches/bleeding_edge/src/compiler/arm/instruction-selector-arm.cc
Thu Oct 23 10:22:06 2014 UTC
@@ -900,8 +900,7 @@
// Shared routine for multiple word compare operations.
void VisitWordCompare(InstructionSelector* selector, Node* node,
- InstructionCode opcode, FlagsContinuation* cont,
- bool commutative) {
+ InstructionCode opcode, FlagsContinuation* cont) {
ArmOperandGenerator g(selector);
Int32BinopMatcher m(node);
InstructionOperand* inputs[5];
@@ -915,7 +914,7 @@
input_count++;
} else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
&input_count, &inputs[1])) {
- if (!commutative) cont->Commute();
+ if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
inputs[0] = g.UseRegister(m.right().node());
input_count++;
} else {
@@ -944,81 +943,49 @@
void VisitWordCompare(InstructionSelector* selector, Node* node,
FlagsContinuation* cont) {
- VisitWordCompare(selector, node, kArmCmp, cont, false);
+ VisitWordCompare(selector, node, kArmCmp, cont);
}
-void VisitWordTest(InstructionSelector* selector, Node* node,
- FlagsContinuation* cont) {
- ArmOperandGenerator g(selector);
- InstructionCode opcode =
- cont->Encode(kArmTst) |
AddressingModeField::encode(kMode_Operand2_R);
- if (cont->IsBranch()) {
- selector->Emit(opcode, nullptr, g.UseRegister(node),
g.UseRegister(node),
- g.Label(cont->true_block()),
- g.Label(cont->false_block()))->MarkAsControl();
- } else {
- selector->Emit(opcode, g.DefineAsRegister(cont->result()),
- g.UseRegister(node), g.UseRegister(node));
- }
-}
-
-} // namespace
-
-
-void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
- BasicBlock* fbranch) {
- ArmOperandGenerator g(this);
- Node* user = branch;
- Node* value = branch->InputAt(0);
-
- FlagsContinuation cont(kNotEqual, tbranch, fbranch);
-
- // If we can fall through to the true block, invert the branch.
- if (IsNextInAssemblyOrder(tbranch)) {
- cont.Negate();
- cont.SwapBlocks();
- }
-
- // 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 comparisons 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, &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, cont);
+ }
case IrOpcode::kInt32LessThan:
- cont.OverwriteAndNegateIfEqual(kSignedLessThan);
- return VisitWordCompare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kSignedLessThan);
+ return VisitWordCompare(selector, value, cont);
case IrOpcode::kInt32LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
- return VisitWordCompare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
+ return VisitWordCompare(selector, value, cont);
case IrOpcode::kUint32LessThan:
- cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
- return VisitWordCompare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
+ return VisitWordCompare(selector, value, cont);
case IrOpcode::kUint32LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
- return VisitWordCompare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
+ return VisitWordCompare(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(kUnorderedLessThan);
- return VisitFloat64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnorderedLessThan);
+ return VisitFloat64Compare(selector, value, cont);
case IrOpcode::kFloat64LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
- return VisitFloat64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
+ return VisitFloat64Compare(selector, value, cont);
case IrOpcode::kProjection:
// Check if this is the overflow output projection of an
// <Operation>WithOverflow node.
@@ -1028,16 +995,16 @@
// <Operation> is either NULL, which means there's no use of the
// actual value, or was already defined, which means it is
scheduled
// *AFTER* this branch).
- Node* node = value->InputAt(0);
- Node* result = node->FindProjection(0);
- if (!result || IsDefined(result)) {
+ Node* const node = value->InputAt(0);
+ Node* const result = node->FindProjection(0);
+ if (!result || selector->IsDefined(result)) {
switch (node->opcode()) {
case IrOpcode::kInt32AddWithOverflow:
- cont.OverwriteAndNegateIfEqual(kOverflow);
- return VisitBinop(this, node, kArmAdd, kArmAdd, &cont);
+ cont->OverwriteAndNegateIfEqual(kOverflow);
+ return VisitBinop(selector, node, kArmAdd, kArmAdd, cont);
case IrOpcode::kInt32SubWithOverflow:
- cont.OverwriteAndNegateIfEqual(kOverflow);
- return VisitBinop(this, node, kArmSub, kArmRsb, &cont);
+ cont->OverwriteAndNegateIfEqual(kOverflow);
+ return VisitBinop(selector, node, kArmSub, kArmRsb, cont);
default:
break;
}
@@ -1045,64 +1012,63 @@
}
break;
case IrOpcode::kInt32Add:
- return VisitWordCompare(this, value, kArmCmn, &cont, true);
+ return VisitWordCompare(selector, value, kArmCmn, cont);
case IrOpcode::kInt32Sub:
- return VisitWordCompare(this, value, kArmCmp, &cont, false);
+ return VisitWordCompare(selector, value, kArmCmp, cont);
case IrOpcode::kWord32And:
- return VisitWordCompare(this, value, kArmTst, &cont, true);
+ return VisitWordCompare(selector, value, kArmTst, cont);
case IrOpcode::kWord32Or:
- return VisitBinop(this, value, kArmOrr, kArmOrr, &cont);
+ return VisitBinop(selector, value, kArmOrr, kArmOrr, cont);
case IrOpcode::kWord32Xor:
- return VisitWordCompare(this, value, kArmTeq, &cont, true);
+ return VisitWordCompare(selector, value, kArmTeq, cont);
case IrOpcode::kWord32Sar:
- return VisitShift(this, value, TryMatchASR, &cont);
+ return VisitShift(selector, value, TryMatchASR, cont);
case IrOpcode::kWord32Shl:
- return VisitShift(this, value, TryMatchLSL, &cont);
+ return VisitShift(selector, value, TryMatchLSL, cont);
case IrOpcode::kWord32Shr:
- return VisitShift(this, value, TryMatchLSR, &cont);
+ return VisitShift(selector, value, TryMatchLSR, cont);
case IrOpcode::kWord32Ror:
- return VisitShift(this, value, TryMatchROR, &cont);
+ return VisitShift(selector, value, TryMatchROR, cont);
default:
break;
}
+ break;
}
- // Branch could not be combined with a compare, emit compare against 0.
- return VisitWordTest(this, value, &cont);
+ // Continuation could not be combined with a compare, emit compare
against 0.
+ ArmOperandGenerator g(selector);
+ InstructionCode const opcode =
+ cont->Encode(kArmTst) |
AddressingModeField::encode(kMode_Operand2_R);
+ InstructionOperand* const value_operand = g.UseRegister(value);
+ if (cont->IsBranch()) {
+ selector->Emit(opcode, nullptr, value_operand, value_operand,
+ g.Label(cont->true_block()),
+ g.Label(cont->false_block()))->MarkAsControl();
+ } else {
+ selector->Emit(opcode, g.DefineAsRegister(cont->result()),
value_operand,
+ value_operand);
+ }
}
+} // namespace
+
+
+void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
+ BasicBlock* fbranch) {
+ FlagsContinuation cont(kNotEqual, tbranch, fbranch);
+ if (IsNextInAssemblyOrder(tbranch)) { // We can fallthru to the true
block.
+ cont.Negate();
+ cont.SwapBlocks();
+ }
+ VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
+}
+
void InstructionSelector::VisitWord32Equal(Node* const node) {
- Node* const user = node;
FlagsContinuation cont(kEqual, node);
- Int32BinopMatcher m(user);
+ Int32BinopMatcher m(node);
if (m.right().Is(0)) {
- Node* const value = m.left().node();
- if (CanCover(user, value)) {
- switch (value->opcode()) {
- case IrOpcode::kInt32Add:
- return VisitWordCompare(this, value, kArmCmn, &cont, true);
- case IrOpcode::kInt32Sub:
- return VisitWordCompare(this, value, kArmCmp, &cont, false);
- case IrOpcode::kWord32And:
- return VisitWordCompare(this, value, kArmTst, &cont, true);
- case IrOpcode::kWord32Or:
- return VisitBinop(this, value, kArmOrr, kArmOrr, &cont);
- case IrOpcode::kWord32Xor:
- return VisitWordCompare(this, value, kArmTeq, &cont, true);
- case IrOpcode::kWord32Sar:
- return VisitShift(this, value, TryMatchASR, &cont);
- case IrOpcode::kWord32Shl:
- return VisitShift(this, value, TryMatchLSL, &cont);
- case IrOpcode::kWord32Shr:
- return VisitShift(this, value, TryMatchLSR, &cont);
- case IrOpcode::kWord32Ror:
- return VisitShift(this, value, TryMatchROR, &cont);
- default:
- break;
- }
- return VisitWordTest(this, value, &cont);
- }
+ return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
}
VisitWordCompare(this, node, &cont);
}
=======================================
--- /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
Tue Oct 21 10:59:55 2014 UTC
+++ /branches/bleeding_edge/src/compiler/ia32/instruction-selector-ia32.cc
Thu Oct 23 10:22:06 2014 UTC
@@ -647,10 +647,12 @@
}
+namespace {
+
// Shared routine for multiple compare operations.
-static void VisitCompare(InstructionSelector* selector, InstructionCode
opcode,
- InstructionOperand* left, InstructionOperand*
right,
- FlagsContinuation* cont) {
+void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
+ InstructionOperand* left, InstructionOperand* right,
+ FlagsContinuation* cont) {
IA32OperandGenerator g(selector);
if (cont->IsBranch()) {
selector->Emit(cont->Encode(opcode), NULL, left, right,
@@ -666,20 +668,28 @@
// Shared routine for multiple compare operations.
-static void VisitCompare(InstructionSelector* selector, InstructionCode
opcode,
- Node* left, Node* right, FlagsContinuation* cont,
- bool commutative) {
+void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
+ Node* left, Node* right, FlagsContinuation* cont,
+ bool commutative) {
IA32OperandGenerator g(selector);
if (commutative && g.CanBeBetterLeftOperand(right)) {
std::swap(left, right);
}
VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
}
+
+
+// Shared routine for multiple float compare operations.
+void VisitFloat64Compare(InstructionSelector* selector, Node* node,
+ FlagsContinuation* cont) {
+ VisitCompare(selector, kSSEFloat64Cmp, node->InputAt(0),
node->InputAt(1),
+ cont, node->op()->HasProperty(Operator::kCommutative));
+}
// Shared routine for multiple word compare operations.
-static void VisitWordCompare(InstructionSelector* selector, Node* node,
- InstructionCode opcode, FlagsContinuation*
cont) {
+void VisitWordCompare(InstructionSelector* selector, Node* node,
+ InstructionCode opcode, FlagsContinuation* cont) {
IA32OperandGenerator g(selector);
Node* const left = node->InputAt(0);
Node* const right = node->InputAt(1);
@@ -697,67 +707,52 @@
}
-// Shared routine for multiple float compare operations.
-static void VisitFloat64Compare(InstructionSelector* selector, Node* node,
- FlagsContinuation* cont) {
- VisitCompare(selector, kSSEFloat64Cmp, node->InputAt(0),
node->InputAt(1),
- cont, node->op()->HasProperty(Operator::kCommutative));
+void VisitWordCompare(InstructionSelector* selector, Node* node,
+ FlagsContinuation* cont) {
+ VisitWordCompare(selector, node, kIA32Cmp, cont);
}
-void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
- BasicBlock* fbranch) {
- IA32OperandGenerator g(this);
- Node* user = branch;
- Node* value = branch->InputAt(0);
-
- FlagsContinuation cont(kNotEqual, tbranch, fbranch);
-
- // If we can fall through to the true block, invert the branch.
- if (IsNextInAssemblyOrder(tbranch)) {
- cont.Negate();
- cont.SwapBlocks();
- }
-
- // 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;
- }
- }
-
+// Shared routine for word comparison with zero.
+void VisitWordCompareZero(InstructionSelector* selector, Node* user,
+ Node* value, FlagsContinuation* cont) {
// Try to combine the branch with a comparison.
- if (CanCover(user, value)) {
+ while (selector->CanCover(user, value)) {
switch (value->opcode()) {
- case IrOpcode::kWord32Equal:
- cont.OverwriteAndNegateIfEqual(kEqual);
- return VisitWordCompare(this, value, kIA32Cmp, &cont);
+ case IrOpcode::kWord32Equal: {
+ // Try to 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, cont);
+ }
case IrOpcode::kInt32LessThan:
- cont.OverwriteAndNegateIfEqual(kSignedLessThan);
- return VisitWordCompare(this, value, kIA32Cmp, &cont);
+ cont->OverwriteAndNegateIfEqual(kSignedLessThan);
+ return VisitWordCompare(selector, value, cont);
case IrOpcode::kInt32LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
- return VisitWordCompare(this, value, kIA32Cmp, &cont);
+ cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
+ return VisitWordCompare(selector, value, cont);
case IrOpcode::kUint32LessThan:
- cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
- return VisitWordCompare(this, value, kIA32Cmp, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
+ return VisitWordCompare(selector, value, cont);
case IrOpcode::kUint32LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
- return VisitWordCompare(this, value, kIA32Cmp, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
+ return VisitWordCompare(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(kUnorderedLessThan);
- return VisitFloat64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnorderedLessThan);
+ return VisitFloat64Compare(selector, value, cont);
case IrOpcode::kFloat64LessThanOrEqual:
- cont.OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
- return VisitFloat64Compare(this, value, &cont);
+ cont->OverwriteAndNegateIfEqual(kUnorderedLessThanOrEqual);
+ return VisitFloat64Compare(selector, value, cont);
case IrOpcode::kProjection:
// Check if this is the overflow output projection of an
// <Operation>WithOverflow node.
@@ -769,14 +764,14 @@
// *AFTER* this branch).
Node* node = value->InputAt(0);
Node* result = node->FindProjection(0);
- if (result == NULL || IsDefined(result)) {
+ if (result == NULL || selector->IsDefined(result)) {
switch (node->opcode()) {
case IrOpcode::kInt32AddWithOverflow:
- cont.OverwriteAndNegateIfEqual(kOverflow);
- return VisitBinop(this, node, kIA32Add, &cont);
+ cont->OverwriteAndNegateIfEqual(kOverflow);
+ return VisitBinop(selector, node, kIA32Add, cont);
case IrOpcode::kInt32SubWithOverflow:
- cont.OverwriteAndNegateIfEqual(kOverflow);
- return VisitBinop(this, node, kIA32Sub, &cont);
+ cont->OverwriteAndNegateIfEqual(kOverflow);
+ return VisitBinop(selector, node, kIA32Sub, cont);
default:
break;
}
@@ -784,61 +779,65 @@
}
break;
case IrOpcode::kInt32Sub:
- return VisitWordCompare(this, value, kIA32Cmp, &cont);
+ return VisitWordCompare(selector, value, cont);
case IrOpcode::kWord32And:
- return VisitWordCompare(this, value, kIA32Test, &cont);
+ return VisitWordCompare(selector, value, kIA32Test, cont);
default:
break;
}
+ break;
}
- // Branch could not be combined with a compare, emit compare against 0.
- VisitCompare(this, kIA32Cmp, g.Use(value), g.TempImmediate(0), &cont);
+ // Continuation could not be combined with a compare, emit compare
against 0.
+ IA32OperandGenerator g(selector);
+ VisitCompare(selector, kIA32Cmp, g.Use(value), g.TempImmediate(0), cont);
+}
+
+} // namespace
+
+
+void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
+ BasicBlock* fbranch) {
+ FlagsContinuation cont(kNotEqual, tbranch, fbranch);
+ if (IsNextInAssemblyOrder(tbranch)) { // We can fallthru to the true
block.
+ cont.Negate();
+ cont.SwapBlocks();
+ }
+ VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
}
void InstructionSelector::VisitWord32Equal(Node* const node) {
- Node* const user = node;
FlagsContinuation cont(kEqual, node);
- Int32BinopMatcher m(user);
+ Int32BinopMatcher m(node);
if (m.right().Is(0)) {
- Node* const value = m.left().node();
- if (CanCover(user, value)) {
- switch (value->opcode()) {
- case IrOpcode::kInt32Sub:
- return VisitWordCompare(this, value, kIA32Cmp, &cont);
- case IrOpcode::kWord32And:
- return VisitWordCompare(this, value, kIA32Test, &cont);
- default:
- break;
- }
- }
+ return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
}
- VisitWordCompare(this, node, kIA32Cmp, &cont);
+ VisitWordCompare(this, node, &cont);
}
void InstructionSelector::VisitInt32LessThan(Node* node) {
FlagsContinuation cont(kSignedLessThan, node);
- VisitWordCompare(this, node, kIA32Cmp, &cont);
+ VisitWordCompare(this, node, &cont);
}
void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
FlagsContinuation cont(kSignedLessThanOrEqual, node);
- VisitWordCompare(this, node, kIA32Cmp, &cont);
+ VisitWordCompare(this, node, &cont);
}
void InstructionSelector::VisitUint32LessThan(Node* node) {
FlagsContinuation cont(kUnsignedLessThan, node);
- VisitWordCompare(this, node, kIA32Cmp, &cont);
+ VisitWordCompare(this, node, &cont);
}
void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
- VisitWordCompare(this, node, kIA32Cmp, &cont);
+ VisitWordCompare(this, node, &cont);
}
=======================================
--- /branches/bleeding_edge/src/compiler/instruction-selector.h Tue Oct 21
14:44:50 2014 UTC
+++ /branches/bleeding_edge/src/compiler/instruction-selector.h Thu Oct 23
10:22:06 2014 UTC
@@ -84,21 +84,11 @@
static Features SupportedFeatures() {
return Features(CpuFeatures::SupportedFeatures());
}
-
- // Checks if {node} is currently live.
- bool IsLive(Node* node) const { return !IsDefined(node) && IsUsed(node);
}
-
- private:
- friend class OperandGenerator;
//
===========================================================================
// ============ Architecture-independent graph covering methods.
=============
//
===========================================================================
- // Checks if {block} will appear directly after {current_block_} when
- // assembling code, in which case, a fall-through can be used.
- bool IsNextInAssemblyOrder(const BasicBlock* block) const;
-
// Used in pattern matching during code generation.
// Check if {node} can be covered while generating code for the current
// instruction. A node can be covered if the {user} of the node has the
only
@@ -109,13 +99,23 @@
// generated for it.
bool IsDefined(Node* node) const;
- // Inform the instruction selection that {node} was just defined.
- void MarkAsDefined(Node* node);
-
// Checks if {node} has any uses, and therefore code has to be generated
for
// it.
bool IsUsed(Node* node) const;
+ // Checks if {node} is currently live.
+ bool IsLive(Node* node) const { return !IsDefined(node) && IsUsed(node);
}
+
+ private:
+ friend class OperandGenerator;
+
+ // Checks if {block} will appear directly after {current_block_} when
+ // assembling code, in which case, a fall-through can be used.
+ bool IsNextInAssemblyOrder(const BasicBlock* block) const;
+
+ // Inform the instruction selection that {node} was just defined.
+ void MarkAsDefined(Node* node);
+
// Inform the instruction selection that {node} has at least one use and
we
// will need to generate code for it.
void MarkAsUsed(Node* node);
=======================================
--- /branches/bleeding_edge/src/compiler/machine-operator-reducer.cc Tue
Oct 21 12:24:01 2014 UTC
+++ /branches/bleeding_edge/src/compiler/machine-operator-reducer.cc Thu
Oct 23 10:22:06 2014 UTC
@@ -243,6 +243,21 @@
if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
break;
}
+ case IrOpcode::kWord64Equal: {
+ Int64BinopMatcher m(node);
+ if (m.IsFoldable()) { // K == K => K
+ return ReplaceBool(m.left().Value() == m.right().Value());
+ }
+ if (m.left().IsInt64Sub() && m.right().Is(0)) { // x - y == 0 => x
== y
+ Int64BinopMatcher msub(m.left().node());
+ node->ReplaceInput(0, msub.left().node());
+ node->ReplaceInput(1, msub.right().node());
+ return Changed(node);
+ }
+ // TODO(turbofan): fold HeapConstant, ExternalReference, pointer
compares
+ if (m.LeftEqualsRight()) return ReplaceBool(true); // x == x => true
+ break;
+ }
case IrOpcode::kInt32Add: {
Int32BinopMatcher m(node);
if (m.right().Is(0)) return Replace(m.left().node()); // x + 0 => x
=======================================
--- /branches/bleeding_edge/src/compiler/simplified-lowering.cc Wed Oct 22
11:24:55 2014 UTC
+++ /branches/bleeding_edge/src/compiler/simplified-lowering.cc Thu Oct 23
10:22:06 2014 UTC
@@ -456,8 +456,8 @@
if (lower()) {
MachineTypeUnion input = GetInfo(node->InputAt(0))->output;
if (input & kRepBit) {
- // BooleanNot(x: kRepBit) => WordEqual(x, #0)
- node->set_op(lowering->machine()->WordEqual());
+ // BooleanNot(x: kRepBit) => Word32Equal(x, #0)
+ node->set_op(lowering->machine()->Word32Equal());
node->AppendInput(jsgraph_->zone(),
jsgraph_->Int32Constant(0));
} else {
// BooleanNot(x: kRepTagged) => WordEqual(x, #false)
=======================================
--- /branches/bleeding_edge/src/compiler/typer.cc Mon Oct 20 07:56:50 2014
UTC
+++ /branches/bleeding_edge/src/compiler/typer.cc Thu Oct 23 10:22:06 2014
UTC
@@ -1044,7 +1044,7 @@
Bounds Typer::Visitor::TypeBooleanToNumber(Node* node) {
- return Bounds(Type::None(zone()), Type::Number(zone()));
+ return Bounds(Type::None(zone()), typer_->zero_or_one);
}
=======================================
--- /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
Tue Oct 21 10:59:55 2014 UTC
+++ /branches/bleeding_edge/src/compiler/x64/instruction-selector-x64.cc
Thu Oct 23 10:22:06 2014 UTC
@@ -819,6 +819,14 @@
node->op()->HasProperty(Operator::kCommutative));
}
}
+
+
+// Shared routine for comparison with zero.
+static void VisitCompareZero(InstructionSelector* selector, Node* node,
+ InstructionCode opcode, FlagsContinuation*
cont) {
+ X64OperandGenerator g(selector);
+ VisitCompare(selector, opcode, g.Use(node), g.TempImmediate(0), cont);
+}
// Shared routine for multiple float64 compare operations.
@@ -946,16 +954,30 @@
}
// Branch could not be combined with a compare, emit compare against 0.
- VisitCompare(this, kX64Cmp32, g.Use(value), g.TempImmediate(0), &cont);
+ VisitCompareZero(this, value, kX64Cmp32, &cont);
}
void InstructionSelector::VisitWord32Equal(Node* const node) {
- Node* const user = node;
+ Node* user = node;
FlagsContinuation cont(kEqual, node);
Int32BinopMatcher m(user);
if (m.right().Is(0)) {
- Node* const value = m.left().node();
+ Node* value = m.left().node();
+
+ // 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)) {
switch (value->opcode()) {
case IrOpcode::kInt32Sub:
@@ -966,6 +988,7 @@
break;
}
}
+ return VisitCompareZero(this, value, kX64Cmp32, &cont);
}
VisitWordCompare(this, node, kX64Cmp32, &cont);
}
@@ -996,11 +1019,25 @@
void InstructionSelector::VisitWord64Equal(Node* const node) {
- Node* const user = node;
+ Node* user = node;
FlagsContinuation cont(kEqual, node);
Int64BinopMatcher m(user);
if (m.right().Is(0)) {
- Node* const value = m.left().node();
+ Node* value = m.left().node();
+
+ // Try to combine with comparisons against 0 by simply inverting the
branch.
+ while (CanCover(user, value) && value->opcode() ==
IrOpcode::kWord64Equal) {
+ Int64BinopMatcher 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)) {
switch (value->opcode()) {
case IrOpcode::kInt64Sub:
@@ -1011,6 +1048,7 @@
break;
}
}
+ return VisitCompareZero(this, value, kX64Cmp, &cont);
}
VisitWordCompare(this, node, kX64Cmp, &cont);
}
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Wed
Oct 15 12:15:38 2014 UTC
+++ /branches/bleeding_edge/test/cctest/compiler/test-run-machops.cc Thu
Oct 23 10:22:06 2014 UTC
@@ -554,6 +554,142 @@
}
}
}
+
+
+TEST(RunInt32AddAndWord32EqualP) {
+ {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32,
kMachInt32);
+ m.Return(m.Int32Add(m.Parameter(0),
+ m.Word32Equal(m.Parameter(1), m.Parameter(2))));
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ FOR_INT32_INPUTS(k) {
+ // Use uint32_t because signed overflow is UB in C.
+ int32_t const expected =
+ bit_cast<int32_t>(bit_cast<uint32_t>(*i) + (*j == *k));
+ CHECK_EQ(expected, m.Call(*i, *j, *k));
+ }
+ }
+ }
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32,
kMachInt32);
+ m.Return(m.Int32Add(m.Word32Equal(m.Parameter(0), m.Parameter(1)),
+ m.Parameter(2)));
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ FOR_INT32_INPUTS(k) {
+ // Use uint32_t because signed overflow is UB in C.
+ int32_t const expected =
+ bit_cast<int32_t>((*i == *j) + bit_cast<uint32_t>(*k));
+ CHECK_EQ(expected, m.Call(*i, *j, *k));
+ }
+ }
+ }
+ }
+}
+
+
+TEST(RunInt32AddAndWord32EqualImm) {
+ {
+ FOR_INT32_INPUTS(i) {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ m.Return(m.Int32Add(m.Int32Constant(*i),
+ m.Word32Equal(m.Parameter(0), m.Parameter(1))));
+ FOR_INT32_INPUTS(j) {
+ FOR_INT32_INPUTS(k) {
+ // Use uint32_t because signed overflow is UB in C.
+ int32_t const expected =
+ bit_cast<int32_t>(bit_cast<uint32_t>(*i) + (*j == *k));
+ CHECK_EQ(expected, m.Call(*j, *k));
+ }
+ }
+ }
+ }
+ {
+ FOR_INT32_INPUTS(i) {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ m.Return(m.Int32Add(m.Word32Equal(m.Int32Constant(*i),
m.Parameter(0)),
+ m.Parameter(1)));
+ FOR_INT32_INPUTS(j) {
+ FOR_INT32_INPUTS(k) {
+ // Use uint32_t because signed overflow is UB in C.
+ int32_t const expected =
+ bit_cast<int32_t>((*i == *j) + bit_cast<uint32_t>(*k));
+ CHECK_EQ(expected, m.Call(*j, *k));
+ }
+ }
+ }
+ }
+}
+
+
+TEST(RunInt32AddAndWord32NotEqualP) {
+ {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32,
kMachInt32);
+ m.Return(m.Int32Add(m.Parameter(0),
+ m.Word32NotEqual(m.Parameter(1), m.Parameter(2))));
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ FOR_INT32_INPUTS(k) {
+ // Use uint32_t because signed overflow is UB in C.
+ int32_t const expected =
+ bit_cast<int32_t>(bit_cast<uint32_t>(*i) + (*j != *k));
+ CHECK_EQ(expected, m.Call(*i, *j, *k));
+ }
+ }
+ }
+ }
+ {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32,
kMachInt32);
+ m.Return(m.Int32Add(m.Word32NotEqual(m.Parameter(0), m.Parameter(1)),
+ m.Parameter(2)));
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ FOR_INT32_INPUTS(k) {
+ // Use uint32_t because signed overflow is UB in C.
+ int32_t const expected =
+ bit_cast<int32_t>((*i != *j) + bit_cast<uint32_t>(*k));
+ CHECK_EQ(expected, m.Call(*i, *j, *k));
+ }
+ }
+ }
+ }
+}
+
+
+TEST(RunInt32AddAndWord32NotEqualImm) {
+ {
+ FOR_INT32_INPUTS(i) {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ m.Return(m.Int32Add(m.Int32Constant(*i),
+ m.Word32NotEqual(m.Parameter(0),
m.Parameter(1))));
+ FOR_INT32_INPUTS(j) {
+ FOR_INT32_INPUTS(k) {
+ // Use uint32_t because signed overflow is UB in C.
+ int32_t const expected =
+ bit_cast<int32_t>(bit_cast<uint32_t>(*i) + (*j != *k));
+ CHECK_EQ(expected, m.Call(*j, *k));
+ }
+ }
+ }
+ }
+ {
+ FOR_INT32_INPUTS(i) {
+ RawMachineAssemblerTester<int32_t> m(kMachInt32, kMachInt32);
+ m.Return(m.Int32Add(m.Word32NotEqual(m.Int32Constant(*i),
m.Parameter(0)),
+ m.Parameter(1)));
+ FOR_INT32_INPUTS(j) {
+ FOR_INT32_INPUTS(k) {
+ // Use uint32_t because signed overflow is UB in C.
+ int32_t const expected =
+ bit_cast<int32_t>((*i != *j) + bit_cast<uint32_t>(*k));
+ CHECK_EQ(expected, m.Call(*j, *k));
+ }
+ }
+ }
+ }
+}
TEST(RunInt32AddAndWord32SarP) {
=======================================
---
/branches/bleeding_edge/test/cctest/compiler/test-simplified-lowering.cc
Wed Oct 15 11:38:04 2014 UTC
+++
/branches/bleeding_edge/test/cctest/compiler/test-simplified-lowering.cc
Thu Oct 23 10:22:06 2014 UTC
@@ -791,7 +791,7 @@
Node* use = t.Branch(inv);
t.Lower();
Node* cmp = use->InputAt(0);
- CHECK_EQ(t.machine()->WordEqual()->opcode(), cmp->opcode());
+ CHECK_EQ(t.machine()->Word32Equal()->opcode(), cmp->opcode());
CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
Node* f = t.jsgraph.Int32Constant(0);
CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
@@ -808,7 +808,7 @@
t.Lower();
CHECK_EQ(IrOpcode::kChangeBitToBool, use->InputAt(0)->opcode());
Node* cmp = use->InputAt(0)->InputAt(0);
- CHECK_EQ(t.machine()->WordEqual()->opcode(), cmp->opcode());
+ CHECK_EQ(t.machine()->Word32Equal()->opcode(), cmp->opcode());
CHECK(b == cmp->InputAt(0) || b == cmp->InputAt(1));
Node* f = t.jsgraph.Int32Constant(0);
CHECK(f == cmp->InputAt(0) || f == cmp->InputAt(1));
=======================================
---
/branches/bleeding_edge/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
Fri Oct 17 07:07:54 2014 UTC
+++
/branches/bleeding_edge/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
Thu Oct 23 10:22:06 2014 UTC
@@ -1369,6 +1369,113 @@
EXPECT_EQ(1U, s[0]->InputCount());
EXPECT_EQ(1U, s[0]->OutputCount());
}
+
+
+//
-----------------------------------------------------------------------------
+// Comparisons.
+
+
+namespace {
+
+struct Comparison {
+ Constructor constructor;
+ const char* constructor_name;
+ FlagsCondition flags_condition;
+ FlagsCondition negated_flags_condition;
+};
+
+
+std::ostream& operator<<(std::ostream& os, const Comparison& cmp) {
+ return os << cmp.constructor_name;
+}
+
+
+const Comparison kComparisons[] = {
+ {&RawMachineAssembler::Word32Equal, "Word32Equal", kEqual, kNotEqual},
+ {&RawMachineAssembler::Int32LessThan, "Int32LessThan", kSignedLessThan,
+ kSignedGreaterThanOrEqual},
+ {&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual",
+ kSignedLessThanOrEqual, kSignedGreaterThan},
+ {&RawMachineAssembler::Uint32LessThan, "Uint32LessThan",
kUnsignedLessThan,
+ kUnsignedGreaterThanOrEqual},
+ {&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual",
+ kUnsignedLessThanOrEqual, kUnsignedGreaterThan}};
+
+} // namespace
+
+
+typedef InstructionSelectorTestWithParam<Comparison>
+ InstructionSelectorComparisonTest;
+
+
+TEST_P(InstructionSelectorComparisonTest, Parameters) {
+ const Comparison& cmp = GetParam();
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const r = (m.*cmp.constructor)(p0, p1);
+ m.Return(r);
+ Stream const s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+ EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition());
+}
+
+
+TEST_P(InstructionSelectorComparisonTest, Word32EqualWithZero) {
+ {
+ const Comparison& cmp = GetParam();
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const r =
+ m.Word32Equal((m.*cmp.constructor)(p0, p1), m.Int32Constant(0));
+ m.Return(r);
+ Stream const s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+ EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
+ }
+ {
+ const Comparison& cmp = GetParam();
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32);
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ Node* const r =
+ m.Word32Equal(m.Int32Constant(0), (m.*cmp.constructor)(p0, p1));
+ m.Return(r);
+ Stream const s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmCmp, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
+ ASSERT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0)));
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode());
+ EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition());
+ }
+}
+
+
+INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
+ InstructionSelectorComparisonTest,
+ ::testing::ValuesIn(kComparisons));
//
-----------------------------------------------------------------------------
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.