Bug 1331350 - Fuse BitAnd, Compare and Test into BitAndAndBranch r=jandem

MozReview-Commit-ID: 3EqbLbOywc9
This commit is contained in:
Sander Mathijs van Veen 2017-02-13 03:33:00 +01:00
parent 8ffcff7389
commit a9119dcaa8
6 changed files with 104 additions and 6 deletions

View File

@ -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);
}

View File

@ -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++;

View File

@ -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

View File

@ -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());
}

View File

@ -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

View File

@ -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