From b4525b34074665ed472cd421077a1633110f16a7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 29 Dec 2011 22:44:16 -0200 Subject: Add configure-time checking for the SSE and AVX features on Windows Modify configure.exe to run some configure-time tests and check if the SSE and AVX compiler features are supported. The tests themselves required a bit of changes to compile with MSVC. The include in sse4_2.cpp was wrong. And for whatever reason, it didn't like the volatile variables, which GCC, Clang and ICC have been happy with. This should produce no effect in compilation, though: even dead code must be syntactically correct. We're not running the output. Change-Id: Ibe5d0904a378a7efed853c7215f88a2ddcefb1b3 Reviewed-by: Oswald Buddenhagen --- tools/configure/configureapp.cpp | 140 ++++++++++++++++++++++++++++++++++++++- tools/configure/configureapp.h | 2 + tools/configure/environment.cpp | 9 ++- tools/configure/environment.h | 2 +- 4 files changed, 146 insertions(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 5a24e9b266..84d759ba33 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -212,6 +212,12 @@ Configure::Configure(int& argc, char** argv) dictionary[ "WIDGETS" ] = "yes"; dictionary[ "RTTI" ] = "yes"; dictionary[ "SSE2" ] = "auto"; + dictionary[ "SSE3" ] = "auto"; + dictionary[ "SSSE3" ] = "auto"; + dictionary[ "SSE4_1" ] = "auto"; + dictionary[ "SSE4_2" ] = "auto"; + dictionary[ "AVX" ] = "auto"; + dictionary[ "AVX2" ] = "auto"; dictionary[ "IWMMXT" ] = "auto"; dictionary[ "SYNCQT" ] = "auto"; dictionary[ "CE_CRT" ] = "no"; @@ -808,6 +814,30 @@ void Configure::parseCmdLine() dictionary[ "SSE2" ] = "no"; else if (configCmdLine.at(i) == "-sse2") dictionary[ "SSE2" ] = "yes"; + else if (configCmdLine.at(i) == "-no-sse3") + dictionary[ "SSE3" ] = "no"; + else if (configCmdLine.at(i) == "-sse3") + dictionary[ "SSE3" ] = "yes"; + else if (configCmdLine.at(i) == "-no-ssse3") + dictionary[ "SSSE3" ] = "no"; + else if (configCmdLine.at(i) == "-ssse3") + dictionary[ "SSSE3" ] = "yes"; + else if (configCmdLine.at(i) == "-no-sse4.1") + dictionary[ "SSE4_1" ] = "no"; + else if (configCmdLine.at(i) == "-sse4.1") + dictionary[ "SSE4_1" ] = "yes"; + else if (configCmdLine.at(i) == "-no-sse4.2") + dictionary[ "SSE4_2" ] = "no"; + else if (configCmdLine.at(i) == "-sse4.2") + dictionary[ "SSE4_2" ] = "yes"; + else if (configCmdLine.at(i) == "-no-avx") + dictionary[ "AVX" ] = "no"; + else if (configCmdLine.at(i) == "-avx") + dictionary[ "AVX" ] = "yes"; + else if (configCmdLine.at(i) == "-no-avx2") + dictionary[ "AVX2" ] = "no"; + else if (configCmdLine.at(i) == "-avx2") + dictionary[ "AVX2" ] = "yes"; else if (configCmdLine.at(i) == "-no-iwmmxt") dictionary[ "IWMMXT" ] = "no"; else if (configCmdLine.at(i) == "-iwmmxt") @@ -1380,6 +1410,12 @@ void Configure::applySpecSpecifics() dictionary[ "OPENSSL" ] = "no"; dictionary[ "RTTI" ] = "no"; dictionary[ "SSE2" ] = "no"; + dictionary[ "SSE3" ] = "no"; + dictionary[ "SSSE3" ] = "no"; + dictionary[ "SSE4_1" ] = "no"; + dictionary[ "SSE4_2" ] = "no"; + dictionary[ "AVX" ] = "no"; + dictionary[ "AVX2" ] = "no"; dictionary[ "IWMMXT" ] = "no"; dictionary[ "CE_CRT" ] = "yes"; dictionary[ "DIRECTSHOW" ] = "no"; @@ -1468,7 +1504,10 @@ bool Configure::displayHelp() "[-qt-zlib] [-system-zlib] [-qt-pcre] [-system-pcre] [-no-gif]\n" "[-no-libpng] [-qt-libpng] [-system-libpng]\n" "[-no-libjpeg] [-qt-libjpeg] [-system-libjpeg]\n" - "[-sse2] [-no-sse2]\n" + "[-sse2] [-no-sse2] [-sse3] [-no-sse3]\n" + "[-ssse3] [-no-ssse3]\n" + "[-sse4.1] [-no-sse4.1] [-sse4.2] [-no-sse4.2]\n" + "[-avx] [-no-avx] [-avx2] [-no-avx2]\n" "[-no-iwmmxt] [-iwmmxt] [-openssl] [-openssl-linked]\n" "[-no-openssl] [-no-dbus] [-dbus] [-dbus-linked] [-platform ]\n" "[-qtnamespace ] [-qtlibinfix ] [-no-phonon]\n" @@ -1635,7 +1674,19 @@ bool Configure::displayHelp() desc("RTTI", "no", "-no-rtti", "Do not compile runtime type information."); desc("RTTI", "yes", "-rtti", "Compile runtime type information.\n"); desc("SSE2", "no", "-no-sse2", "Do not compile with use of SSE2 instructions"); - desc("SSE2", "yes", "-sse2", "Compile with use of SSE2 instructions"); + desc("SSE2", "yes", "-sse2", "Compile with use of SSE2 instructions"); + desc("SSE3", "no", "-no-sse3", "Do not compile with use of SSE3 instructions"); + desc("SSE3", "yes", "-sse3", "Compile with use of SSE3 instructions"); + desc("SSSE3", "no", "-no-ssse3", "Do not compile with use of SSSE3 instructions"); + desc("SSSE3", "yes", "-ssse3", "Compile with use of SSSE3 instructions"); + desc("SSE4_1", "no", "-no-sse4.1", "Do not compile with use of SSE4.1 instructions"); + desc("SSE4_1", "yes", "-sse4.1", "Compile with use of SSE4.1 instructions"); + desc("SSE4_2", "no", "-no-sse4.2", "Do not compile with use of SSE4.2 instructions"); + desc("SSE4_2", "yes", "-sse4.2", "Compile with use of SSE4.2 instructions"); + desc("AVX", "no", "-no-avx", "Do not compile with use of AVX instructions"); + desc("AVX", "yes", "-avx", "Compile with use of AVX instructions"); + desc("AVX2", "no", "-no-avx2", "Do not compile with use of AVX2 instructions"); + desc("AVX2", "yes", "-avx2", "Compile with use of AVX2 instructions"); desc("OPENSSL", "no", "-no-openssl", "Do not compile in OpenSSL support"); desc("OPENSSL", "yes", "-openssl", "Compile in run-time OpenSSL support"); desc("OPENSSL", "linked","-openssl-linked", "Compile in linked OpenSSL support"); @@ -1878,7 +1929,19 @@ bool Configure::checkAvailability(const QString &part) else if (part == "DIRECTSHOW") available = (dictionary.value("XQMAKESPEC").startsWith("wince")); else if (part == "SSE2") - available = (dictionary.value("QMAKESPEC") != "win32-msvc"); + available = tryCompileProject("common/sse2"); + else if (part == "SSE3") + available = tryCompileProject("common/sse3"); + else if (part == "SSSE3") + available = tryCompileProject("common/ssse3"); + else if (part == "SSE4_1") + available = tryCompileProject("common/sse4_1"); + else if (part == "SSE4_2") + available = tryCompileProject("common/sse4_2"); + else if (part == "AVX") + available = tryCompileProject("common/avx"); + else if (part == "AVX2") + available = tryCompileProject("common/avx2"); else if (part == "OPENSSL") available = findFile("openssl\\ssl.h"); else if (part == "DBUS") @@ -1989,6 +2052,18 @@ void Configure::autoDetection() dictionary["SQL_IBASE"] = checkAvailability("SQL_IBASE") ? defaultTo("SQL_IBASE") : "no"; if (dictionary["SSE2"] == "auto") dictionary["SSE2"] = checkAvailability("SSE2") ? "yes" : "no"; + if (dictionary["SSE3"] == "auto") + dictionary["SSE3"] = checkAvailability("SSE3") ? "yes" : "no"; + if (dictionary["SSSE3"] == "auto") + dictionary["SSSE3"] = checkAvailability("SSSE3") ? "yes" : "no"; + if (dictionary["SSE4_1"] == "auto") + dictionary["SSE4_1"] = checkAvailability("SSE4_1") ? "yes" : "no"; + if (dictionary["SSE4_2"] == "auto") + dictionary["SSE4_2"] = checkAvailability("SSE4_2") ? "yes" : "no"; + if (dictionary["AVX"] == "auto") + dictionary["AVX"] = checkAvailability("AVX") ? "yes" : "no"; + if (dictionary["AVX2"] == "auto") + dictionary["AVX2"] = checkAvailability("AVX2") ? "yes" : "no"; if (dictionary["IWMMXT"] == "auto") dictionary["IWMMXT"] = checkAvailability("IWMMXT") ? "yes" : "no"; if (dictionary["OPENSSL"] == "auto") @@ -2543,6 +2618,18 @@ void Configure::generateCachefile() moduleStream << "CONFIG += create_prl link_prl"; if (dictionary[ "SSE2" ] == "yes") moduleStream << " sse2"; + if (dictionary[ "SSE3" ] == "yes") + moduleStream << " sse3"; + if (dictionary[ "SSSE3" ] == "yes") + moduleStream << " ssse3"; + if (dictionary[ "SSE4_1" ] == "yes") + moduleStream << " sse4_1"; + if (dictionary[ "SSE4_2" ] == "yes") + moduleStream << " sse4_2"; + if (dictionary[ "AVX" ] == "yes") + moduleStream << " avx"; + if (dictionary[ "AVX2" ] == "yes") + moduleStream << " avx2"; if (dictionary[ "IWMMXT" ] == "yes") moduleStream << " iwmmxt"; moduleStream << endl; @@ -2665,6 +2752,47 @@ void Configure::detectArch() QDir::setCurrent(oldpwd); } +bool Configure::tryCompileProject(const QString &projectPath, const QString &extraOptions) +{ + QString oldpwd = QDir::currentPath(); + + QString newpwd = fixSeparators(QString("%1/config.tests/%2").arg(buildPath, projectPath)); + if (!QDir().exists(newpwd) && !QDir().mkpath(newpwd)) { + cout << "Failed to create directory " << qPrintable(newpwd) << endl; + dictionary["DONE"] = "error"; + return false; + } + if (!QDir::setCurrent(newpwd)) { + cout << "Failed to change working directory to " << qPrintable(newpwd) << endl; + dictionary["DONE"] = "error"; + return false; + } + + // run qmake + QString command = + fixSeparators(QString("%1/bin/qmake.exe %2/config.tests/%3 %4 2>&1") + .arg(buildPath, sourcePath, projectPath, extraOptions)); + int code = 0; + QString output = Environment::execute(command, &code); + //cout << output << endl; + + if (code == 0) { + // compile + command = dictionary[ "MAKE" ]; + if (command.contains("nmake")) + command += " /NOLOGO"; + command += " -s 2>&1"; + output = Environment::execute(command, &code); + //cout << output << endl; + + // clean up + Environment::execute(command + " distclean 2>&1"); + } + + QDir::setCurrent(oldpwd); + return code == 0; +} + void Configure::generateQConfigPri() { // Generate qconfig.pri @@ -3108,6 +3236,12 @@ void Configure::displayConfig() sout << "Accessibility support......." << dictionary[ "ACCESSIBILITY" ] << endl; sout << "RTTI support................" << dictionary[ "RTTI" ] << endl; sout << "SSE2 support................" << dictionary[ "SSE2" ] << endl; + sout << "SSE3 support................" << dictionary[ "SSE3" ] << endl; + sout << "SSSE3 support..............." << dictionary[ "SSSE3" ] << endl; + sout << "SSE4.1 support.............." << dictionary[ "SSE4_1" ] << endl; + sout << "SSE4.2 support.............." << dictionary[ "SSE4_2" ] << endl; + sout << "AVX support................." << dictionary[ "AVX" ] << endl; + sout << "AVX2 support................" << dictionary[ "AVX2" ] << endl; sout << "IWMMXT support.............." << dictionary[ "IWMMXT" ] << endl; sout << "OpenGL support.............." << dictionary[ "OPENGL" ] << endl; if (dictionary.value(QStringLiteral("OPENGL_ES_2")) == QStringLiteral("yes")) { diff --git a/tools/configure/configureapp.h b/tools/configure/configureapp.h index 4ac0736a2c..5aac227c9e 100644 --- a/tools/configure/configureapp.h +++ b/tools/configure/configureapp.h @@ -169,6 +169,8 @@ private: void saveCmdLine(); #endif + bool tryCompileProject(const QString &projectPath, const QString &extraOptions = QString()); + void desc(const char *description, int startingAt = 0, int wrapIndent = 0); void desc(const char *option, const char *description, bool skipIndent = false, char fillChar = '.'); void desc(const char *mark_option, const char *mark, const char *option, const char *description, char fillChar = '.'); diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp index 43cfc06599..0365340833 100644 --- a/tools/configure/environment.cpp +++ b/tools/configure/environment.cpp @@ -431,7 +431,7 @@ int Environment::execute(QStringList arguments, const QStringList &additionalEnv Taken from qmake's system() command. */ -QString Environment::execute(const QString &command) +QString Environment::execute(const QString &command, int *returnCode) { QString output; FILE *proc = _popen(command.toLatin1().constData(), "r"); @@ -443,8 +443,11 @@ QString Environment::execute(const QString &command) buff[read_in] = '\0'; output += buff; } - if (proc) - _pclose(proc); + if (proc) { + int r = _pclose(proc); + if (returnCode) + *returnCode = r; + } return output; } diff --git a/tools/configure/environment.h b/tools/configure/environment.h index 5075e9ae5b..979d538e8a 100644 --- a/tools/configure/environment.h +++ b/tools/configure/environment.h @@ -66,7 +66,7 @@ public: static bool detectExecutable(const QString &executable); static int execute(QStringList arguments, const QStringList &additionalEnv, const QStringList &removeEnv); - static QString execute(const QString &command); + static QString execute(const QString &command, int *returnCode = 0); static bool cpdir(const QString &srcDir, const QString &destDir, const QString &includeSrcDir = QString()); -- cgit v1.2.3