Reviewers: ulan, jochen traveling until Jun 23,
Description:
ARM: Avoid duplicate vmla when merging vmul and vadd
Avoid generating duplicate vmla instructions for vmul/vadd sequences where
the
vmul has more than one use.
For example: function f(a, b, c) { return (a * b) + c + (a * b); }
Previously, this would produce a vmul for the subexpression (a * b), then
vmla
for (a * b) + c, then vmla for (a * b) + [(a * b) + c].
Now it produces vmul, vadd, vadd, as expected.
BUG=
Please review this at https://codereview.chromium.org/323423003/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files (+14, -11 lines):
M src/arm/lithium-arm.cc
M src/hydrogen-instructions.h
M src/hydrogen-instructions.cc
M src/mips/lithium-mips.cc
Index: src/arm/lithium-arm.cc
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index
93dc830dab30e3630bac62966133e5c35f3e8843..34cb1fcacc37cd9cb2e152c32e6b3ade77825e14
100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1500,8 +1500,8 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
return DefineAsRegister(mul);
} else if (instr->representation().IsDouble()) {
- if (instr->UseCount() == 1 && (instr->uses().value()->IsAdd() ||
- instr->uses().value()->IsSub())) {
+ if (instr->HasOneUse() && (instr->uses().value()->IsAdd() ||
+ instr->uses().value()->IsSub())) {
HBinaryOperation* use =
HBinaryOperation::cast(instr->uses().value());
if (use->IsAdd() && instr == use->left()) {
@@ -1547,7 +1547,7 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) {
}
return result;
} else if (instr->representation().IsDouble()) {
- if (instr->right()->IsMul()) {
+ if (instr->right()->IsMul() && instr->right()->HasOneUse()) {
return DoMultiplySub(instr->left(), HMul::cast(instr->right()));
}
@@ -1618,12 +1618,12 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
LInstruction* result = DefineAsRegister(add);
return result;
} else if (instr->representation().IsDouble()) {
- if (instr->left()->IsMul()) {
+ if (instr->left()->IsMul() && instr->left()->HasOneUse()) {
return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
}
- if (instr->right()->IsMul()) {
- ASSERT(!instr->left()->IsMul());
+ if (instr->right()->IsMul() && instr->right()->HasOneUse()) {
+ ASSERT(!instr->left()->IsMul() || !instr->left()->HasOneUse());
return DoMultiplyAdd(HMul::cast(instr->right()), instr->left());
}
Index: src/hydrogen-instructions.cc
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index
8b40a249d34372d793adad1c69c6496d82e5bd52..3cb0a5251ab7f56e97d84a3cef89baba57bbe4de
100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1581,7 +1581,7 @@ HValue* HUnaryMathOperation::Canonicalize() {
val, representation(), false, false));
}
}
- if (op() == kMathFloor && value()->IsDiv() && value()->UseCount() == 1) {
+ if (op() == kMathFloor && value()->IsDiv() && value()->HasOneUse()) {
HDiv* hdiv = HDiv::cast(value());
HValue* left = hdiv->left();
@@ -2149,7 +2149,7 @@ void
InductionVariableData::ChecksRelatedToLength::UseNewIndexInCurrentBlock(
added_index()->SetOperandAt(1, index_base);
added_index()->SetOperandAt(2, added_constant());
first_check_in_block()->SetOperandAt(0, added_index());
- if (previous_index->UseCount() == 0) {
+ if (previous_index->HasNoUses()) {
previous_index->DeleteAndReplaceWith(NULL);
}
}
@@ -2893,7 +2893,7 @@ bool HConstant::EmitAtUses() {
// TODO(titzer): this seems like a hack that should be fixed by custom
OSR.
return true;
}
- if (UseCount() == 0) return true;
+ if (HasNoUses()) return true;
if (IsCell()) return false;
if (representation().IsDouble()) return false;
if (representation().IsExternal()) return false;
Index: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index
f1720f444247d83635c84d00a99cf2457ee0022e..e85c0e7b48341be82afb844628a64ade6c122987
100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -663,6 +663,9 @@ class HValue : public ZoneObject {
void DeleteAndReplaceWith(HValue* other);
void ReplaceAllUsesWith(HValue* other);
bool HasNoUses() const { return use_list_ == NULL; }
+ bool HasOneUse() const {
+ return use_list_ != NULL && use_list_->tail() == NULL;
+ }
bool HasMultipleUses() const {
return use_list_ != NULL && use_list_->tail() != NULL;
}
@@ -3760,7 +3763,7 @@ class HBinaryOperation : public
HTemplateInstruction<3> {
// Otherwise, if there is only one use of the right operand, it would
be
// better off on the left for platforms that only have 2-arg arithmetic
// ops (e.g ia32, x64) that clobber the left operand.
- return right()->UseCount() == 1;
+ return right()->HasOneUse();
}
HValue* BetterLeftOperand() {
Index: src/mips/lithium-mips.cc
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index
830fc9152df8eb07031306fd4d354990012d5acb..180c07fdeec0805b7ee08f45d58cdbac6578f34f
100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -1492,7 +1492,7 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
} else if (instr->representation().IsDouble()) {
if (kArchVariant == kMips32r2) {
- if (instr->UseCount() == 1 && instr->uses().value()->IsAdd()) {
+ if (instr->HasOneUse() && instr->uses().value()->IsAdd()) {
HAdd* add = HAdd::cast(instr->uses().value());
if (instr == add->left()) {
// This mul is the lhs of an add. The add and mul will be folded
--
--
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.