V4: disable type inference and loop peeling for the interpreter.
authorErik Verbruggen <erik.verbruggen@digia.com>
Fri, 22 Aug 2014 10:11:40 +0000 (12:11 +0200)
committerErik Verbruggen <erik.verbruggen@digia.com>
Tue, 26 Aug 2014 14:45:26 +0000 (16:45 +0200)
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>
src/qml/compiler/qqmltypecompiler.cpp
src/qml/compiler/qv4isel_moth.cpp
src/qml/compiler/qv4isel_p.cpp
src/qml/compiler/qv4isel_p.h
src/qml/compiler/qv4jsir.cpp
src/qml/compiler/qv4ssa.cpp
src/qml/compiler/qv4ssa_p.h

index b960f4b..90f775f 100644 (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);
     }
 
index a0a8948..40a4484 100644 (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();
index 9e15e45..f160954 100644 (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)
 {
index 7048b33..984e8ab 100644 (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;
index 53d0630..e23ca1d 100644 (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);
index 774d8fb..d67b88b 100644 (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) {
index 72f3eb3..21a5b03 100644 (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