Bug 895465 - IonMonkey: Optimize codegen for test(and(x, y)). r=mrosenberg

This commit is contained in:
Dan Gohman 2013-07-24 09:36:14 -07:00
parent 5d2089d328
commit c31a6471bc
11 changed files with 133 additions and 21 deletions

View File

@ -1666,6 +1666,33 @@ class LCompareVM : public LCallInstructionHelper<1, 2 * BOX_PIECES, 0>
}
};
class LBitAndAndBranch : public LControlInstructionHelper<2, 2, 0>
{
public:
LIR_HEADER(BitAndAndBranch)
LBitAndAndBranch(MBasicBlock *ifTrue, MBasicBlock *ifFalse)
{
setSuccessor(0, ifTrue);
setSuccessor(1, ifFalse);
}
MBasicBlock *ifTrue() const {
return getSuccessor(0);
}
MBasicBlock *ifFalse() const {
return getSuccessor(1);
}
const LAllocation *left() {
return getOperand(0);
}
const LAllocation *right() {
return getOperand(1);
}
MCompare *mir() {
return mir_->toCompare();
}
};
class LIsNullOrLikeUndefined : public LInstructionHelper<1, BOX_PIECES, 2>
{
public:

View File

@ -81,6 +81,7 @@
_(CompareV) \
_(CompareVAndBranch) \
_(CompareVM) \
_(BitAndAndBranch) \
_(IsNullOrLikeUndefined) \
_(IsNullOrLikeUndefinedAndBranch)\
_(EmulatesUndefined) \

View File

@ -518,6 +518,27 @@ ReorderComparison(JSOp op, MDefinition **lhsp, MDefinition **rhsp)
return op;
}
static void
ReorderCommutative(MDefinition **lhsp, MDefinition **rhsp)
{
MDefinition *lhs = *lhsp;
MDefinition *rhs = *rhsp;
// Ensure that if there is a constant, then it is in rhs.
// In addition, since clobbering binary operations clobber the left
// operand, prefer a non-constant lhs operand with no further uses.
if (rhs->isConstant())
return;
if (lhs->isConstant() ||
(rhs->defUseCount() == 1 && lhs->defUseCount() > 1))
{
*rhsp = lhs;
*lhsp = rhs;
}
}
bool
LIRGenerator::visitTest(MTest *test)
{
@ -672,6 +693,17 @@ LIRGenerator::visitTest(MTest *test)
}
}
// Check if the operand for this test is a bitand operation. If it is, we want
// to emit an LBitAndAndBranch rather than an LTest*AndBranch.
if (opd->isBitAnd() && opd->isEmittedAtUses()) {
MDefinition *lhs = opd->getOperand(0);
MDefinition *rhs = opd->getOperand(1);
if (lhs->type() == MIRType_Int32 && rhs->type() == MIRType_Int32) {
ReorderCommutative(&lhs, &rhs);
return lowerForBitAndAndBranch(new LBitAndAndBranch(ifTrue, ifFalse), test, lhs, rhs);
}
}
if (opd->type() == MIRType_Double)
return add(new LTestDAndBranch(useRegister(opd), ifTrue, ifFalse));
@ -846,27 +878,6 @@ LIRGenerator::visitCompare(MCompare *comp)
MOZ_ASSUME_UNREACHABLE("Unrecognized compare type.");
}
static void
ReorderCommutative(MDefinition **lhsp, MDefinition **rhsp)
{
MDefinition *lhs = *lhsp;
MDefinition *rhs = *rhsp;
// Ensure that if there is a constant, then it is in rhs.
// In addition, since clobbering binary operations clobber the left
// operand, prefer a non-constant lhs operand with no further uses.
if (rhs->isConstant())
return;
if (lhs->isConstant() ||
(rhs->defUseCount() == 1 && lhs->defUseCount() > 1))
{
*rhsp = lhs;
*lhsp = rhs;
}
}
bool
LIRGenerator::lowerBitOp(JSOp op, MInstruction *ins)
{
@ -926,9 +937,36 @@ LIRGenerator::visitBitNot(MBitNot *ins)
return assignSafepoint(lir, ins);
}
static bool
CanEmitBitAndAtUses(MInstruction *ins)
{
if (!ins->canEmitAtUses())
return false;
if (ins->getOperand(0)->type() != MIRType_Int32 || ins->getOperand(1)->type() != MIRType_Int32)
return false;
MUseDefIterator iter(ins);
if (!iter)
return false;
if (!iter.def()->isTest())
return false;
iter++;
return !iter;
}
bool
LIRGenerator::visitBitAnd(MBitAnd *ins)
{
// Sniff out if the output of this bitand is used only for a branching.
// If it is, then we will emit an LBitAndAndBranch instruction in place
// of this bitand and any test that uses this bitand. Thus, we can
// ignore this BitAnd.
if (CanEmitBitAndAtUses(ins))
return emitAtUses(ins);
return lowerBitOp(JSOP_BITAND, ins);
}

