From 736a17f8f46a324221c15c73a1a22c02eb90e9e4 Mon Sep 17 00:00:00 2001 From: "rodolph.perfetta@arm.com" Date: Fri, 20 Jun 2014 11:26:17 +0000 Subject: [PATCH] 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= R=ulan@chromium.org Review URL: https://codereview.chromium.org/323423003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21899 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 12 ++++++------ src/hydrogen-instructions.cc | 6 +++--- src/hydrogen-instructions.h | 5 ++++- src/mips/lithium-mips.cc | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 18eb39a..2d2b31c 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()); } diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index dae7447..03b3502 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; diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index f1720f4..e85c0e7 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() { diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 4cf8a63..75c9e79 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 -- 2.7.4