From a9119dcaa86c2b4d020a687ac9be047d6fcb04bd Mon Sep 17 00:00:00 2001 From: Sander Mathijs van Veen Date: Mon, 13 Feb 2017 03:33:00 +0100 Subject: [PATCH] Bug 1331350 - Fuse BitAnd, Compare and Test into BitAndAndBranch r=jandem MozReview-Commit-ID: 3EqbLbOywc9 --- js/src/jit-test/tests/ion/bug1331350.js | 56 +++++++++++++++++++ js/src/jit/Lowering.cpp | 39 ++++++++++++- js/src/jit/arm/CodeGenerator-arm.cpp | 2 +- .../mips-shared/CodeGenerator-mips-shared.cpp | 2 +- js/src/jit/shared/LIR-shared.h | 9 ++- .../x86-shared/CodeGenerator-x86-shared.cpp | 2 +- 6 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 js/src/jit-test/tests/ion/bug1331350.js diff --git a/js/src/jit-test/tests/ion/bug1331350.js b/js/src/jit-test/tests/ion/bug1331350.js new file mode 100644 index 000000000000..ea83bfa4fe17 --- /dev/null +++ b/js/src/jit-test/tests/ion/bug1331350.js @@ -0,0 +1,56 @@ +// |jit-test| --ion-eager +function optimize(a, b) { + a = a | 0; + b = b | 0; + + if ((a & 3) === 0) { + a = a + 1 | 0 + } + + if ((a & 7) !== 0) { + a = a + 1 | 0 + } + + return a + b | 0 +} + +for (var i=0; i<20; i++) { + assertEq(optimize(4 | 0, 6 | 0), 12); + assertEq(optimize(7 | 0, 11 | 0), 19); +} + +function not_optimizable(a, b) { + a = a | 0; + b = b | 0; + + if ((a & 3) > 0) { + a = a + 1 | 0 + } + + if ((a & 3) >= 0) { + a = a + 1 | 0 + } + + if ((a & 7) < 0) { + a = a + 1 | 0 + } + + if ((a & 7) <= 0) { + a = a + 1 | 0 + } + + if ((b & 3) === 1) { + b = b + 1 | 0 + } + + if ((b & 7) !== 3) { + b = b + 1 | 0 + } + + return a + b | 0 +} + +for (var i=0; i<20; i++) { + assertEq(not_optimizable(4 | 0, 6 | 0), 12); + assertEq(not_optimizable(7 | 0, 11 | 0), 20); +} diff --git a/js/src/jit/Lowering.cpp b/js/src/jit/Lowering.cpp index b231331b6bf2..b21648972aa3 100644 --- a/js/src/jit/Lowering.cpp +++ b/js/src/jit/Lowering.cpp @@ -779,6 +779,40 @@ LIRGenerator::visitTest(MTest* test) return; } + if (opd->isCompare() && opd->isEmittedAtUses()) { + // Emit LBitAndBranch for cases like |if ((x & y) === 0)|. + MCompare* comp = opd->toCompare(); + if ((comp->isInt32Comparison() || + comp->compareType() == MCompare::Compare_UInt32) && + comp->getOperand(1)->isConstant() && + comp->getOperand(1)->toConstant()->isInt32(0) && + comp->getOperand(0)->isBitAnd() && + comp->getOperand(0)->isEmittedAtUses()) + { + MDefinition* bitAnd = opd->getOperand(0); + MDefinition* lhs = bitAnd->getOperand(0); + MDefinition* rhs = bitAnd->getOperand(1); + + Assembler::Condition cond = JSOpToCondition(comp->compareType(), + comp->jsop()); + + if (lhs->type() == MIRType::Int32 && rhs->type() == MIRType::Int32 && + (cond == Assembler::Equal || cond == Assembler::NotEqual)) + { + ReorderCommutative(&lhs, &rhs, test); + if (cond == Assembler::Equal) + cond = Assembler::Zero; + else if(cond == Assembler::NotEqual) + cond = Assembler::NonZero; + else + MOZ_ASSERT_UNREACHABLE("inequality operators cannot be folded"); + lowerForBitAndAndBranch(new(alloc()) LBitAndAndBranch(ifTrue, ifFalse, cond), + test, lhs, rhs); + return; + } + } + } + // Check if the operand for this test is a compare operation. If it is, we want // to emit an LCompare*AndBranch rather than an LTest*AndBranch, to fuse the // compare and jump instructions. @@ -1221,10 +1255,11 @@ CanEmitBitAndAtUses(MInstruction* ins) return false; MNode* node = iter->consumer(); - if (!node->isDefinition()) + if (!node->isDefinition() || !node->toDefinition()->isInstruction()) return false; - if (!node->toDefinition()->isTest()) + MInstruction* use = node->toDefinition()->toInstruction(); + if (!use->isTest() && !(use->isCompare() && CanEmitCompareAtUses(use))) return false; iter++; diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index 8adc044a8148..7864b6ab7273 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -1633,7 +1633,7 @@ CodeGeneratorARM::visitBitAndAndBranch(LBitAndAndBranch* baab) masm.ma_tst(ToRegister(baab->left()), Imm32(ToInt32(baab->right())), scratch); else masm.ma_tst(ToRegister(baab->left()), ToRegister(baab->right())); - emitBranch(Assembler::NonZero, baab->ifTrue(), baab->ifFalse()); + emitBranch(baab->cond(), baab->ifTrue(), baab->ifFalse()); } void diff --git a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp index 307cacf5b736..2df56581f2a6 100644 --- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp +++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp @@ -1736,7 +1736,7 @@ CodeGeneratorMIPSShared::visitBitAndAndBranch(LBitAndAndBranch* lir) masm.ma_and(ScratchRegister, ToRegister(lir->left()), Imm32(ToInt32(lir->right()))); else masm.as_and(ScratchRegister, ToRegister(lir->left()), ToRegister(lir->right())); - emitBranch(ScratchRegister, ScratchRegister, Assembler::NonZero, lir->ifTrue(), + emitBranch(ScratchRegister, ScratchRegister, lir->cond(), lir->ifTrue(), lir->ifFalse()); } diff --git a/js/src/jit/shared/LIR-shared.h b/js/src/jit/shared/LIR-shared.h index 3e1235f57019..d30ccae31f0c 100644 --- a/js/src/jit/shared/LIR-shared.h +++ b/js/src/jit/shared/LIR-shared.h @@ -2967,9 +2967,12 @@ class LCompareVM : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0> class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> { + Assembler::Condition cond_; public: LIR_HEADER(BitAndAndBranch) - LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse) + LBitAndAndBranch(MBasicBlock* ifTrue, MBasicBlock* ifFalse, + Assembler::Condition cond = Assembler::NonZero) + : cond_(cond) { setSuccessor(0, ifTrue); setSuccessor(1, ifFalse); @@ -2987,6 +2990,10 @@ class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0> const LAllocation* right() { return getOperand(1); } + Assembler::Condition cond() const { + MOZ_ASSERT(cond_ == Assembler::Zero || cond_ == Assembler::NonZero); + return cond_; + } }; // Takes a value and tests whether it is null, undefined, or is an object that diff --git a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp index 9cf03aedeb43..a0da371609b9 100644 --- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp @@ -141,7 +141,7 @@ CodeGeneratorX86Shared::visitBitAndAndBranch(LBitAndAndBranch* baab) masm.test32(ToRegister(baab->left()), Imm32(ToInt32(baab->right()))); else masm.test32(ToRegister(baab->left()), ToRegister(baab->right())); - emitBranch(Assembler::NonZero, baab->ifTrue(), baab->ifFalse()); + emitBranch(baab->cond(), baab->ifTrue(), baab->ifFalse()); } void