From f9305f9ffaf8dd443369a156f7f7650de6372265 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 2 Oct 2013 14:41:35 +0200 Subject: V4: invert conditions when the true block follows the test. Change-Id: I5044acd4263b71734e4eb5d7e74b1a4a8414741e Reviewed-by: Lars Knoll --- src/3rdparty/masm/assembler/MacroAssembler.h | 2 +- src/3rdparty/masm/masm-defs.pri | 1 + src/qml/compiler/qv4instr_moth_p.h | 1 + src/qml/compiler/qv4isel_masm.cpp | 47 ++++++++++++++++++---------- src/qml/compiler/qv4isel_masm_p.h | 5 ++- src/qml/compiler/qv4isel_moth.cpp | 18 ++++++++--- src/qml/jsruntime/qv4vme_moth.cpp | 2 ++ 7 files changed, 52 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/3rdparty/masm/assembler/MacroAssembler.h b/src/3rdparty/masm/assembler/MacroAssembler.h index f74680d7fc..0c95bc7ca1 100644 --- a/src/3rdparty/masm/assembler/MacroAssembler.h +++ b/src/3rdparty/masm/assembler/MacroAssembler.h @@ -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) diff --git a/src/3rdparty/masm/masm-defs.pri b/src/3rdparty/masm/masm-defs.pri index 836ac0c796..ef9f79a42f 100644 --- a/src/3rdparty/masm/masm-defs.pri +++ b/src/3rdparty/masm/masm-defs.pri @@ -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__ diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index f8ccfff92f..3c28633491 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -438,6 +438,7 @@ union Instr MOTH_INSTR_HEADER ptrdiff_t offset; Param condition; + bool invert; }; struct instr_unop { MOTH_INSTR_HEADER diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp index 850dc64b99..5ee539648e 100644 --- a/src/qml/compiler/qv4isel_masm.cpp +++ b/src/qml/compiler/qv4isel_masm.cpp @@ -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; } diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h index a689cdf63e..8235e6e62c 100644 --- a/src/qml/compiler/qv4isel_masm_p.h +++ b/src/qml/compiler/qv4isel_masm_p.h @@ -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, diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index af914c79e7..4bea6322e6 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -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); + } } } diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index e933376a13..0807e6bad8 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -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) -- cgit v1.2.3