Revision: 9718
Author: [email protected]
Date: Thu Oct 20 03:26:45 2011
Log: Speed up comparison with a constant.
Improve optimized code for comparison of an int32 against a constant, or
comparison of two double constants. Contributed by m.m.capewell.
Original codereview is http://codereview.chromium.org/7489045/.
This cl is just created in order to commit the change.
BUG=
TEST=
Review URL: http://codereview.chromium.org/8352040
http://code.google.com/p/v8/source/detail?r=9718
Modified:
/branches/bleeding_edge/src/arm/lithium-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm/lithium-codegen-arm.h
/branches/bleeding_edge/src/assembler.cc
/branches/bleeding_edge/src/assembler.h
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h
/branches/bleeding_edge/src/ia32/lithium-ia32.cc
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
/branches/bleeding_edge/src/x64/lithium-codegen-x64.h
/branches/bleeding_edge/src/x64/lithium-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Wed Oct 19 05:10:18 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Thu Oct 20 03:26:45 2011
@@ -1425,8 +1425,8 @@
if (r.IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
- LOperand* left = UseRegisterAtStart(instr->left());
- LOperand* right = UseRegisterAtStart(instr->right());
+ LOperand* left = UseRegisterOrConstantAtStart(instr->left());
+ LOperand* right = UseRegisterOrConstantAtStart(instr->right());
return new LCmpIDAndBranch(left, right);
} else {
ASSERT(r.IsDouble());
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Wed Oct 19
05:10:18 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Oct 20
03:26:45 2011
@@ -408,6 +408,12 @@
value->Number());
return static_cast<int32_t>(value->Number());
}
+
+
+double LCodeGen::ToDouble(LConstantOperand* op) const {
+ Handle<Object> value = chunk_->LookupLiteral(op);
+ return value->Number();
+}
Operand LCodeGen::ToOperand(LOperand* op) {
@@ -1703,11 +1709,6 @@
}
return cond;
}
-
-
-void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
- __ cmp(ToRegister(left), ToRegister(right));
-}
void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
@@ -1715,20 +1716,39 @@
LOperand* right = instr->InputAt(1);
int false_block = chunk_->LookupDestination(instr->false_block_id());
int true_block = chunk_->LookupDestination(instr->true_block_id());
-
- if (instr->is_double()) {
- // Compare left and right as doubles and load the
- // resulting flags into the normal status register.
- __ VFPCompareAndSetFlags(ToDoubleRegister(left),
ToDoubleRegister(right));
- // If a NaN is involved, i.e. the result is unordered (V set),
- // jump to false block label.
- __ b(vs, chunk_->GetAssemblyLabel(false_block));
+ Condition cond = TokenToCondition(instr->op(), false);
+
+ if (left->IsConstantOperand() && right->IsConstantOperand()) {
+ // We can statically evaluate the comparison.
+ double left_val = ToDouble(LConstantOperand::cast(left));
+ double right_val = ToDouble(LConstantOperand::cast(right));
+ int next_block =
+ EvalComparison(instr->op(), left_val, right_val) ? true_block
+ : false_block;
+ EmitGoto(next_block);
} else {
- EmitCmpI(left, right);
- }
-
- Condition cc = TokenToCondition(instr->op(), instr->is_double());
- EmitBranch(true_block, false_block, cc);
+ if (instr->is_double()) {
+ // Compare left and right operands as doubles and load the
+ // resulting flags into the normal status register.
+ __ VFPCompareAndSetFlags(ToDoubleRegister(left),
ToDoubleRegister(right));
+ // If a NaN is involved, i.e. the result is unordered (V set),
+ // jump to false block label.
+ __ b(vs, chunk_->GetAssemblyLabel(false_block));
+ } else {
+ if (right->IsConstantOperand()) {
+ __ cmp(ToRegister(left),
+ Operand(ToInteger32(LConstantOperand::cast(right))));
+ } else if (left->IsConstantOperand()) {
+ __ cmp(ToRegister(right),
+ Operand(ToInteger32(LConstantOperand::cast(left))));
+ // We transposed the operands. Reverse the condition.
+ cond = ReverseCondition(cond);
+ } else {
+ __ cmp(ToRegister(left), ToRegister(right));
+ }
+ }
+ EmitBranch(true_block, false_block, cond);
+ }
}
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Tue Oct 18
08:07:42 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.h Thu Oct 20
03:26:45 2011
@@ -86,6 +86,7 @@
SwVfpRegister flt_scratch,
DoubleRegister dbl_scratch);
int ToInteger32(LConstantOperand* op) const;
+ double ToDouble(LConstantOperand* op) const;
Operand ToOperand(LOperand* op);
MemOperand ToMemOperand(LOperand* op) const;
// Returns a MemOperand pointing to the high word of a DoubleStackSlot.
@@ -263,7 +264,6 @@
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
void EmitBranch(int left_block, int right_block, Condition cc);
- void EmitCmpI(LOperand* left, LOperand* right);
void EmitNumberUntagD(Register input,
DoubleRegister result,
bool deoptimize_on_undefined,
=======================================
--- /branches/bleeding_edge/src/assembler.cc Tue Oct 4 02:07:50 2011
+++ /branches/bleeding_edge/src/assembler.cc Thu Oct 20 03:26:45 2011
@@ -1135,6 +1135,23 @@
if (x == y) return EQUAL;
return x < y ? LESS : GREATER;
}
+
+
+bool EvalComparison(Token::Value op, double op1, double op2) {
+ ASSERT(Token::IsCompareOp(op));
+ switch (op) {
+ case Token::EQ:
+ case Token::EQ_STRICT: return (op1 == op2);
+ case Token::NE: return (op1 != op2);
+ case Token::LT: return (op1 < op2);
+ case Token::GT: return (op1 > op2);
+ case Token::LTE: return (op1 <= op2);
+ case Token::GTE: return (op1 >= op2);
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
ExternalReference ExternalReference::double_fp_operation(
=======================================
--- /branches/bleeding_edge/src/assembler.h Wed Oct 12 08:43:41 2011
+++ /branches/bleeding_edge/src/assembler.h Thu Oct 20 03:26:45 2011
@@ -846,6 +846,8 @@
}
return num_bits_set;
}
+
+bool EvalComparison(Token::Value op, double op1, double op2);
// Computes pow(x, y) with the special cases in the spec for Math.pow.
double power_double_int(double x, int y);
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Wed Oct 19
05:10:18 2011
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Oct 20
03:26:45 2011
@@ -353,6 +353,12 @@
value->Number());
return static_cast<int32_t>(value->Number());
}
+
+
+double LCodeGen::ToDouble(LConstantOperand* op) const {
+ Handle<Object> value = chunk_->LookupLiteral(op);
+ return value->Number();
+}
Immediate LCodeGen::ToImmediate(LOperand* op) {
@@ -1572,15 +1578,6 @@
}
return cond;
}
-
-
-void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
- if (right->IsConstantOperand()) {
- __ cmp(ToOperand(left), ToImmediate(right));
- } else {
- __ cmp(ToRegister(left), ToOperand(right));
- }
-}
void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
@@ -1588,18 +1585,35 @@
LOperand* right = instr->InputAt(1);
int false_block = chunk_->LookupDestination(instr->false_block_id());
int true_block = chunk_->LookupDestination(instr->true_block_id());
-
- if (instr->is_double()) {
- // Don't base result on EFLAGS when a NaN is involved. Instead
- // jump to the false block.
- __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
- __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
+ Condition cc = TokenToCondition(instr->op(), instr->is_double());
+
+ if (left->IsConstantOperand() && right->IsConstantOperand()) {
+ // We can statically evaluate the comparison.
+ double left_val = ToDouble(LConstantOperand::cast(left));
+ double right_val = ToDouble(LConstantOperand::cast(right));
+ int next_block =
+ EvalComparison(instr->op(), left_val, right_val) ? true_block
+ : false_block;
+ EmitGoto(next_block);
} else {
- EmitCmpI(left, right);
- }
-
- Condition cc = TokenToCondition(instr->op(), instr->is_double());
- EmitBranch(true_block, false_block, cc);
+ if (instr->is_double()) {
+ // Don't base result on EFLAGS when a NaN is involved. Instead
+ // jump to the false block.
+ __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
+ __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
+ } else {
+ if (right->IsConstantOperand()) {
+ __ cmp(ToRegister(left), ToImmediate(right));
+ } else if (left->IsConstantOperand()) {
+ __ cmp(ToOperand(right), ToImmediate(left));
+ // We transposed the operands. Reverse the condition.
+ cc = ReverseCondition(cc);
+ } else {
+ __ cmp(ToRegister(left), ToOperand(right));
+ }
+ }
+ EmitBranch(true_block, false_block, cc);
+ }
}
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Fri Oct 14
00:45:18 2011
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.h Thu Oct 20
03:26:45 2011
@@ -227,6 +227,7 @@
Register ToRegister(int index) const;
XMMRegister ToDoubleRegister(int index) const;
int ToInteger32(LConstantOperand* op) const;
+ double ToDouble(LConstantOperand* op) const;
Operand BuildFastArrayOperand(LOperand* elements_pointer,
LOperand* key,
ElementsKind elements_kind,
@@ -261,7 +262,6 @@
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
void EmitBranch(int left_block, int right_block, Condition cc);
- void EmitCmpI(LOperand* left, LOperand* right);
void EmitNumberUntagD(Register input,
XMMRegister result,
bool deoptimize_on_undefined,
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Wed Oct 19 05:10:18
2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Thu Oct 20 03:26:45
2011
@@ -1456,15 +1456,22 @@
if (r.IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
- LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* left = UseRegisterOrConstantAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
return new LCmpIDAndBranch(left, right);
} else {
ASSERT(r.IsDouble());
ASSERT(instr->left()->representation().IsDouble());
ASSERT(instr->right()->representation().IsDouble());
- LOperand* left = UseRegisterAtStart(instr->left());
- LOperand* right = UseRegisterAtStart(instr->right());
+ LOperand* left;
+ LOperand* right;
+ if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
+ left = UseRegisterOrConstantAtStart(instr->left());
+ right = UseRegisterOrConstantAtStart(instr->right());
+ } else {
+ left = UseRegisterAtStart(instr->left());
+ right = UseRegisterAtStart(instr->right());
+ }
return new LCmpIDAndBranch(left, right);
}
}
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Wed Oct 19
05:10:18 2011
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Thu Oct 20
03:26:45 2011
@@ -372,6 +372,12 @@
value->Number());
return static_cast<int32_t>(value->Number());
}
+
+
+double LCodeGen::ToDouble(LConstantOperand* op) const {
+ Handle<Object> value = chunk_->LookupLiteral(op);
+ return value->Number();
+}
Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
@@ -1524,22 +1530,6 @@
}
return cond;
}
-
-
-void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) {
- if (right->IsConstantOperand()) {
- int32_t value = ToInteger32(LConstantOperand::cast(right));
- if (left->IsRegister()) {
- __ cmpl(ToRegister(left), Immediate(value));
- } else {
- __ cmpl(ToOperand(left), Immediate(value));
- }
- } else if (right->IsRegister()) {
- __ cmpl(ToRegister(left), ToRegister(right));
- } else {
- __ cmpl(ToRegister(left), ToOperand(right));
- }
-}
void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) {
@@ -1547,18 +1537,46 @@
LOperand* right = instr->InputAt(1);
int false_block = chunk_->LookupDestination(instr->false_block_id());
int true_block = chunk_->LookupDestination(instr->true_block_id());
-
- if (instr->is_double()) {
- // Don't base result on EFLAGS when a NaN is involved. Instead
- // jump to the false block.
- __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
- __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
+ Condition cc = TokenToCondition(instr->op(), instr->is_double());
+
+ if (left->IsConstantOperand() && right->IsConstantOperand()) {
+ // We can statically evaluate the comparison.
+ double left_val = ToDouble(LConstantOperand::cast(left));
+ double right_val = ToDouble(LConstantOperand::cast(right));
+ int next_block =
+ EvalComparison(instr->op(), left_val, right_val) ? true_block
+ : false_block;
+ EmitGoto(next_block);
} else {
- EmitCmpI(left, right);
- }
-
- Condition cc = TokenToCondition(instr->op(), instr->is_double());
- EmitBranch(true_block, false_block, cc);
+ if (instr->is_double()) {
+ // Don't base result on EFLAGS when a NaN is involved. Instead
+ // jump to the false block.
+ __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right));
+ __ j(parity_even, chunk_->GetAssemblyLabel(false_block));
+ } else {
+ int32_t value;
+ if (right->IsConstantOperand()) {
+ value = ToInteger32(LConstantOperand::cast(right));
+ __ cmpl(ToRegister(left), Immediate(value));
+ } else if (left->IsConstantOperand()) {
+ value = ToInteger32(LConstantOperand::cast(left));
+ if (right->IsRegister()) {
+ __ cmpl(ToRegister(right), Immediate(value));
+ } else {
+ __ cmpl(ToOperand(right), Immediate(value));
+ }
+ // We transposed the operands. Reverse the condition.
+ cc = ReverseCondition(cc);
+ } else {
+ if (right->IsRegister()) {
+ __ cmpl(ToRegister(left), ToRegister(right));
+ } else {
+ __ cmpl(ToRegister(left), ToOperand(right));
+ }
+ }
+ }
+ EmitBranch(true_block, false_block, cc);
+ }
}
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.h Tue Oct 18
08:07:42 2011
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.h Thu Oct 20
03:26:45 2011
@@ -77,6 +77,7 @@
XMMRegister ToDoubleRegister(LOperand* op) const;
bool IsInteger32Constant(LConstantOperand* op) const;
int ToInteger32(LConstantOperand* op) const;
+ double ToDouble(LConstantOperand* op) const;
bool IsTaggedConstant(LConstantOperand* op) const;
Handle<Object> ToHandle(LConstantOperand* op) const;
Operand ToOperand(LOperand* op) const;
@@ -250,7 +251,6 @@
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
void EmitBranch(int left_block, int right_block, Condition cc);
- void EmitCmpI(LOperand* left, LOperand* right);
void EmitNumberUntagD(Register input,
XMMRegister result,
bool deoptimize_on_undefined,
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Wed Oct 19 05:10:18 2011
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc Thu Oct 20 03:26:45 2011
@@ -1417,15 +1417,22 @@
if (r.IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
- LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* left = UseRegisterOrConstantAtStart(instr->left());
LOperand* right = UseOrConstantAtStart(instr->right());
return new LCmpIDAndBranch(left, right);
} else {
ASSERT(r.IsDouble());
ASSERT(instr->left()->representation().IsDouble());
ASSERT(instr->right()->representation().IsDouble());
- LOperand* left = UseRegisterAtStart(instr->left());
- LOperand* right = UseRegisterAtStart(instr->right());
+ LOperand* left;
+ LOperand* right;
+ if (instr->left()->IsConstant() && instr->right()->IsConstant()) {
+ left = UseRegisterOrConstantAtStart(instr->left());
+ right = UseRegisterOrConstantAtStart(instr->right());
+ } else {
+ left = UseRegisterAtStart(instr->left());
+ right = UseRegisterAtStart(instr->right());
+ }
return new LCmpIDAndBranch(left, right);
}
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev