| Index: src/arm/lithium-arm.cc
|
| diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
|
| index c7b4382a8d710c026a96e24a6b4ebffdf43463e5..c46cc2164e3c318663139e8c613f9149ad1cacb5 100644
|
| --- a/src/arm/lithium-arm.cc
|
| +++ b/src/arm/lithium-arm.cc
|
| @@ -1362,16 +1362,23 @@ LInstruction* LChunkBuilder::DoMul(HMul* instr) {
|
| return DefineAsRegister(mul);
|
|
|
| } else if (instr->representation().IsDouble()) {
|
| - if (instr->UseCount() == 1 && 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
|
| - // into a multiply-add.
|
| + if (instr->UseCount() == 1 && (instr->uses().value()->IsAdd() ||
|
| + instr->uses().value()->IsSub())) {
|
| + HBinaryOperation* use = HBinaryOperation::cast(instr->uses().value());
|
| +
|
| + if (use->IsAdd() && instr == use->left()) {
|
| + // This mul is the lhs of an add. The add and mul will be folded into a
|
| + // multiply-add in DoAdd.
|
| return NULL;
|
| }
|
| - if (instr == add->right() && !add->left()->IsMul()) {
|
| + if (instr == use->right() && use->IsAdd() && !use->left()->IsMul()) {
|
| // This mul is the rhs of an add, where the lhs is not another mul.
|
| - // The add and mul will be folded into a multiply-add.
|
| + // The add and mul will be folded into a multiply-add in DoAdd.
|
| + return NULL;
|
| + }
|
| + if (instr == use->right() && use->IsSub()) {
|
| + // This mul is the rhs of a sub. The sub and mul will be folded into a
|
| + // multiply-sub in DoSub.
|
| return NULL;
|
| }
|
| }
|
| @@ -1402,6 +1409,10 @@ LInstruction* LChunkBuilder::DoSub(HSub* instr) {
|
| }
|
| return result;
|
| } else if (instr->representation().IsDouble()) {
|
| + if (instr->right()->IsMul()) {
|
| + return DoMultiplySub(instr->left(), HMul::cast(instr->right()));
|
| + }
|
| +
|
| return DoArithmeticD(Token::SUB, instr);
|
| } else {
|
| return DoArithmeticT(Token::SUB, instr);
|
| @@ -1435,6 +1446,18 @@ LInstruction* LChunkBuilder::DoMultiplyAdd(HMul* mul, HValue* addend) {
|
| multiplicand_op));
|
| }
|
|
|
| +
|
| +LInstruction* LChunkBuilder::DoMultiplySub(HValue* minuend, HMul* mul) {
|
| + LOperand* minuend_op = UseRegisterAtStart(minuend);
|
| + LOperand* multiplier_op = UseRegisterAtStart(mul->left());
|
| + LOperand* multiplicand_op = UseRegisterAtStart(mul->right());
|
| +
|
| + return DefineSameAsFirst(new(zone()) LMultiplySubD(minuend_op,
|
| + multiplier_op,
|
| + multiplicand_op));
|
| +}
|
| +
|
| +
|
| LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
| if (instr->representation().IsInteger32()) {
|
| ASSERT(instr->left()->representation().IsInteger32());
|
| @@ -1448,8 +1471,9 @@ LInstruction* LChunkBuilder::DoAdd(HAdd* instr) {
|
| }
|
| return result;
|
| } else if (instr->representation().IsDouble()) {
|
| - if (instr->left()->IsMul())
|
| + if (instr->left()->IsMul()) {
|
| return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
|
| + }
|
|
|
| if (instr->right()->IsMul()) {
|
| ASSERT(!instr->left()->IsMul());
|
|
|