V4: invert conditions when the true block follows the test.

Change-Id: I5044acd4263b71734e4eb5d7e74b1a4a8414741e
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Erik Verbruggen 2013-10-02 14:41:35 +02:00 committed by The Qt Project
parent c860d1399b
commit f9305f9ffa
7 changed files with 52 additions and 24 deletions

View File

@ -90,7 +90,7 @@ public:
static const double twoToThe32; // This is super useful for some double code.
// Utilities used by the DFG JIT.
#if ENABLE(DFG_JIT)
#if ENABLE(DFG_JIT) || ENABLE(DFG_JIT_UTILITY_METHODS)
using MacroAssemblerBase::invert;
static DoubleCondition invert(DoubleCondition cond)

View File

@ -20,6 +20,7 @@ win*: DEFINES += NOMINMAX
DEFINES += ENABLE_LLINT=0
DEFINES += ENABLE_DFG_JIT=0
DEFINES += ENABLE_DFG_JIT_UTILITY_METHODS=1
DEFINES += ENABLE_JIT_CONSTANT_BLINDING=0
DEFINES += ENABLE_ASSEMBLER=1
DEFINES += BUILDING_QT__

View File

@ -438,6 +438,7 @@ union Instr
MOTH_INSTR_HEADER
ptrdiff_t offset;
Param condition;
bool invert;
};
struct instr_unop {
MOTH_INSTR_HEADER

View File

@ -262,6 +262,19 @@ void Assembler::addPatch(DataLabelPtr patch, V4IR::BasicBlock *target)
_labelPatches[target].append(patch);
}
void Assembler::generateCJumpOnNonZero(RegisterID reg, V4IR::BasicBlock *currentBlock,
V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock)
{
if (trueBlock == _nextBlock) {
Jump target = branch32(Equal, reg, TrustedImm32(0));
addPatch(falseBlock, target);
} else {
Jump target = branch32(NotEqual, reg, TrustedImm32(0));
addPatch(trueBlock, target);
jumpToBlock(currentBlock, falseBlock);
}
}
Assembler::Pointer Assembler::loadTempAddress(RegisterID reg, V4IR::Temp *t)
{
int32_t offset = 0;
@ -1688,19 +1701,14 @@ void InstructionSelection::visitCJump(V4IR::CJump *s)
testBoolean.link(_as);
}
Assembler::Jump target = _as->branch32(Assembler::NotEqual, reg, Assembler::TrustedImm32(0));
_as->addPatch(s->iftrue, target);
_as->jumpToBlock(_block, s->iffalse);
_as->generateCJumpOnNonZero(reg, _block, s->iftrue, s->iffalse);
return;
} else if (V4IR::Const *c = s->cond->asConst()) {
// TODO: SSA optimization for constant condition evaluation should remove this.
// See also visitCJump() in RegAllocInfo.
generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_to_boolean,
Assembler::PointerToValue(c));
Assembler::Jump target = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
Assembler::TrustedImm32(0));
_as->addPatch(s->iftrue, target);
_as->jumpToBlock(_block, s->iffalse);
_as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, s->iftrue, s->iffalse);
return;
} else if (V4IR::Binop *b = s->cond->asBinop()) {
if (b->left->type == V4IR::DoubleType && b->right->type == V4IR::DoubleType
@ -1739,10 +1747,7 @@ void InstructionSelection::visitCJump(V4IR::CJump *s)
Assembler::PointerToValue(b->left),
Assembler::PointerToValue(b->right));
Assembler::Jump target = _as->branch32(Assembler::NotEqual, Assembler::ReturnValueRegister,
Assembler::TrustedImm32(0));
_as->addPatch(s->iftrue, target);
_as->jumpToBlock(_block, s->iffalse);
_as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, s->iftrue, s->iffalse);
return;
}
Q_UNREACHABLE();
@ -2045,7 +2050,7 @@ void InstructionSelection::doubleBinop(V4IR::AluOp oper, V4IR::Expr *leftSource,
break;
default: {
Q_ASSERT(target->type == V4IR::BoolType);
Assembler::Jump trueCase = branchDouble(oper, leftSource, rightSource);
Assembler::Jump trueCase = branchDouble(false, oper, leftSource, rightSource);
_as->storeBool(false, target);
Assembler::Jump done = _as->jump();
trueCase.link(_as);
@ -2058,8 +2063,8 @@ void InstructionSelection::doubleBinop(V4IR::AluOp oper, V4IR::Expr *leftSource,
_as->storeDouble(Assembler::FPGpr0, target);
}
Assembler::Jump InstructionSelection::branchDouble(V4IR::AluOp op, V4IR::Expr *left,
V4IR::Expr *right)
Assembler::Jump InstructionSelection::branchDouble(bool invertCondition, V4IR::AluOp op,
V4IR::Expr *left, V4IR::Expr *right)
{
Q_ASSERT(isPregOrConst(left));
Q_ASSERT(isPregOrConst(right));
@ -2078,6 +2083,9 @@ Assembler::Jump InstructionSelection::branchDouble(V4IR::AluOp op, V4IR::Expr *l
default:
Q_UNREACHABLE();
}
if (invertCondition)
cond = JSC::MacroAssembler::invert(cond);
return _as->branchDouble(cond, _as->toDoubleRegister(left), _as->toDoubleRegister(right));
}
@ -2087,9 +2095,14 @@ bool InstructionSelection::visitCJumpDouble(V4IR::AluOp op, V4IR::Expr *left, V4
if (!isPregOrConst(left) || !isPregOrConst(right))
return false;
Assembler::Jump target = branchDouble(op, left, right);
_as->addPatch(iftrue, target);
_as->jumpToBlock(_block, iffalse);
if (_as->nextBlock() == iftrue) {
Assembler::Jump target = branchDouble(true, op, left, right);
_as->addPatch(iffalse, target);
} else {
Assembler::Jump target = branchDouble(false, op, left, right);
_as->addPatch(iftrue, target);
_as->jumpToBlock(_block, iffalse);
}
return true;
}

View File

@ -446,10 +446,13 @@ public:
}
void registerBlock(V4IR::BasicBlock*, V4IR::BasicBlock *nextBlock);
V4IR::BasicBlock *nextBlock() const { return _nextBlock; }
void jumpToBlock(V4IR::BasicBlock* current, V4IR::BasicBlock *target);
void addPatch(V4IR::BasicBlock* targetBlock, Jump targetJump);
void addPatch(DataLabelPtr patch, Label target);
void addPatch(DataLabelPtr patch, V4IR::BasicBlock *target);
void generateCJumpOnNonZero(RegisterID reg, V4IR::BasicBlock *currentBlock,
V4IR::BasicBlock *trueBlock, V4IR::BasicBlock *falseBlock);
Pointer loadTempAddress(RegisterID reg, V4IR::Temp *t);
Pointer loadStringAddress(RegisterID reg, const QString &string);
@ -1441,7 +1444,7 @@ protected:
V4IR::Expr *rightSource, V4IR::Temp *target);
void doubleBinop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource,
V4IR::Temp *target);
Assembler::Jump branchDouble(V4IR::AluOp op, V4IR::Expr *left, V4IR::Expr *right);
Assembler::Jump branchDouble(bool invertCondition, V4IR::AluOp op, V4IR::Expr *left, V4IR::Expr *right);
bool visitCJumpDouble(V4IR::AluOp op, V4IR::Expr *left, V4IR::Expr *right,
V4IR::BasicBlock *iftrue, V4IR::BasicBlock *iffalse);
bool int32Binop(V4IR::AluOp oper, V4IR::Expr *leftSource, V4IR::Expr *rightSource,

View File

@ -651,14 +651,22 @@ void InstructionSelection::visitCJump(V4IR::CJump *s)
Instruction::CJump jump;
jump.offset = 0;
jump.condition = condition;
ptrdiff_t trueLoc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
_patches[s->iftrue].append(trueLoc);
if (s->iffalse != _nextBlock) {
Instruction::Jump jump;
jump.offset = 0;
if (s->iftrue == _nextBlock) {
jump.invert = true;
ptrdiff_t falseLoc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
_patches[s->iffalse].append(falseLoc);
} else {
jump.invert = false;
ptrdiff_t trueLoc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
_patches[s->iftrue].append(trueLoc);
if (s->iffalse != _nextBlock) {
Instruction::Jump jump;
jump.offset = 0;
ptrdiff_t falseLoc = addInstruction(jump) + (((const char *)&jump.offset) - ((const char *)&jump));
_patches[s->iffalse].append(falseLoc);
}
}
}

View File

@ -506,6 +506,8 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *&code,
MOTH_BEGIN_INSTR(CJump)
uint cond = __qmljs_to_boolean(VALUEPTR(instr.condition));
TRACE(condition, "%s", cond ? "TRUE" : "FALSE");
if (instr.invert)
cond = !cond;
if (cond)
code = ((uchar *)&instr.offset) + instr.offset;
MOTH_END_INSTR(CJump)