View File

@ -1449,6 +1449,17 @@ CodeGeneratorARM::visitCompareVAndBranch(LCompareVAndBranch *lir)
return true;
}
bool
CodeGeneratorARM::visitBitAndAndBranch(LBitAndAndBranch *baab)
{
if (baab->right()->isConstant())
masm.ma_tst(ToRegister(baab->left()), Imm32(ToInt32(baab->right())));
else
masm.ma_tst(ToRegister(baab->left()), ToRegister(baab->right()));
emitBranch(Assembler::NonZero, baab->ifTrue(), baab->ifFalse());
return true;
}
bool
CodeGeneratorARM::visitUInt32ToDouble(LUInt32ToDouble *lir)
{

View File

@ -95,6 +95,7 @@ class CodeGeneratorARM : public CodeGeneratorShared
virtual bool visitCompareBAndBranch(LCompareBAndBranch *lir);
virtual bool visitCompareV(LCompareV *lir);
virtual bool visitCompareVAndBranch(LCompareVAndBranch *lir);
virtual bool visitBitAndAndBranch(LBitAndAndBranch *baab);
virtual bool visitUInt32ToDouble(LUInt32ToDouble *lir);
virtual bool visitNotI(LNotI *ins);
virtual bool visitNotD(LNotD *ins);

View File

@ -185,6 +185,15 @@ LIRGeneratorARM::lowerForFPU(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir,
LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::DEFAULT));
}
bool
LIRGeneratorARM::lowerForBitAndAndBranch(LBitAndAndBranch *baab, MInstruction *mir,
MDefinition *lhs, MDefinition *rhs)
{
baab->setOperand(0, useRegister(lhs));
baab->setOperand(1, useRegisterOrConstant(rhs));
return add(baab, mir);
}
bool
LIRGeneratorARM::defineUntypedPhi(MPhi *phi, size_t lirIndex)
{

View File

@ -45,6 +45,8 @@ class LIRGeneratorARM : public LIRGeneratorShared
MDefinition *src);
bool lowerForFPU(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir,
MDefinition *lhs, MDefinition *rhs);
bool lowerForBitAndAndBranch(LBitAndAndBranch *baab, MInstruction *mir,
MDefinition *lhs, MDefinition *rhs);
bool lowerTruncateDToInt32(MTruncateToInt32 *ins);

View File

@ -128,6 +128,17 @@ CodeGeneratorX86Shared::visitTestDAndBranch(LTestDAndBranch *test)
return true;
}
bool
CodeGeneratorX86Shared::visitBitAndAndBranch(LBitAndAndBranch *baab)
{
if (baab->right()->isConstant())
masm.testl(ToRegister(baab->left()), Imm32(ToInt32(baab->right())));
else
masm.testl(ToRegister(baab->left()), ToRegister(baab->right()));
emitBranch(Assembler::NonZero, baab->ifTrue(), baab->ifFalse());
return true;
}
void
CodeGeneratorX86Shared::emitCompare(MCompare::CompareType type, const LAllocation *left, const LAllocation *right)
{

View File

@ -98,6 +98,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
virtual bool visitCompareAndBranch(LCompareAndBranch *comp);
virtual bool visitCompareD(LCompareD *comp);
virtual bool visitCompareDAndBranch(LCompareDAndBranch *comp);
virtual bool visitBitAndAndBranch(LBitAndAndBranch *baab);
virtual bool visitNotI(LNotI *comp);
virtual bool visitNotD(LNotD *comp);
virtual bool visitMathD(LMathD *math);

View File

@ -116,6 +116,15 @@ LIRGeneratorX86Shared::lowerForFPU(LInstructionHelper<1, 2, 0> *ins, MDefinition
return defineReuseInput(ins, mir, 0);
}
bool
LIRGeneratorX86Shared::lowerForBitAndAndBranch(LBitAndAndBranch *baab, MInstruction *mir,
MDefinition *lhs, MDefinition *rhs)
{
baab->setOperand(0, useRegister(lhs));
baab->setOperand(1, useRegisterOrConstant(rhs));
return add(baab, mir);
}
bool
LIRGeneratorX86Shared::lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs)
{

View File

@ -34,6 +34,8 @@ class LIRGeneratorX86Shared : public LIRGeneratorShared
MDefinition *rhs);
bool lowerForFPU(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir, MDefinition *lhs,
MDefinition *rhs);
bool lowerForBitAndAndBranch(LBitAndAndBranch *baab, MInstruction *mir,
MDefinition *lhs, MDefinition *rhs);
bool visitConstant(MConstant *ins);
bool visitAsmJSNeg(MAsmJSNeg *ins);
bool visitAsmJSUDiv(MAsmJSUDiv *ins);