V4: disable type inference and loop peeling for the interpreter.

Loop peeling is always disabled. Type inference is still enabled for
QML code, because of the static-type nature of the properties.

This speeds up crypto.js by 20%.

Change-Id: Ibf51cb36f8904d64df0793980d463451dfd361e2
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
Erik Verbruggen 2014-08-22 12:11:40 +02:00
parent 39286a50c3
commit b926452f6c
7 changed files with 39 additions and 21 deletions

View File

@ -218,6 +218,7 @@ bool QQmlTypeCompiler::compile()
QV4::ExecutionEngine *v4 = engine->v4engine();
QScopedPointer<QV4::EvalInstructionSelection> isel(v4->iselFactory->create(engine, v4->executableAllocator, &document->jsModule, &document->jsGenerator));
isel->setUseFastLookups(false);
isel->setUseTypeInference(true);
document->javaScriptCompilationUnit = isel->compile(/*generated unit data*/false);
}

View File

@ -321,7 +321,9 @@ InstructionSelection::InstructionSelection(QQmlEnginePrivate *qmlEngine, QV4::Ex
, _codeEnd(0)
, _currentStatement(0)
, compilationUnit(new CompilationUnit)
{}
{
setUseTypeInference(false);
}
InstructionSelection::~InstructionSelection()
{
@ -351,7 +353,7 @@ void InstructionSelection::run(int functionIndex)
qSwap(codeEnd, _codeEnd);
IR::Optimizer opt(_function);
opt.run(qmlEngine);
opt.run(qmlEngine, useTypeInference, /*peelLoops =*/ false);
if (opt.isInSSA()) {
static const bool doStackSlotAllocation =
qgetenv("QV4_NO_INTERPRETER_STACK_SLOT_ALLOCATION").isEmpty();

View File

@ -51,6 +51,7 @@ using namespace QV4::IR;
EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
: useFastLookups(true)
, useTypeInference(true)
, executableAllocator(execAllocator)
, irModule(module)
{

View File

@ -60,6 +60,7 @@ public:
QV4::CompiledData::CompilationUnit *compile(bool generateUnitData = true);
void setUseFastLookups(bool b) { useFastLookups = b; }
void setUseTypeInference(bool onoff) { useTypeInference = onoff; }
int registerString(const QString &str) { return jsGenerator->registerString(str); }
uint registerIndexedGetterLookup() { return jsGenerator->registerIndexedGetterLookup(); }
@ -76,6 +77,7 @@ protected:
virtual QV4::CompiledData::CompilationUnit *backendCompileStep() = 0;
bool useFastLookups;
bool useTypeInference;
QV4::ExecutableAllocator *executableAllocator;
QV4::Compiler::JSUnitGenerator *jsGenerator;
QScopedPointer<QV4::Compiler::JSUnitGenerator> ownJSGenerator;

View File

@ -989,6 +989,9 @@ void IRPrinter::print(BasicBlock *bb)
printBlockStart();
foreach (Stmt *s, currentBB->statements()) {
if (!s)
continue;
QByteArray str;
QBuffer buf(&str);
buf.open(QIODevice::WriteOnly);

View File

@ -1794,6 +1794,9 @@ public:
void reset()
{
worklist.assign(worklist.size(), false);
worklistSize = 0;
foreach (Stmt *s, stmts) {
if (!s)
continue;
@ -3934,6 +3937,7 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df)
// constant propagation:
if (Const *sourceConst = m->source->asConst()) {
Q_ASSERT(sourceConst->type != UnknownType);
replaceUses(targetTemp, sourceConst, W);
defUses.removeDef(*targetTemp);
W.remove(s);
@ -3998,7 +4002,8 @@ void optimizeSSA(StatementWorklist &W, DefUses &defUses, DominatorTree &df)
doneSomething = true;
break;
case OpUPlus:
constOperand->type = unop->type;
if (unop->type != UnknownType)
constOperand->type = unop->type;
doneSomething = true;
break;
case OpCompl:
@ -5057,7 +5062,7 @@ Optimizer::Optimizer(IR::Function *function)
, inSSA(false)
{}
void Optimizer::run(QQmlEnginePrivate *qmlEngine)
void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool peelLoops)
{
#if defined(SHOW_SSA)
qout << "##### NOW IN FUNCTION " << (function->name ? qPrintable(*function->name) : "anonymous!")
@ -5093,13 +5098,15 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine)
showMeTheCode(function);
// cfg2dot(function, loopDetection.allLoops());
QVector<LoopDetection::LoopInfo *> innerLoops = loopDetection.innermostLoops();
LoopPeeling(df).run(innerLoops);
if (peelLoops) {
QVector<LoopDetection::LoopInfo *> innerLoops = loopDetection.innermostLoops();
LoopPeeling(df).run(innerLoops);
// cfg2dot(function, loopDetection.allLoops());
showMeTheCode(function);
if (!innerLoops.isEmpty())
verifyImmediateDominators(df, function);
// cfg2dot(function, loopDetection.allLoops());
showMeTheCode(function);
if (!innerLoops.isEmpty())
verifyImmediateDominators(df, function);
}
}
verifyCFG(function);
@ -5123,18 +5130,20 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine)
StatementWorklist worklist(function);
// qout << "Running type inference..." << endl;
TypeInference(qmlEngine, defUses).run(worklist);
showMeTheCode(function);
if (doTypeInference) {
// qout << "Running type inference..." << endl;
TypeInference(qmlEngine, defUses).run(worklist);
showMeTheCode(function);
// qout << "Doing reverse inference..." << endl;
ReverseInference(defUses).run(function);
// showMeTheCode(function);
// qout << "Doing reverse inference..." << endl;
ReverseInference(defUses).run(function);
// showMeTheCode(function);
// qout << "Doing type propagation..." << endl;
TypePropagation(defUses).run(function, worklist);
// showMeTheCode(function);
verifyNoPointerSharing(function);
// qout << "Doing type propagation..." << endl;
TypePropagation(defUses).run(function, worklist);
// showMeTheCode(function);
verifyNoPointerSharing(function);
}
static bool doOpt = qgetenv("QV4_NO_OPT").isEmpty();
if (doOpt) {

View File

@ -207,7 +207,7 @@ class Q_QML_PRIVATE_EXPORT Optimizer
public:
Optimizer(Function *function);
void run(QQmlEnginePrivate *qmlEngine);
void run(QQmlEnginePrivate *qmlEngine, bool doTypeInference = true, bool peelLoops = true);
void convertOutOfSSA();
bool isInSSA() const